Dalam setiap definisi kelas yang diberikan, saya telah melihat definisi metode yang diurutkan dalam berbagai cara: abjad, kronologis berdasarkan penggunaan yang paling umum, abjad dikelompokkan berdasarkan visibilitas, abjad dengan getter dan setter dikelompokkan bersama, dll. Ketika saya mulai menulis kelas baru, Saya cenderung mengetik semuanya, lalu menyusun ulang ketika saya selesai menulis seluruh kelas. Pada catatan itu, saya punya tiga pertanyaan:
- Apakah pesanan itu penting?
- Apakah ada pesanan "terbaik"?
- Saya kira tidak ada, jadi apa pro dan kontra dari strategi pemesanan yang berbeda?
code-quality
Johntron
sumber
sumber
Jawaban:
Dalam beberapa bahasa pemrograman, ketertiban memang penting karena Anda tidak dapat memanfaatkan berbagai hal sampai setelah dinyatakan. Tetapi kecuali itu, untuk sebagian besar bahasa itu tidak masalah bagi kompiler. Jadi, Anda tinggal membiarkannya menjadi masalah bagi manusia.
Kutipan favorit Martin Fowler saya adalah:
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
Jadi saya akan mengatakan bahwa pemesanan kelas Anda harus bergantung pada apa yang membuatnya mudah dipahami manusia.Saya pribadi lebih suka perawatan step-down yang diberikan Bob Martin dalam
Clean Code
bukunya. Variabel anggota di bagian atas kelas, lalu konstruktor, lalu semua metode lainnya. Dan Anda memesan metode untuk berdekatan dengan bagaimana mereka digunakan dalam kelas (daripada secara sewenang-wenang menempatkan semua publik kemudian pribadi kemudian dilindungi). Dia menyebutnya meminimalkan "jarak vertikal" atau sesuatu seperti itu (saat ini tidak ada buku tentang saya).Edit:
Ide dasar "jarak vertikal" adalah Anda ingin menghindari membuat orang melompat-lompat di sekitar kode sumber Anda hanya untuk memahaminya. Jika ada yang terkait, mereka harus lebih dekat bersama. Hal-hal yang tidak terkait dapat terpisah lebih jauh.
Bab 5 dari Kode Bersih (buku bagus, btw) membahas banyak detail tentang bagaimana Tn. Martin menyarankan kode pemesanan. Dia menyarankan bahwa membaca kode harus bekerja seperti membaca artikel surat kabar: detail tingkat tinggi didahulukan (di bagian atas) dan Anda mendapatkan lebih banyak detail saat membaca. Dia berkata, "Jika satu fungsi memanggil fungsi lainnya, fungsi itu harus ditutup secara vertikal, dan si penelepon harus berada di atas callee, jika memungkinkan." Selain itu, konsep terkait harus berdekatan.
Jadi, inilah contoh yang dibuat-buat yang buruk dalam banyak hal (desain OO yang buruk; tidak pernah menggunakan
double
uang) tetapi menggambarkan ide:Metode diperintahkan sehingga mereka dekat dengan yang memanggil mereka, bekerja turun dari atas. Jika kita meletakkan semua
private
metode di bawah inipublic
, maka Anda harus melakukan lebih banyak lagi untuk mengikuti alur program.getFirstName
dangetLastName
secara konseptual terkait (dangetEmployeeId
mungkin juga), sehingga mereka saling berdekatan. Kita bisa memindahkan semuanya ke bawah, tetapi kita tidak ingin melihatgetFirstName
di atas dangetLastName
di bawah.Semoga ini memberi Anda ide dasar. Jika Anda tertarik pada hal semacam ini, saya sangat merekomendasikan membaca
Clean Code
.sumber
calculateBonus()
datang sebelumisFullTimeEmployee()
dandidCompleteBonusObjectives()
?isFullTimeEmployee
dandidCompleteBonusObjectives
digunakan olehisEligibleForBonus
karena itu mereka harus dekat secara vertikal. Tapi Anda bisa berpotensicalculateBonus
naik untuk mendekatkannya ke tempat namanya. Sayangnya, karena Anda memiliki fungsi memanggil fungsi pada akhirnya Anda berakhir dengan masalah (seperti satu fungsi bersama yang dipanggil oleh beberapa orang lain) di mana tidak ada pemesanan yang sempurna. Kemudian terserah penilaian terbaik Anda. Saya merekomendasikan agar kelas dan fungsi tetap kecil untuk mengurangi masalah tersebut.Saya biasanya memesan metode saya berdasarkan hubungan dan urutan penggunaan.
Ambil kelas jaringan, saya akan mengelompokkan semua metode TCP bersama, lalu semua metode UDP bersama-sama. Di dalam TCP saya akan memiliki metode setup sebagai yang pertama, mungkin mengirim pesan yang diberikan kedua dan tutup tcp socket sebagai yang ketiga.
Jelas tidak semua kelas akan cocok dengan pola itu, tapi itu adalah alur kerja umum saya.
Saya melakukannya dengan cara itu untuk debugging lebih dari apa pun, ketika saya memiliki masalah dan saya ingin melompat ke metode, saya tidak berpikir bagaimana itu dieja, saya pikir apa yang bertanggung jawab untuk dan pergi ke bagian itu.
Cara ini khususnya masuk akal bagi pihak ketiga melihat / menggunakan kode Anda sebagai dikelompokkan bersama dan akan mengikuti urutan yang digunakan, sehingga kode yang mereka tulis dengan kelas Anda akan mengikuti struktur yang sama dengan kelas.
Mengenai apakah itu penting?
untuk keterbacaan, pasti.
selain itu tidak juga, hanya dalam kasus di mana bahasa tertentu Anda tidak dapat memanggil metode kecuali ditentukan di atas di mana disebut dll.
sumber
Idealnya, kelas Anda sangat kecil sehingga tidak masalah. Jika Anda hanya memiliki selusin metode, dan editor atau IDE Anda mendukung pelipatan, Anda tidak memiliki masalah, karena seluruh daftar metode cocok dalam 12 baris.
Kegagalan itu, perbedaan tingkat atas harus publik vs swasta. Daftarkan metode publik terlebih dahulu: inilah yang paling dicari orang, karena mereka menentukan cara kelas Anda berinteraksi dengan basis kode lainnya.
Kemudian, di dalam masing-masing ini, masuk akal untuk mengelompokkan metode berdasarkan fungsi: konstruktor dan destruktor dalam satu blok, pengambil / penyetel di blok lain, operator kelebihan beban, metode statis, dan sisanya dari kelompok itu. Dalam C ++, saya ingin tetap
operator=
dekat dengan konstruktor, karena itu terkait erat dengan copy constructor, dan juga karena saya ingin dapat dengan cepat mengetahui apakah semua (atau tidak ada) dari default ctor, copy ctor, operator = dan dtor ada.sumber
tl; dr
Hanya jika bahasa yang Anda gunakan memerlukan pemesanan khusus. Selain itu, pemesanan terserah Anda. Pilih sistem yang konsisten dan masuk akal, dan cobalah untuk tetap menggunakannya sebanyak mungkin.
Hanya jika bahasa yang Anda gunakan perlu memiliki fungsi yang ditentukan lebih awal dalam file daripada di mana ia dipanggil, seperti dalam contoh ini:
Anda akan mendapatkan kesalahan karena Anda menelepon
funcB()
sebelum menggunakannya. Saya pikir ini adalah masalah dalam PL / SQL dan mungkin di C juga, tetapi Anda dapat memiliki deklarasi maju seperti:Ini satu-satunya situasi yang bisa saya pikirkan di mana jika pemesanannya "salah", Anda bahkan tidak akan bisa mengkompilasi.
Jika tidak, Anda selalu dapat memesan ulang sesuka Anda. Anda bahkan dapat menulis alat untuk melakukannya untuk Anda (jika Anda tidak dapat menemukannya di sana).
Jika bahasa / lingkungan tidak memiliki persyaratan pemesanan, maka urutan "terbaik" adalah yang paling cocok untuk Anda . Bagi saya, saya suka memiliki semua getter / setter bersama, biasanya di awal kelas (tapi setelah konstruktor / initializers statis), dan kemudian metode pribadi, lalu dilindungi, lalu publik. Dalam setiap grup berbasis lingkup biasanya tidak ada pemesanan, meskipun metode kelebihan beban saya coba untuk tetap bersama, dalam urutan jumlah parameter. Saya juga mencoba menyatukan metode dengan fungsi terkait, meskipun kadang-kadang saya harus memecah pemesanan berbasis lingkup untuk melakukannya; dan kadang-kadang mencoba mempertahankan pemesanan berbasis-ruang-fungsi-kelompok istirahat. Dan IDE saya dapat memberi saya tampilan garis besar alfabet, jadi itu bagus juga. ;)
Beberapa bahasa, seperti C # memiliki kemampuan untuk mengelompokkan kode dalam "wilayah" yang tidak berpengaruh pada kompilasi tetapi mungkin membuatnya lebih mudah untuk menjaga fungsi terkait bersama, kemudian menyembunyikan / menampilkannya dengan IDE. Seperti yang ditunjukkan MainMa , ada beberapa yang menganggap ini sebagai praktik buruk. Saya telah melihat contoh yang baik dan buruk dari daerah yang digunakan dengan cara ini, jadi jika Anda akan melakukannya, berhati-hatilah.
sumber