The Antarmuka Pemisahan Prinsip mengatakan:
Tidak ada klien yang harus dipaksa untuk bergantung pada metode yang tidak digunakannya. ISP membagi antarmuka yang sangat besar menjadi yang lebih kecil dan lebih spesifik sehingga klien hanya perlu tahu tentang metode yang menarik bagi mereka.
Ada beberapa pertanyaan yang belum terjawab di sini. Satu adalah:
Seberapa kecil?
Kamu bilang:
Saat ini saya berurusan dengan ini dengan membagi namespace modul tergantung pada kebutuhan kliennya.
Saya menyebutnya pengetikan manual bebek . Anda membangun antarmuka yang mengekspos hanya apa yang dibutuhkan klien. Prinsip pemisahan antarmuka bukan hanya mengetik bebek manual.
Tetapi ISP juga bukan sekadar panggilan untuk antarmuka peran "koheren" yang dapat digunakan kembali. Tidak ada desain antarmuka peran yang "koheren" yang dapat dengan sempurna melindungi terhadap penambahan klien baru dengan kebutuhan perannya sendiri.
ISP adalah cara untuk mengisolasi klien dari dampak perubahan pada layanan. Itu dimaksudkan untuk membuat build berjalan lebih cepat saat Anda membuat perubahan. Tentu itu memiliki manfaat lain, seperti tidak melanggar klien, tapi itulah poin utamanya. Jika saya mengubah count()
tanda tangan fungsi layanan , bagus jika klien yang tidak menggunakan count()
tidak perlu diedit dan dikompilasi ulang.
Inilah MENGAPA saya peduli tentang Prinsip Segregasi Antarmuka. Itu bukan sesuatu yang saya anggap penting. Ini memecahkan masalah nyata.
Jadi cara itu harus diterapkan harus menyelesaikan masalah untuk Anda. Tidak ada cara menghafal otak mati untuk menerapkan ISP yang tidak dapat dikalahkan hanya dengan contoh yang tepat dari perubahan yang diperlukan. Anda seharusnya melihat bagaimana sistem berubah dan membuat pilihan yang akan membuat segalanya menjadi tenang. Mari menjelajahi opsi.
Pertama-tama tanyakan pada diri Anda: apakah membuat perubahan pada antarmuka layanan sulit sekarang? Jika tidak, pergilah ke luar dan mainkan sampai Anda tenang. Ini bukan latihan intelektual. Pastikan obatnya tidak lebih buruk dari penyakitnya.
Jika banyak klien menggunakan subset fungsi yang sama, itu berpendapat untuk antarmuka yang dapat digunakan kembali "koheren". Subset ini kemungkinan berfokus pada satu gagasan yang dapat kita pikirkan sebagai peran yang diberikan layanan kepada klien. Sangat menyenangkan ketika ini bekerja. Ini tidak selalu berhasil.
Jika banyak klien menggunakan himpunan fungsi yang berbeda, mungkin saja klien tersebut benar-benar menggunakan layanan melalui berbagai peran. Tidak apa-apa tapi itu membuat peran sulit dilihat. Temukan mereka dan cobalah untuk menggoda mereka. Itu dapat menempatkan kita kembali dalam kasus 1. Klien hanya menggunakan layanan melalui lebih dari satu antarmuka. Tolong jangan mulai casting layanan. Jika ada yang berarti melewati layanan ke klien lebih dari sekali. Itu bekerja tetapi itu membuat saya mempertanyakan apakah layanan ini bukan bola lumpur besar yang perlu dipecah.
Jika banyak klien menggunakan himpunan bagian yang berbeda tetapi Anda tidak melihat peran bahkan memungkinkan bahwa klien mungkin menggunakan lebih dari satu maka Anda tidak memiliki yang lebih baik daripada mengetik bebek untuk merancang antarmuka Anda. Cara mendesain antarmuka ini memastikan bahwa klien tidak terpapar pada satu fungsi pun yang tidak digunakan tetapi hampir menjamin bahwa menambahkan klien baru akan selalu melibatkan penambahan antarmuka baru yang sementara implementasi layanan tidak perlu tahu tentang hal itu antarmuka yang akan menggabungkan antarmuka peran. Kami hanya menukar satu rasa sakit dengan yang lain.
Jika banyak klien menggunakan himpunan bagian yang berbeda, tumpang tindih, klien baru diharapkan untuk menambahkan bahwa akan memerlukan himpunan himpunan bagian yang tidak dapat diprediksi, dan Anda tidak ingin memecah layanan kemudian mempertimbangkan solusi yang lebih fungsional. Karena dua opsi pertama tidak berfungsi dan Anda benar-benar berada di tempat yang buruk di mana tidak ada yang mengikuti pola dan lebih banyak perubahan datang maka pertimbangkan untuk menyediakan setiap fungsi antarmuka itu sendiri. Mengakhiri di sini bukan berarti ISP gagal. Jika ada yang gagal itu adalah paradigma berorientasi objek. Antarmuka metode tunggal mengikuti ISP secara ekstrim. Ini adalah pengetikan keyboard yang lumayan tetapi Anda mungkin menemukan ini tiba-tiba membuat antarmuka dapat digunakan kembali. Sekali lagi, pastikan tidak ada
Jadi ternyata mereka bisa menjadi sangat kecil.
Saya menganggap pertanyaan ini sebagai tantangan untuk menerapkan ISP dalam kasus yang paling ekstrem. Namun perlu diingat bahwa ekstrem sebaiknya dihindari. Dalam desain yang dipikirkan dengan baik yang menerapkan prinsip - prinsip PADAT lainnya masalah ini biasanya tidak terjadi atau masalah, hampir sebanyak.
Pertanyaan lain yang belum terjawab adalah:
Siapa yang memiliki antarmuka ini?
Berkali-kali saya melihat antarmuka yang dirancang dengan apa yang saya sebut mentalitas "perpustakaan". Kita semua bersalah atas pengkodean monyet-lihat-monyet-di mana Anda hanya melakukan sesuatu karena itulah yang Anda lakukan. Kami bersalah atas hal yang sama dengan antarmuka.
Ketika saya melihat sebuah antarmuka yang dirancang untuk kelas di perpustakaan saya dulu berpikir: oh, orang-orang ini adalah pro. Ini harus menjadi cara yang tepat untuk melakukan antarmuka. Apa yang saya gagal mengerti adalah bahwa batas perpustakaan memiliki kebutuhan dan masalah sendiri. Untuk satu hal, perpustakaan sama sekali tidak tahu tentang desain klien itu. Tidak semua batas sama. Dan kadang-kadang bahkan batas yang sama memiliki cara berbeda untuk melewatinya.
Berikut adalah dua cara sederhana untuk melihat desain antarmuka:
Antarmuka yang dimiliki layanan. Beberapa orang merancang setiap antarmuka untuk mengekspos semua layanan yang dapat dilakukan. Anda bahkan dapat menemukan opsi refactoring di IDE yang akan menulis antarmuka untuk Anda menggunakan kelas apa pun yang Anda berikan.
Antarmuka yang dimiliki klien. ISP sepertinya berpendapat bahwa ini benar dan layanan yang dimiliki salah. Anda harus memecah setiap antarmuka dengan kebutuhan klien dalam pikiran. Karena klien memiliki antarmuka, ia harus mendefinisikannya.
Jadi siapa yang benar?
Pertimbangkan plugin:
Siapa yang memiliki antarmuka di sini? Klien? Pelayanan?
Ternyata keduanya.
Warna di sini adalah lapisan. Lapisan merah (kanan) tidak seharusnya tahu apa-apa tentang lapisan hijau (kiri). Lapisan hijau dapat diubah atau diganti tanpa menyentuh lapisan merah. Dengan begitu setiap lapisan hijau bisa dicolokkan ke lapisan merah.
Saya suka mengetahui apa yang seharusnya diketahui tentang apa, dan apa yang tidak seharusnya diketahui. Bagi saya, "apa yang tahu tentang apa?", Adalah satu-satunya pertanyaan arsitektur yang paling penting.
Mari kita perjelas kosakata:
[Client] --> [Interface] <|-- [Service]
----- Flow ----- of ----- control ---->
Klien adalah sesuatu yang digunakan.
Suatu layanan adalah sesuatu yang digunakan.
Interactor
kebetulan keduanya.
ISP mengatakan memecah antarmuka untuk klien. Baik, mari terapkan itu di sini:
Presenter
(layanan) tidak boleh menentukan Output Port <I>
antarmuka. Antarmuka harus dipersempit untuk apa Interactor
(di sini bertindak sebagai klien) kebutuhan. Itu berarti antarmuka TAHU tentang Interactor
dan, untuk mengikuti ISP, harus berubah dengannya. Dan ini baik-baik saja.
Interactor
(di sini bertindak sebagai layanan) tidak boleh menentukan Input Port <I>
antarmuka. Antarmuka harus dipersempit dengan apa yang Controller
(klien) butuhkan. Itu berarti antarmuka TAHU tentang Controller
dan, untuk mengikuti ISP, harus berubah dengannya. Dan ini tidak baik.
Yang kedua tidak baik karena lapisan merah tidak seharusnya tahu tentang lapisan hijau. Jadi apakah ISP salah? Yah agak. Tidak ada prinsip yang mutlak. Ini adalah kasus di mana orang-orang bodoh yang menyukai antarmuka untuk menunjukkan segala sesuatu yang dapat dilakukan layanan ternyata benar.
Setidaknya, mereka benar jika Interactor
tidak melakukan apa pun selain dari kebutuhan use case ini. Jika Interactor
hal-hal untuk kasus penggunaan lain tidak ada alasan ini Input Port <I>
harus tahu tentang mereka. Tidak yakin mengapa Interactor
tidak bisa hanya fokus pada satu Use Case jadi ini bukan masalah, tetapi banyak hal terjadi.
Tetapi input port <I>
antarmuka tidak bisa menjadi budak bagi Controller
klien dan menjadikannya plugin yang benar. Ini adalah batas 'perpustakaan'. Toko pemrograman yang sama sekali berbeda bisa menulis lapisan hijau bertahun-tahun setelah lapisan merah diterbitkan.
Jika Anda melewati batas 'perpustakaan' dan Anda merasa perlu menerapkan ISP walaupun Anda tidak memiliki antarmuka di sisi lain, Anda harus menemukan cara untuk mempersempit antarmuka tanpa mengubahnya.
Salah satu cara untuk melakukannya adalah adaptor. Letakkan di antara suka klien Controler
dan Input Port <I>
antarmuka. Adaptor menerima Interactor
sebagai Input Port <I>
dan mendelegasikan itu berfungsi untuk itu. Namun, itu hanya mengekspos apa yang Controller
dibutuhkan klien melalui antarmuka peran atau antarmuka yang dimiliki oleh lapisan hijau. Adaptor tidak mengikuti ISP sendiri tetapi memungkinkan kelas yang lebih kompleks ingin Controller
menikmati ISP. Ini berguna jika ada lebih sedikit adapter daripada klien seperti Controller
itu yang menggunakannya dan ketika Anda berada dalam situasi yang tidak biasa di mana Anda melewati batas perpustakaan dan, meskipun diterbitkan, perpustakaan tidak akan berhenti berubah. Melihat Anda, Firefox. Sekarang perubahan itu hanya merusak adaptor Anda.
Jadi apa artinya ini? Itu berarti jujur Anda belum memberikan informasi yang cukup bagi saya untuk memberi tahu Anda apa yang harus Anda lakukan. Saya tidak tahu apakah tidak mengikuti ISP menyebabkan Anda mengalami masalah. Saya tidak tahu apakah mengikutinya tidak akan menyebabkan lebih banyak masalah bagi Anda.
Saya tahu Anda sedang mencari prinsip panduan sederhana. ISP mencoba menjadi seperti itu. Tapi banyak yang tidak terucapkan. Saya percaya akan hal itu. Ya, tolong jangan memaksa klien untuk bergantung pada metode yang tidak mereka gunakan, tanpa alasan yang bagus!
Jika Anda memiliki alasan yang bagus, seperti mendesain sesuatu untuk menerima plugin, maka waspadai masalah tidak mengikuti penyebab ISP (sulit untuk berubah tanpa melanggar klien), dan cara untuk mengurangi mereka (tetap Interactor
atau setidaknya Input Port <I>
fokus pada satu stabil) gunakan kasing).