Ada masalah dengan deskripsi dan interpretasi prinsip-prinsip pengembangan arsitektur SOLID (kepenulisan Robert Martin). Banyak sumber memberikan definisi dan bahkan contoh penggunaannya. Mempelajari mereka dan mencoba untuk menggunakan diri saya sendiri, saya terus-menerus menemukan diri saya berpikir bahwa tidak ada cukup penjelasan tentang keajaiban aplikasi mereka. Dan mencoba melihat roda gigi internal, untuk memahami - dan bagi saya itu artinya mengingat - meletakkannya di "rak syarat". Nah, apakah itu akan bermanfaat bagi orang lain.

Kami melanjutkan untuk "menyulap rak-rak" dari pendekatan desain di atas.
Prinsip Tanggung Jawab Tunggal (SRP) prinsip tanggung jawab tunggal
Sepotong kode harus berubah hanya selama implementasi satu tujuan. Jika bagian kode mengimplementasikan dua tugas dan perubahan untuk penggunaan yang berbeda, maka Anda harus menduplikasi bagian ini dalam contoh untuk setiap tujuan. Ini sangat penting karena memerlukan penyimpangan dari prinsip yang diterima secara umum untuk menghilangkan duplikasi.
Tujuan dari prinsip ini adalah untuk menghilangkan kesalahan implisit yang diperkenalkan karena fakta bahwa invarian berikut ada untuk pengembangan bagian kode, prosedur, kelas, komponen (selanjutnya, istilah [komponen] digunakan untuk menggabungkan konsep-konsep ini):
- [1] [komponen] yang ditulis dengan benar perlu digunakan dan lebih sering beberapa kali,
- [2] di setiap tempat penggunaan, [komponen] diharapkan untuk mempertahankan perilaku konsisten yang mengarah pada hasil yang berulang,
- [3] saat menggunakan [komponen] di beberapa tempat, hasilnya harus memuaskan setiap tempat penggunaan,
- jika perubahan [komponen] diperlukan untuk salah satu tempat penggunaan, dan perilaku [komponen] sebelumnya diperlukan untuk tempat penggunaan lain, perlu membuat salinan [komponen] dan kemudian memodifikasinya (atau menggeneralisasi [komponen] dengan parameter tambahan yang menyediakan perilaku berbeda),
jika ada tempat penggunaan [komponen] yang tidak penting untuk tugas saat ini diselesaikan oleh programmer, maka sangat mudah baginya untuk melupakan memeriksa kompatibilitas dengan tempat-tempat penggunaan perubahan yang dibuat untuk [komponen] ini.
Oleh karena itu, semua tempat penggunaan harus ditempatkan di zona [Tanggung Jawab Tunggal] dari satu tanggung jawab tunggal, yaitu, diubah dan diperhitungkan sekaligus untuk setiap masalah yang diselesaikan oleh programmer).
Prinsip berlaku untuk bagian kode dan komponen, pustaka, program, serangkaian program yang digunakan di beberapa tempat.
Banyak sumber memberikan contoh kelas dengan hanya satu "fungsi" sebagai cita-cita SRP dan kelas "objek ilahi", menggabungkan semua fungsi aplikasi, sebagai antipattern. Kelas IMHO dengan hanya satu "fungsi" adalah persyaratan untuk optimasi prematur arsitektur kode, mendorong untuk menulis banyak kelas (entitas kode) dari awal, sementara lupa bahwa tidak adanya lebih dari satu tempat penggunaan memungkinkan programmer untuk dengan cepat mengevaluasi sejumlah kecil yang terletak secara lokal (dalam satu kelas) kode interaksi daripada menganalisis hubungan eksternal entitas kode yang berbeda yang bertanggung jawab untuk "fungsi" mereka. Sebuah "objek ilahi" untuk aplikasi kecil juga bukan kejahatan yang kuat - ini memungkinkan Anda untuk memulai pengembangan: pilih semua entitas yang diperlukan dan, tulis mereka secara berdampingan, terpisah dari objek eksternal dari perpustakaan standar dan modul eksternal (buat sel hidup dan pisahkan dengan membran). Dalam proses pertumbuhan dan pengembangan proyek, ada banyak metode yang membantu untuk mengikuti SRP, salah satunya adalah pembagian ke dalam kelas dan meminimalkan jumlah "fungsi" di mana masing-masing kelas bertanggung jawab (pembelahan sel dan spesialisasi mereka dalam tubuh).
Di sini saya ingin menulis serangkaian teknik untuk mempertahankan SRP, tetapi pekerjaan ini belum selesai (saya harap "tangan-tangan"). Dari area yang jelas di mana Anda dapat mencari trik ini:
- pola desain;
- menggunakan cabang komponen khusus yang berbeda, sebagai lawan untuk membuat komponen yang memenuhi semua metode aplikasi (garpu pada GitHub).
Prinsip Terbuka-Tertutup (OCP) Prinsip Terbuka / Tertutup
Optimal untuk merencanakan pengembangan kode sehingga bagi programmer untuk melaksanakan tugas baru perlu menambahkan kode baru, sedangkan kode lama tidak perlu perubahan. Kode harus terbuka (Terbuka) untuk ditambahkan dan ditutup (Ditutup) untuk berubah.
Tujuan dari prinsip ini adalah untuk meminimalkan biaya tenaga kerja dan menghilangkan kesalahan implisit yang diperkenalkan karena invarian berikut dalam pengembangan:
- [1], [2], [3] dijelaskan sebelumnya,
- untuk mengimplementasikan tugas baru, programmer dapat menambahkan [komponen] baru atau mengubah perilaku [komponen] lama,
- penambahan [komponen] memerlukan verifikasi di tempat penggunaan baru, dan biaya waktu programmer
- perubahan perilaku [komponen] yang disebabkan oleh tugas baru memerlukan verifikasi di tempat penggunaan baru dan di semua tempat penggunaan lama, yang juga menyebabkan konsumsi waktu programmer, dan dalam kasus [komponen] yang dipublikasikan, pekerjaan semua programmer yang menggunakan [komponen].
disarankan untuk memilih opsi untuk mengimplementasikan tugas baru sambil meminimalkan waktu yang dihabiskan oleh programmer.
Lebih sering dalam praktik pengembangan perangkat lunak, biaya penambahan jauh lebih sedikit daripada biaya perubahan, yang membuat penggunaan prinsip [Terbuka-Tertutup] menjadi jelas. Pada saat yang sama, ada banyak teknik untuk mempertahankan arsitektur program dalam keadaan di mana implementasi tugas baru dilakukan dengan menambahkan hanya [komponen]. Pekerjaan dengan arsitektur ini juga membutuhkan waktu programmer, tetapi praktik dalam proyek-proyek besar menunjukkan jauh lebih sedikit daripada menggunakan pendekatan mengubah prosedur lama. Dan, tentu saja, deskripsi perkembangan ini adalah idealisasi. Hampir tidak ada implementasi tugas dengan hanya menambah atau hanya mengubah. Dalam kehidupan nyata, campuran dari pendekatan ini digunakan, tetapi OCP menekankan manfaat menggunakan pendekatan add.
Dan di sini saya ingin menulis serangkaian teknik untuk mempertahankan OCP. Dari area yang jelas di mana Anda dapat mencari trik ini:
- pola desain;
- perpustakaan dll dan opsi untuk distribusi mereka, memperbarui dan pengembangan fungsionalitas;
- pengembangan perpustakaan COM dan objek di dalamnya;
- pengembangan bahasa pemrograman dan dukungan untuk kode yang ditulis sebelumnya;
- mengembangkan sistem legislatif negara.
Prinsip Pengganti Liskov (LSP) Prinsip Pengganti Barbara Liskov
Prinsip ini membatasi penggunaan ekstensi antarmuka dasar [basis] untuk implementasi, yang menyatakan bahwa setiap implementasi antarmuka dasar harus memiliki perilaku sebagai antarmuka dasar. Pada saat yang sama, antarmuka dasar memperbaiki perilaku yang diharapkan di tempat penggunaannya. Dan kehadiran dalam perilaku implementasi perbedaan dari perilaku yang diharapkan, diperbaiki oleh antarmuka dasar, akan mengarah pada kemungkinan pelanggaran invarian [2].
Prinsip ini didasarkan dan memperbaiki teknik desain berdasarkan abstraksi. Dalam pendekatan ini, sebuah abstraksi diperkenalkan - beberapa sifat dasar dan karakteristik perilaku banyak situasi diperbaiki. Misalnya, [komponen-prosedur] "Pindah ke posisi sebelumnya" untuk situasi: "Kursor dalam teks", "Buku di rak", "Elemen dalam larik", "Kaki menari", dll. Dan ditugaskan ke [komponen] ini ( sering dengan pengalaman sehari-hari dan tanpa formalisasi) beberapa prasyarat dan perilaku, misalnya: "Kehadiran objek bergerak", "Ulangi beberapa kali", "Kehadiran urutan elemen", "Kehadiran posisi tetap elemen". LSP mensyaratkan bahwa ketika menambahkan situasi penggunaan baru untuk [komponen] semua prasyarat dan batasan basis dipenuhi. Dan situasi "biji-bijian dalam kaleng gula" tidak dapat dijelaskan oleh abstraksi ini, meskipun biji-bijian, tentu saja, memiliki posisi, ada posisi di mana biji-bijian telah ada sebelumnya, dan dimungkinkan untuk memindahkannya di dalamnya - hanya ada posisi tetap unsur-unsur.
Tujuan dari prinsip ini adalah untuk menghilangkan kesalahan implisit yang diperkenalkan karena invarian berikut dalam pengembangan:
- [1], [2], [3] dijelaskan sebelumnya,
- [prosedur] dasar menjelaskan perilaku yang berguna dalam sejumlah besar situasi, menetapkan kendala yang diperlukan untuk penerapannya,
[prosedur] yang dikembangkan untuk implementasi pangkalan harus memenuhi semua batasannya, termasuk yang tersirat dengan jalur yang sulit (disediakan secara tidak resmi).
Sangat sering, contoh dengan Rectangle ([base]) dan Square (implementasi) diberikan untuk menggambarkan prinsip ini. class CSquare : public CRectangle
situasi class CSquare : public CRectangle
. Di [basis], operasi untuk bekerja dengan lebar dan tinggi (Atur (Dapatkan) Lebar, Atur (Dapatkan) Tinggi) diperkenalkan. Dalam implementasi CSquare, operasi Set ini dipaksa untuk mengubah kedua ukuran objek. Saya selalu kekurangan penjelasan bahwa batasan berikut diatur "secara informal" di [dasar]: "kemampuan untuk menggunakan Lebar, Tinggi secara mandiri." Dalam implementasi CSquare, itu dilanggar, dan di tempat-tempat menggunakan urutan tindakan sederhana berdasarkan penggunaan kemerdekaan ini: r.SetWidth(r.GetWidth()*2); r.SetHeight(r.GetHeight()*2)
r.SetWidth(r.GetWidth()*2); r.SetHeight(r.GetHeight()*2)
- untuk implementasi, CSquare akan meningkatkan kedua ukuran sebanyak 4 kali, alih-alih 2 kali diasumsikan untuk CRectangle.
IMHO prinsip ini menunjukkan sulitnya melacak kendala informal seperti itu, yang, dengan utilitas besar dan frekuensi tinggi penggunaan pendekatan pengembangan "implementasi dasar" memerlukan perhatian khusus.
Prinsip Segregasi Antarmuka (ISP) prinsip pemisahan antarmuka; Dependency Inversion Principle (DIP). Prinsip Ketergantungan Inversi
Kedua prinsip ini sangat dekat dalam bidang persyaratannya. Keduanya secara implisit menyiratkan kegunaan menggunakan antarmuka dasar sekecil mungkin, sebagai alat untuk interaksi dua [komponen]: "klien" dan "server" - nama-nama ini dipilih hanya untuk identifikasi. Dalam hal ini, informasi umum yang digunakan oleh [komponen] terkonsentrasi di antarmuka dasar. Satu [komponen] ("server") mengimplementasikan implementasi antarmuka dasar, [komponen] lainnya ("klien") merujuk pada implementasi ini.
Tujuan dari prinsip-prinsip ini adalah untuk meminimalkan ketergantungan komponen, yang memungkinkan perubahan independen pada kode mereka jika tidak mengubah antarmuka yang mendasarinya. Independensi perubahan komponen mengurangi kerumitan dan tenaga kerja jika komponen memenuhi persyaratan prinsip SRP. Pendekatan serupa dimungkinkan karena invarian berikut ada dalam pengembangan:
- [1], [2], [3] dijelaskan sebelumnya,
- setiap [komponen] yang melekat dalam perilakunya membentuk batas penggunaannya,
- di setiap tempat penggunaan [komponen] semua pembatasannya mungkin terlibat,
- konsekuensi [komponen] dasar dari definisi tersebut memiliki kompleksitas yang lebih sedikit dan jumlah pembatasan daripada implementasi [komponen],
- setiap perubahan dalam [komponen] mengubah batasannya dan memerlukan verifikasi semua tempat penggunaannya, yang menyebabkan pengeluaran waktu seorang programmer,
tempat penggunaan basis [komponen] tidak memerlukan verifikasi setelah melakukan perubahan pada implementasi [komponen].
Jelas bahwa disarankan untuk meminimalkan "ukuran" antarmuka dasar dengan membuang fungsionalitas dan batasan yang tidak digunakan, sehingga membatasi implementasi [komponen] dengan prinsip (LSP) lebih sedikit
Prinsip ISP menekankan perlunya pemisahan (Pemisahan) dari antarmuka "server", jika tidak semua fungsionalitas yang diterbitkan digunakan oleh "klien" ini. Dalam hal ini, hanya [pangkalan] yang dibutuhkan oleh klien yang dialokasikan dan minimalisasi informasi yang membatasi bersama dipastikan.
Dan di sini saya ingin menulis serangkaian teknik untuk mempertahankan DIP. Dari area yang jelas di mana Anda dapat mencari trik ini:
- pemisahan deskripsi kelas menjadi bagian-bagian publik dan pribadi (dan prinsip-prinsip OOP lainnya),
- deskripsi interaksi dengan perpustakaan dinamis dengan serangkaian fungsi dan deskriptor objek terbatas,
- menggunakan lemari arsip sebagai antarmuka untuk mengakses perpustakaan buku.
Kembali ke tajuk, saya akan menjelaskan mengapa "tidak mengerti" dipilih. Negasi ditambahkan untuk menekankan kesalahan yang panjang dan sangat bermanfaat aturan IMHO. Lebih baik tidak memahami dan karena itu tidak menggunakan teknologi, daripada salah paham, percaya, menghabiskan sumber daya Anda untuk menggunakan teknologi dan, sebagai hasilnya, tidak mendapatkan knalpot yang bermanfaat kecuali kepuasan diri dan kemungkinan membual tentang keterlibatan dalam teknologi modis.
Terima kasih atas perhatian anda
Referensi