Saya mengerti apa yang seharusnya dicapai oleh SOLID dan menggunakannya secara teratur dalam situasi di mana modularitas penting dan tujuannya jelas berguna. Namun, dua hal mencegah saya menerapkannya secara konsisten di basis kode saya:
Saya ingin menghindari abstraksi dini. Dalam pengalaman saya menggambar garis abstraksi tanpa kasus penggunaan konkret (jenis yang ada sekarang atau di masa mendatang) menyebabkan mereka ditarik di tempat yang salah. Ketika saya mencoba mengubah kode semacam itu, garis abstraksi menghalangi dan bukannya membantu. Oleh karena itu, saya cenderung melakukan kesalahan dengan tidak menggambar garis abstraksi sampai saya memiliki ide yang bagus tentang di mana mereka akan berguna.
Saya merasa sulit untuk membenarkan peningkatan modularitas untuk kepentingannya sendiri jika itu membuat kode saya lebih bertele-tele, lebih sulit untuk dipahami, dll. Dan tidak menghilangkan duplikasi. Saya menemukan kode objek prosedural atau objek Tuhan yang sederhana, berpasangan ketat terkadang lebih mudah dipahami daripada kode ravioli yang sangat diperhitungkan dengan baik karena alirannya sederhana dan linier. Ini juga jauh lebih mudah untuk ditulis.
Di sisi lain, pola pikir ini sering mengarah pada objek-objek Tuhan. Saya biasanya memperbaiki ini secara konservatif, menambahkan garis abstraksi yang jelas hanya ketika saya melihat pola yang jelas muncul. Apa, jika ada, yang salah dengan objek-objek Tuhan dan kode yang digabungkan secara ketat jika Anda tidak jelas membutuhkan lebih banyak modularitas, tidak memiliki duplikasi yang signifikan dan kode tersebut dapat dibaca?
EDIT: Sejauh prinsip-prinsip SOLID individu, saya bermaksud untuk menekankan bahwa Pergantian Liskov adalah IMHO formalisasi akal sehat dan harus diterapkan di mana-mana, karena abstraksi tidak masuk akal jika tidak. Selain itu, setiap kelas harus memiliki tanggung jawab tunggal pada tingkat abstraksi tertentu, meskipun itu mungkin tingkat yang sangat tinggi dengan rincian implementasi semuanya dijejalkan ke dalam satu kelas 2.000 garis besar. Pada dasarnya, abstraksi Anda harus masuk akal di mana Anda memilih untuk abstrak. Prinsip-prinsip yang saya pertanyakan dalam kasus-kasus di mana modularitas tidak jelas berguna adalah open-closed, pemisahan antarmuka dan terutama inversi dependensi, karena ini adalah tentang modularitas, bukan hanya memiliki abstraksi yang masuk akal.
sumber
Jawaban:
Berikut ini adalah prinsip sederhana yang dapat Anda terapkan untuk membantu Anda memahami bagaimana menyeimbangkan desain sistem Anda:
S
dalam SOLID. Anda dapat memiliki objek yang sangat besar dalam hal jumlah metode atau jumlah data dan tetap menjunjung tinggi prinsip ini. Ambil contoh objek Ruby String. Objek ini memiliki lebih banyak metode daripada yang bisa Anda goyang, tetapi masih hanya memiliki satu tanggung jawab: memegang string teks untuk aplikasi. Segera setelah objek Anda mulai mengambil tanggung jawab baru, mulailah berpikir keras tentang itu. Masalah pemeliharaan bertanya pada diri sendiri "di mana saya akan menemukan kode ini jika saya memiliki masalah dengan itu nanti?"Intinya Anda mencoba melakukan apa yang Anda bisa untuk tidak menembak diri sendiri ketika tiba saatnya untuk memelihara perangkat lunak. Jika objek besar Anda adalah abstraksi yang masuk akal, maka ada sedikit alasan untuk membaginya hanya karena seseorang datang dengan metrik yang mengatakan kelas tidak boleh lebih dari X lines / methods / properties / etc. Jika ada, itu adalah pedoman dan bukan aturan yang keras dan cepat.
sumber
Saya pikir sebagian besar Anda telah menjawab pertanyaan Anda sendiri. SOLID adalah seperangkat pedoman tentang cara memperbaiki kode Anda, ketika konsep perlu ditingkatkan tingkat abstraksinya.
Seperti semua disiplin kreatif lainnya, tidak ada yang absolut - hanya pertukaran. Semakin Anda melakukannya, semakin mudah untuk memutuskan kapan cukup untuk domain atau persyaratan masalah Anda saat ini.
Setelah mengatakan bahwa - abstrak adalah jantung dari pengembangan perangkat lunak - jadi jika tidak ada alasan untuk tidak melakukannya, maka latihan akan membuat Anda lebih baik, dan Anda akan mendapatkan firasat untuk pengorbanan. Jadi nikmatilah kecuali itu menjadi merugikan.
sumber
Ini sebagian benar dan sebagian salah.
Salah
Ini bukan alasan untuk mencegah seseorang menerapkan prinsip-prinsip OO / SOLID. Itu hanya mencegah penerapannya terlalu dini.
Yang mana...
Kanan.
Jangan refactor kode sampai kode tersebut dapat digunakan kembali; ketika itu persyaratan lengkap. Atau, ketika "kasus penggunaan" semua ada di sana seperti yang Anda katakan.
Ketika bekerja sendirian atau dalam silo
Masalah dengan tidak melakukan OO tidak segera jelas. Setelah Anda menulis versi pertama dari suatu program:
3/4 dari hal-hal baik ini dengan cepat mati dalam waktu singkat.
Akhirnya, Anda mengenali bahwa Anda memiliki objek-objek Tuhan (Objek dengan banyak fungsi), sehingga Anda mengenali fungsi-fungsi individual. Merangkum. Masukkan ke dalam folder. Gunakan antarmuka sesekali. Bantulah diri Anda sendiri untuk pemeliharaan jangka panjang. Terutama karena metode non-refactored cenderung menggembung tanpa batas dan menjadi metode Tuhan.
Dalam sebuah tim
Masalah dengan tidak melakukan OO segera terlihat. Kode OO yang baik setidaknya mendokumentasikan dan dibaca sendiri. Apalagi bila dikombinasikan dengan kode hijau yang baik. Juga, kurangnya struktur membuatnya sulit untuk memisahkan tugas dan integrasi menjadi jauh lebih kompleks.
sumber
Tidak ada yang salah dengan objek besar dan kode yang digabungkan dengan ketat ketika mereka sesuai dan ketika tidak ada rekayasa yang lebih baik diperlukan . Ini hanyalah manifestasi lain dari aturan praktis yang berubah menjadi dogma.
Kopling longgar dan benda kecil dan sederhana cenderung memberikan manfaat spesifik dalam banyak kasus umum, jadi itu ide yang baik untuk menggunakannya, secara umum. Masalahnya terletak pada orang-orang yang tidak memahami alasan di balik prinsip-prinsip yang secara membabi buta mencoba menerapkannya secara universal, bahkan ketika mereka tidak menerapkannya.
sumber
Saya cenderung lebih mendekati ini dari sudut pandang You Are't Gonna Need It. Posting ini akan fokus pada satu item khususnya: warisan.
Dalam desain awal saya, saya membuat hierarki hal yang saya tahu akan ada dua atau lebih. Kemungkinannya adalah mereka akan membutuhkan banyak kode yang sama, jadi ada baiknya merancang itu sejak awal. Setelah kode awal tersedia , dan saya perlu menambahkan lebih banyak fitur / fungsi, saya melihat apa yang saya miliki dan berpikir, "Apakah sesuatu yang sudah saya terapkan memiliki fungsi yang sama atau mirip?" Jika demikian, kemungkinan besar abstraksi baru yang meminta untuk dirilis.
Contoh yang baik dari hal ini adalah kerangka kerja MVC. Mulai dari awal, Anda membuat satu halaman besar dengan kode di belakang. Tetapi kemudian Anda ingin menambahkan halaman lain. Namun, satu kode di belakang sudah mengimplementasikan banyak logika yang dibutuhkan halaman baru. Jadi, Anda abstrak keluar
Controller
kelas / antarmuka yang akan menerapkan logika khusus untuk halaman itu, meninggalkan hal-hal umum di kode "dewa" asli di belakang.sumber
Jika ANDA tahu sebagai pengembang kapan TIDAK menerapkan prinsip karena masa depan kode, maka itu baik untuk Anda.
Saya berharap SOLID tetap di belakang pikiran Anda untuk mengetahui kapan hal-hal perlu diabstraksikan untuk menghindari kerumitan dan meningkatkan kualitas kode jika mulai menurunkan nilai-nilai yang Anda nyatakan.
Lebih penting lagi, pertimbangkan bahwa sebagian besar pengembang melakukan pekerjaan harian dan tidak peduli sebanyak Anda. Jika Anda awalnya menetapkan metode jangka panjang, apa yang dipikirkan pengembang lain yang masuk ke kode ketika mereka datang untuk mempertahankannya atau memperpanjangnya? ... Ya, Anda dapat menebaknya, fungsi LEBIH BESAR, kelas berjalan LEBIH LAMA, kelas berjalan LEBIH LAMA, dan LEBIH BANYAK objek dewa, dan mereka tidak memiliki prinsip dalam pikiran untuk dapat menangkap kode tumbuh dan merangkumnya dengan benar. Kode Anda "dapat dibaca" sekarang menjadi berantakan.
Jadi, Anda mungkin berpendapat bahwa pengembang yang buruk akan melakukan itu terlepas dari apa pun, tetapi setidaknya Anda memiliki keuntungan yang lebih baik jika semuanya tetap sederhana dan terorganisir dengan baik sejak awal.
Saya tidak terlalu keberatan dengan "Peta Registri" global atau "Objek Dewa" jika itu sederhana. Itu benar-benar tergantung pada desain sistem, kadang-kadang Anda bisa lolos dan tetap sederhana, kadang-kadang Anda tidak bisa.
Mari kita juga tidak lupa bahwa fungsi besar dan Objek Tuhan dapat terbukti sangat sulit untuk diuji. Jika Anda ingin tetap gesit dan merasa "Aman" saat re-factoring dan mengubah kode, Anda perlu tes. Tes sulit ditulis ketika fungsi atau objek melakukan banyak hal.
sumber
Masalah dengan objek dewa adalah bahwa Anda biasanya dapat memecahnya menjadi potongan-potongan yang menguntungkan. Menurut definisi, ia melakukan lebih dari satu hal. Seluruh tujuan memecahnya menjadi kelas yang lebih kecil adalah agar Anda dapat memiliki kelas yang melakukan satu hal dengan baik (dan Anda juga tidak perlu meregangkan definisi "satu hal"). Ini berarti, untuk setiap kelas tertentu, setelah Anda mengetahui satu hal yang seharusnya dilakukan, Anda harus dapat membacanya dengan mudah dan mengatakan apakah itu melakukan satu hal dengan benar atau tidak.
Saya pikir ada adalah hal seperti memiliki terlalu banyak modularitas, dan terlalu banyak fleksibilitas, tapi itu lain dari masalah over-desain dan over-engineering, di mana Anda sedang akuntansi persyaratan bahwa Anda bahkan tidak tahu yang diinginkan konsumen. Banyak ide desain yang berorientasi sehingga memudahkan untuk mengontrol perubahan pada bagaimana kode dijalankan, tetapi jika tidak ada yang mengharapkan perubahan, maka tidak ada gunanya memasukkan fleksibilitas.
sumber
Queryer
yang mengoptimalkan kueri basis data, kueri RDBMS dan mem-parsing hasilnya menjadi objek untuk dikembalikan. Jika hanya ada satu cara untuk melakukan ini di aplikasi Anda danQueryer
tertutup rapat dan merangkum cara ini, maka itu hanya melakukan satu hal. Jika ada beberapa cara untuk melakukan ini dan seseorang mungkin peduli tentang detail satu bagiannya, maka ia melakukan banyak hal dan Anda mungkin ingin membaginya.Saya menggunakan pedoman yang lebih sederhana: jika Anda dapat menulis tes unit untuk itu, dan tidak memiliki duplikasi kode, itu cukup abstrak. Plus, Anda dalam posisi yang baik untuk refactoring nanti.
Di luar itu, Anda harus mengingat SOLID, tetapi lebih sebagai pedoman daripada aturan.
sumber
Jika aplikasinya cukup kecil, semuanya dapat dipelihara. Dalam aplikasi yang lebih besar, objek Tuhan dengan cepat menjadi masalah. Akhirnya mengimplementasikan fitur baru membutuhkan memodifikasi 17 objek Dewa. Orang tidak melakukannya dengan sangat baik mengikuti prosedur 17 langkah. Objek Dewa terus-menerus dimodifikasi oleh banyak pengembang, dan perubahan itu harus digabungkan berulang kali. Anda tidak ingin pergi ke sana.
sumber
Saya menyampaikan kekhawatiran Anda tentang abstraksi yang berlebihan dan tidak pantas, tetapi saya tidak perlu terlalu khawatir tentang abstraksi prematur.
Itu mungkin terdengar seperti kontradiksi, tetapi menggunakan abstraksi tidak akan menyebabkan masalah selama Anda tidak terlalu berkomitmen untuk itu terlalu dini - yaitu selama Anda bersedia dan dapat melakukan refactor jika diperlukan.
Apa yang tersirat adalah beberapa tingkat prototyping, eksperimen dan backtracking dalam kode.
Yang mengatakan, tidak ada aturan deterministik sederhana untuk diikuti yang akan menyelesaikan semua masalah. Pengalaman sangat berharga, tetapi Anda harus mendapatkan pengalaman itu dengan membuat kesalahan. Dan selalu ada lebih banyak kesalahan untuk membuat kesalahan sebelumnya tidak akan mempersiapkan Anda.
Meski begitu, perlakukan prinsip-prinsip buku teks sebagai titik awal, kemudian pelajari banyak pemrograman dan lihat bagaimana prinsip-prinsip itu bekerja. Jika mungkin untuk memberikan pedoman yang lebih baik, lebih tepat dan andal daripada hal-hal seperti SOLID, seseorang mungkin akan melakukannya sekarang - dan bahkan jika mereka punya, prinsip-prinsip yang ditingkatkan itu masih tidak sempurna, dan orang-orang akan bertanya tentang batasan pada mereka .
Pekerjaan yang bagus juga - jika ada yang bisa menyediakan algoritma yang jelas dan deterministik untuk merancang dan mengkode program, hanya akan ada satu program terakhir untuk ditulis manusia - program yang secara otomatis akan menulis semua program di masa depan tanpa campur tangan manusia.
sumber
Menggambar garis abstraksi yang tepat adalah sesuatu yang diambil dari pengalaman. Anda akan melakukan kesalahan dalam melakukannya sehingga tidak dapat disangkal.
SOLID adalah bentuk terkonsentrasi dari pengalaman itu yang diserahkan kepada Anda oleh orang-orang yang mendapatkan pengalaman ini dengan cara yang sulit. Anda cukup berhasil melakukannya ketika Anda mengatakan akan menahan diri untuk tidak membuat abstraksi sebelum Anda melihat kebutuhan untuk itu. Nah, pengalaman SOLID memberi Anda akan membantu Anda memecahkan masalah yang belum pernah ada . Tapi percayalah ... ada yang sangat nyata.
SOLID adalah tentang modularitas, modularitas adalah tentang pemeliharaan, dan pemeliharaan adalah tentang memungkinkan Anda untuk menjaga jadwal kerja yang manusiawi setelah perangkat lunak mencapai produksi dan klien mulai memperhatikan bug yang belum Anda miliki.
Manfaat terbesar dari modularitas adalah testabilitas. Semakin modular sistem Anda, semakin mudah untuk menguji dan semakin cepat Anda dapat membangun fondasi yang kokoh untuk melanjutkan dengan aspek-aspek yang lebih sulit dari masalah Anda. Jadi masalah Anda mungkin tidak menuntut modularitas ini tetapi fakta bahwa itu akan memungkinkan Anda untuk membuat kode pengujian yang lebih baik lebih cepat adalah tidak ada otak untuk berjuang untuk modularitas.
Menjadi lincah adalah semua tentang mencoba untuk menyerang keseimbangan halus antara pengiriman cepat dan memberikan kualitas yang baik. Agile tidak berarti bahwa kita harus mengambil jalan pintas, pada kenyataannya, proyek lincah yang paling sukses yang pernah saya lakukan adalah proyek yang sangat memperhatikan pedoman tersebut.
sumber
Poin penting yang tampaknya telah diabaikan adalah bahwa SOLID dipraktikkan bersama dengan TDD. TDD cenderung menyoroti apa yang "sesuai" dalam konteks khusus Anda dan membantu meringankan banyak keraguan yang tampak dalam saran tersebut.
sumber