Saya minta maaf jika ini adalah pertanyaan yang benar-benar sangat mutakhir, tetapi saya ingin tahu apa praktik terbaik yang ada, dan sepertinya saya tidak dapat menemukan jawaban yang baik di Google.
Dalam Python, saya biasanya menggunakan kelas kosong sebagai wadah struktur data super-catchall (seperti file JSON), dan menambahkan atribut di sepanjang jalan:
class DataObj:
"Catch-all data object"
def __init__(self):
pass
def processData(inputs):
data = DataObj()
data.a = 1
data.b = "sym"
data.c = [2,5,2,1]
Ini memberi saya banyak fleksibilitas, karena objek kontainer pada dasarnya dapat menyimpan apa saja. Jadi jika persyaratan baru muncul, saya hanya akan menambahkannya sebagai atribut lain ke objek DataObj (yang saya berikan di kode saya).
Namun, baru-baru ini saya terkesan (oleh programmer FP) bahwa ini adalah praktik yang mengerikan, karena membuatnya sangat sulit untuk membaca kode. Kita harus melalui semua kode untuk mengetahui atribut apa yang sebenarnya dimiliki DataObj.
Pertanyaan : Bagaimana saya bisa menulis ulang ini untuk pemeliharaan yang lebih besar tanpa mengorbankan fleksibilitas?
Apakah ada ide dari pemrograman fungsional yang bisa saya adopsi?
Saya mencari praktik terbaik di luar sana.
Catatan : satu ide adalah untuk menginisialisasi kelas dengan semua atribut yang diharapkan akan ditemui, misalnya
class DataObj:
"Catch-all data object"
def __init__(self):
data.a = 0
data.b = ""
data.c = []
def processData(inputs):
data = DataObj()
data.a = 1
data.b = "sym"
data.c = [2,5,2,1]
Apakah ini ide yang bagus? Bagaimana jika saya tidak tahu atribut saya apriori?
Jawaban:
Kamu tidak. Fleksibilitas inilah yang menyebabkan masalah. Jika ada kode di mana saja dapat mengubah atribut apa yang dimiliki objek, rawatan sudah terpotong-potong. Idealnya, setiap kelas memiliki seperangkat atribut yang ditetapkan setelahnya
__init__
dan sama untuk setiap instance. Tidak selalu mungkin atau masuk akal, tetapi itu harus terjadi setiap kali Anda tidak memiliki alasan yang bagus untuk menghindarinya.Itu bukan ide yang bagus. Tentu, maka atributnya ada di sana, tetapi mungkin memiliki nilai palsu, atau bahkan valid yang menutupi kode yang tidak menetapkan nilai (atau salah eja).
AttributeError
menakutkan, tetapi mendapatkan hasil yang salah lebih buruk. Nilai default secara umum baik-baik saja, tetapi untuk memilih default yang masuk akal (dan memutuskan apa yang diperlukan), Anda perlu tahu untuk apa objek itu digunakan.Maka Anda kacau dalam hal apa pun dan harus menggunakan dict atau daftar alih-alih nama atribut hardcoding. Tapi saya mengerti maksud Anda "... pada saat itu saya menulis kelas wadah". Maka jawabannya adalah: "Anda dapat mengedit file berbaris, ya." Perlu atribut baru? Tambahkan atribut frigging ke kelas kontainer. Ada lebih banyak kode yang menggunakan kelas itu dan tidak perlu atribut itu? Pertimbangkan untuk membagi berbagai hal dalam dua kelas terpisah (gunakan mixin untuk tetap KERING), jadi jadikan opsional jika masuk akal.
Jika Anda takut menulis kelas wadah berulang: Terapkan metaprogramming secara bijaksana, atau gunakan
collections.namedtuple
jika Anda tidak perlu bermutasi anggota setelah pembuatan (teman-teman FP Anda akan senang).sumber
Anda selalu bisa menggunakan kelas Bunch Alex Martelli . Dalam kasus Anda:
Dengan begitu, setidaknya jelas bagi pembaca bahwa data hanyalah penyimpanan data yang bodoh dan orang dapat segera melihat nilai mana yang disimpan tanpa nama apa, karena semuanya terjadi dalam satu baris.
Dan ya, melakukan hal-hal seperti ini sebenarnya adalah ide yang bagus, kadang-kadang.
sumber
Saya mungkin akan menggunakan pendekatan kedua, mungkin menggunakan
None
untuk menunjukkan data yang tidak valid. Memang benar bahwa sulit untuk membaca / memelihara jika Anda menambahkan atribut nanti. Namun, informasi lebih lanjut tentang tujuan kelas / objek ini akan memberikan wawasan tentang mengapa ide pertama adalah desain yang buruk: di mana Anda akan memiliki kelas yang benar-benar kosong tanpa metode atau data default? Mengapa Anda tidak tahu atribut apa yang dimiliki kelas?Ada kemungkinan yang
processData
mungkin lebih baik sebagai metode (process_data
untuk mengikuti konvensi penamaan python), karena bertindak atas kelas. Diberikan contoh, sepertinya itu mungkin lebih baik sebagai struktur data (di manadict
mungkin cukup).Diberikan contoh nyata, Anda dapat mempertimbangkan membawa pertanyaan ke CodeReview , di mana mereka dapat membantu untuk memperbaiki kode.
sumber