Masalah
Saya sedang mengerjakan proyek Python yang kelas utamanya sedikit " God Object ". Ada begitu banyak atribut dan metode!
Saya ingin memperbaiki kelas.
Sejauh ini…
Untuk langkah pertama, saya ingin melakukan sesuatu yang relatif sederhana; tetapi ketika saya mencoba pendekatan yang paling mudah, itu memecahkan beberapa tes dan contoh yang ada.
Pada dasarnya, kelas memiliki daftar atribut yang sangat panjang — tetapi saya dapat dengan jelas melihat mereka dan berpikir, “5 atribut ini terkait ... 8 ini juga terkait… dan kemudian ada sisanya.”
getattr
Saya pada dasarnya hanya ingin mengelompokkan atribut terkait ke dalam kelas pembantu seperti dikt. Saya punya perasaan __getattr__
akan ideal untuk pekerjaan itu. Jadi saya memindahkan atribut ke kelas yang terpisah, dan, tentu saja, __getattr__
bekerja dengan sangat baik…
Pada awalnya .
Tetapi kemudian saya mencoba menjalankan salah satu contoh. Contoh subclass mencoba mengatur salah satu dari atribut ini secara langsung (di tingkat kelas ). Tetapi karena atribut tidak lagi "secara fisik terletak" di kelas induk, saya mendapat kesalahan mengatakan bahwa atribut tidak ada.
@Properti
Saya kemudian membaca tentang @property
dekorator. Tetapi kemudian saya juga membaca bahwa itu menciptakan masalah untuk subclass yang ingin dilakukan self.x = blah
ketika x
merupakan properti dari kelas induk.
Diinginkan
- Biarkan semua kode klien terus bekerja menggunakan
self.whatever
, bahkan jikawhatever
properti orangtua tidak "secara fisik terletak" di kelas (atau contoh) itu sendiri. - Kelompokkan atribut terkait ke dalam wadah mirip-dikt.
- Mengurangi kebisingan ekstrim dari kode di kelas utama.
Misalnya, saya tidak hanya ingin mengubah ini:
larry = 2
curly = 'abcd'
moe = self.doh()
Ke dalam ini:
larry = something_else('larry')
curly = something_else('curly')
moe = yet_another_thing.moe()
... karena itu masih berisik. Meskipun itu berhasil membuat atribut hanya menjadi sesuatu yang dapat mengelola data, yang asli memiliki 3 variabel dan versi tweak masih memiliki 3 variabel.
Namun, saya akan baik-baik saja dengan sesuatu seperti ini:
stooges = Stooges()
Dan jika pencarian self.larry
gagal, sesuatu akan memeriksa stooges
dan melihat apakah larry
ada. (Tetapi itu juga harus bekerja jika subclass mencoba melakukannya larry = 'blah'
di tingkat kelas.)
Ringkasan
- Ingin mengganti grup atribut terkait di kelas induk dengan satu atribut yang menyimpan semua data di tempat lain
- Ingin bekerja dengan kode klien yang ada yang menggunakan (misalnya)
larry = 'blah'
di tingkat kelas - Ingin terus mengizinkan subclass untuk memperluas, menimpa, dan memodifikasi atribut-atribut yang dire-refaktasi ini tanpa mengetahui ada yang berubah
Apakah ini mungkin? Atau saya menggonggong pohon yang salah?
sumber
Jawaban:
Setelah menulis dan kemudian refactored python "objek Tuhan", saya bersimpati. Apa yang saya lakukan adalah memecah objek asli menjadi beberapa bagian berdasarkan metode. Misalnya, aslinya tampak seperti kode semu ini:
Metode barang adalah "unit" mandiri. Saya memigrasikannya ke kelas baru yang instantiate aslinya. Ini mengeluarkan properti yang diperlukan juga. Beberapa hanya digunakan oleh sub kelas dan bisa bergerak lurus ke seberang. Yang lain dibagikan, dan dipindahkan ke kelas bersama.
"Objek Tuhan" membuat salinan baru dari kelas bersama saat start up, dan masing-masing sub kelas baru menerima pointer sebagai bagian dari metode init mereka. Misalnya, inilah versi mailer yang dilucuti:
Ini dibuat sekali dan dibagi antara kelas-kelas yang berbeda yang membutuhkan kemampuan pengiriman surat.
Jadi buat Anda, buat kelas
larry
dengan properti dan metode yang Anda butuhkan. Di mana-mana klien mengatakan untuklarry = blah
menggantinyalarryObj.larry = blah
. Ini memigrasi berbagai hal ke sub proyek tanpa merusak antarmuka saat ini.Satu-satunya hal yang harus dilakukan adalah mencari "unit kerja". Jika Anda akan mengubah bagian dari "Obyek Dewa" menjadi metode itu sendiri, lakukanlah . Tapi, letakkan metode di luar itu. Ini memaksa Anda untuk membuat antarmuka antar komponen.
Meletakkan landasan itu memungkinkan semua yang lain untuk mengikutinya. Misalnya, sepotong objek helper yang menunjukkan bagaimana ia berinteraksi dengan mailer:
Berkonsentrasilah pada unit kerja individu terkecil yang mungkin, dan pindahkan. Ini lebih mudah dilakukan, dan memungkinkan Anda bermain dengan pengaturan dengan cepat. Jangan melihat properti untuk memindahkan barang, mereka mendukung tugas yang dilakukan dengan mereka dalam banyak kasus. Apa pun yang tersisa setelah Anda berurusan dengan metode mungkin harus tetap di objek asli, karena itu adalah bagian dari keadaan bersama.
Tapi , objek baru sekarang harus menerima properti yang mereka butuhkan sebagai variabel init, bukan menyentuh properti objek pemanggil. Mereka kemudian mengembalikan nilai yang diperlukan, yang dapat digunakan oleh penelepon untuk memperbarui properti yang dibagikan sebagaimana diperlukan. Ini membantu decouple objek dan membuat sistem yang lebih kuat.
sumber