Baru-baru ini selama tinjauan kode saya menemukan kode, ditulis oleh seorang rekan baru, yang berisi pola dengan bau. Saya menduga bahwa keputusan kolega saya didasarkan pada aturan yang diusulkan oleh buku Kode Bersih yang terkenal (dan mungkin juga oleh buku-buku serupa lainnya).
Ini adalah pemahaman saya bahwa konstruktor kelas sepenuhnya bertanggung jawab atas pembuatan objek yang valid dan bahwa tugas utamanya adalah penugasan properti (pribadi) objek. Tentu saja dapat terjadi bahwa nilai properti opsional dapat ditetapkan dengan metode selain konstruktor kelas, tetapi situasi seperti itu agak jarang terjadi (walaupun tidak selalu salah, asalkan seluruh kelas mempertimbangkan sifat opsional properti tersebut). Ini penting, karena memungkinkan untuk memastikan bahwa objek selalu dalam keadaan valid.
Namun, dalam kode yang saya temui, sebagian besar nilai properti sebenarnya ditentukan oleh metode lain selain konstruktor. Nilai yang dihasilkan dari perhitungan ditugaskan ke properti yang akan digunakan dalam beberapa metode pribadi di seluruh kelas. Penulis tampaknya menggunakan properti kelas seolah-olah mereka adalah variabel global yang harus dapat diakses di seluruh kelas, alih-alih parameterisasi nilai-nilai ini ke fungsi yang membutuhkannya. Selain itu, metode kelas harus dipanggil dalam urutan tertentu, karena kelas tidak akan berbuat banyak sebaliknya.
Saya menduga bahwa kode ini telah terinspirasi oleh saran untuk menjaga metode tetap pendek (<= 5 baris kode), untuk menghindari daftar parameter besar (<3 parameter) dan bahwa konstruktor tidak boleh melakukan pekerjaan (seperti melakukan perhitungan semacam yang penting untuk validitas objek).
Sekarang tentu saja saya bisa membuat kasus terhadap pola ini jika saya bisa membuktikan bahwa semua jenis kesalahan yang tidak terdefinisi berpotensi muncul ketika metode tidak dipanggil dalam urutan tertentu. Namun, saya memperkirakan bahwa respons terhadap hal ini adalah menambahkan validasi yang memverifikasi bahwa properti harus disetel begitu metode dipanggil yang membutuhkan properti tersebut diatur.
Namun saya lebih suka mengusulkan untuk sepenuhnya mengubah kode, sehingga kelas menjadi cetak biru menjadi objek aktual, daripada serangkaian metode yang harus dipanggil (secara prosedural) dalam urutan tertentu.
Saya merasa bahwa kode yang saya temukan berbau. Bahkan, saya percaya ada perbedaan yang agak jelas tentang kapan harus menyimpan nilai di properti kelas dan kapan memasukkannya ke dalam parameter untuk metode yang berbeda untuk digunakan - Saya tidak benar-benar percaya mereka bisa menjadi alternatif satu sama lain . Saya mencari kata-kata untuk perbedaan ini.
sumber
Jawaban:
Sebagai seseorang yang telah membaca Kode Bersih dan menonton seri Clean Coders, berkali-kali, dan sering mengajar dan melatih orang lain dalam menulis kode pembersih, saya memang dapat memastikan bahwa pengamatan Anda benar - metrik yang Anda tunjukkan semuanya disebutkan dalam buku .
Namun, buku ini terus membuat poin lain yang juga harus diterapkan di samping pedoman yang Anda tunjukkan. Ini tampaknya diabaikan dalam kode yang Anda hadapi. Ini mungkin terjadi karena kolega Anda masih dalam tahap belajar, dalam hal ini, sebanyak yang diperlukan untuk menunjukkan bau kode mereka, ada baiknya untuk diingat bahwa mereka melakukannya dengan niat baik, belajar dan mencoba untuk menulis kode yang lebih baik.
Clean Code mengusulkan bahwa metode harus pendek, dengan sesedikit mungkin argumen. Tetapi di sepanjang pedoman itu, disarankan agar kita harus mengikuti prinsip-prinsip S OLID, meningkatkan kohesi dan mengurangi sambungan .
The S di tribun SOLID untuk Tanggung Jawab Single Prinsip, yang menyatakan bahwa sebuah objek harus bertanggung jawab untuk satu hal. "Hal" bukanlah istilah yang sangat tepat, sehingga deskripsi dari prinsip ini sangat bervariasi. Namun, Paman Bob, penulis Clean Code, juga adalah orang yang menciptakan prinsip ini, menggambarkannya sebagai: "Kumpulkan bersama hal-hal yang berubah karena alasan yang sama. Pisahkan hal-hal yang berubah karena alasan berbeda." Dia melanjutkan dengan mengatakan apa yang dia maksud dengan alasan untuk berubah di sini dan di sini(penjelasan yang lebih lama di sini akan terlalu banyak). Jika prinsip ini diterapkan pada kelas yang Anda hadapi, sangat mungkin bahwa potongan-potongan yang berurusan dengan perhitungan akan dipisahkan dari yang berhubungan dengan holding state, dengan membagi kelas menjadi dua atau lebih, tergantung pada berapa banyak alasan untuk mengubah perhitungan tersebut miliki.
Juga, kelas-kelas Clean haruslah kohesif , artinya sebagian besar metodenya menggunakan sebagian besar atributnya. Dengan demikian, kelas kohesif maksimal adalah kelas di mana semua metode menggunakan semua atributnya; sebagai contoh, dalam aplikasi grafis Anda mungkin memiliki
Vector
kelas dengan atributPoint a
danPoint b
, di mana satu-satunya metode yangscaleBy(double factor)
danprintTo(Canvas canvas)
, baik operasi pada kedua atribut. Sebaliknya, kelas kohesif minimal adalah satu di mana setiap atribut digunakan dalam satu metode saja, dan tidak pernah lebih dari satu atribut digunakan oleh masing-masing metode. Secara rata-rata, sebuah kelas menyajikan "kelompok" non-kohesif bagian kohesif - yaitu beberapa metode menggunakan atributa
,b
danc
, sementara sisanya menggunakanc
dand
- artinya jika kita membagi kelas menjadi dua, kita berakhir dengan dua objek kohesif.Akhirnya, kelas Bersih harus mengurangi kopling sebanyak mungkin. Meskipun ada banyak jenis sambungan yang perlu dibahas di sini, tampaknya kode yang ada sebagian besar menderita kopling sementara , di mana, seperti yang Anda tunjukkan, metode objek hanya akan berfungsi seperti yang diharapkan ketika mereka dipanggil dalam urutan yang benar. Dan seperti dua pedoman yang disebutkan di atas, solusi untuk ini biasanya melibatkan pemisahan kelas menjadi dua atau lebih, objek kohesif . Strategi pemisahan dalam kasus ini biasanya melibatkan pola seperti Builder atau Factory, dan dalam kasus yang sangat kompleks, State-Machines.
TL; DR: Pedoman Kode Bersih yang diikuti kolega Anda baik, tetapi hanya jika juga mengikuti prinsip, praktik, dan pola yang tersisa yang disebutkan oleh buku. The Clean versi "kelas" Anda melihat akan dibagi menjadi beberapa kelas, masing-masing dengan tanggung jawab tunggal, metode kohesif dan tidak ada kopling temporal. Ini adalah konteks di mana metode-metode kecil dan argumen yang tidak ada artinya masuk akal.
sumber
Ini biasanya bertanggung jawab untuk menempatkan objek ke dalam keadaan awal yang valid, ya; properti atau metode lain kemudian dapat mengubah negara ke negara lain yang valid.
Serta masalah dengan keterbacaan dan pemeliharaan yang Anda singgung, sepertinya ada beberapa tahap aliran data / transformasi yang terjadi di dalam kelas itu sendiri, yang dapat menunjukkan bahwa kelas tersebut melanggar prinsip tanggung jawab tunggal.
Mengikuti beberapa pedoman pengkodean sementara mengabaikan yang lain sering menyebabkan kode konyol. Jika kita ingin menghindari seorang konstruktor melakukan pekerjaan, misalnya, cara yang masuk akal biasanya adalah melakukan pekerjaan sebelum konstruksi dan meneruskan hasil pekerjaan itu ke konstruktor. (Satu argumen untuk pendekatan itu mungkin adalah bahwa Anda menghindari memberi kelas Anda dua tanggung jawab: pekerjaan inisialisasi, dan 'pekerjaan utamanya', apa pun itu.)
Dalam pengalaman saya, membuat kelas dan metode menjadi kecil jarang merupakan sesuatu yang harus saya ingat sebagai pertimbangan terpisah - lebih tepatnya, itu mengikuti secara alami dari tanggung jawab tunggal.
Anda mungkin benar untuk melakukannya. Tidak ada yang salah dengan menulis kode prosedur langsung; ada masalah dalam menyalahgunakan paradigma OO untuk menulis kode prosedural yang membingungkan.
Biasanya , Anda seharusnya tidak meletakkan nilai dalam bidang sebagai cara meneruskannya dari satu metode ke metode lainnya; nilai dalam bidang harus menjadi bagian yang bermakna dari keadaan suatu objek pada waktu tertentu. (Saya dapat memikirkan beberapa pengecualian yang valid, tetapi bukan yang metodenya bersifat publik atau di mana ada ketergantungan pesanan yang harus diketahui oleh pengguna kelas)
sumber
Anda kemungkinan besar mencerca pola yang salah di sini. Fungsi kecil dan arity rendah jarang bermasalah sendiri. Masalah sebenarnya di sini adalah kopling yang menyebabkan ketergantungan urutan antara fungsi, jadi cari cara untuk mengatasinya tanpa membuang manfaat dari fungsi kecil.
Kode berbicara lebih keras daripada kata-kata. Orang-orang menerima koreksi semacam ini jauh lebih baik jika Anda benar-benar dapat melakukan bagian dari refactoring dan menunjukkan peningkatan, mungkin sebagai latihan pemrograman pasangan. Ketika saya melakukan ini, saya sering merasa lebih sulit daripada yang saya kira untuk mendapatkan desain yang benar, menyeimbangkan semua kriteria.
sumber