Saya memiliki beberapa antarmuka yang saya maksudkan untuk diimplementasikan oleh pihak ketiga di masa depan, dan saya sendiri menyediakan basis implementasi. Saya hanya akan menggunakan pasangan untuk menunjukkan contoh.
Saat ini, mereka didefinisikan sebagai
Barang:
public interface Item {
String getId();
String getName();
}
ItemStack:
public interface ItemStackFactory {
ItemStack createItemStack(Item item, int quantity);
}
ItemStackContainer:
public interface ItemStackContainer {
default void add(ItemStack stack) {
add(stack, 1);
}
void add(ItemStack stack, int quantity);
}
Sekarang, Item
dan ItemStackFactory
saya benar-benar dapat melihat beberapa pihak ketiga yang perlu memperpanjangnya di masa depan. ItemStackContainer
juga dapat diperluas di masa mendatang, tetapi tidak dengan cara yang dapat saya ramalkan, di luar implementasi default yang disediakan.
Sekarang, saya mencoba membuat perpustakaan ini sekuat mungkin; ini masih dalam tahap awal (pra-pra-alfa) sehingga ini mungkin merupakan tindakan rekayasa berlebihan (YAGNI). Apakah ini tempat yang tepat untuk menggunakan obat generik?
public interface ItemStack<T extends Item> {
T getItem();
int getQuantity();
}
Dan
public interface ItemStackFactory<T extends ItemStack<I extends Item>> {
T createItemStack(I item, int quantity);
}
Saya khawatir hal ini akan membuat implementasi dan penggunaan menjadi lebih sulit untuk dibaca dan dipahami; Saya pikir itu adalah rekomendasi untuk menghindari obat generik bersarang sedapat mungkin.
Jawaban:
Anda menggunakan obat generik di antarmuka Anda ketika implementasi Anda kemungkinan juga bersifat generik.
Misalnya, setiap struktur data yang dapat menerima objek arbitrer adalah kandidat yang baik untuk antarmuka generik. Contoh:
List<T>
danDictionary<K,V>
.Setiap situasi di mana Anda ingin meningkatkan keamanan tipe dengan cara yang umum adalah kandidat yang baik untuk obat generik. A
List<String>
adalah daftar yang hanya beroperasi pada string.Setiap situasi di mana Anda ingin menerapkan SRP dengan cara yang digeneralisasi dan menghindari metode spesifik tipe adalah kandidat yang baik untuk obat generik. Misalnya, dokumen PersonDocument, PlaceDocument, dan ThingDocument dapat diganti dengan a
Document<T>
.Pola Pabrik Abstrak adalah kasus penggunaan yang baik untuk generik, sedangkan Metode Pabrik biasa hanya akan membuat objek yang mewarisi dari antarmuka konkret yang umum.
sumber
class StackFactory { Stack<T> Create<T>(T item, int count); }
. Saya dapat menulis contoh tentang apa yang saya maksud dengan "memperbaiki parameter tipe dalam subkelas" dalam jawaban jika Anda ingin klarifikasi lebih lanjut, meskipun jawabannya hanya akan berhubungan dengan pertanyaan awal.Rencana Anda tentang cara memperkenalkan generalitas ke antarmuka Anda tampaknya benar bagi saya. Namun, pertanyaan Anda apakah itu ide yang bagus atau tidak membutuhkan jawaban yang agak lebih rumit.
Selama bertahun-tahun saya telah mewawancarai sejumlah kandidat untuk posisi Rekayasa Perangkat Lunak atas nama perusahaan tempat saya bekerja, dan saya menyadari bahwa mayoritas pencari kerja di luar sana merasa nyaman menggunakan kelas generik, (misalnya, kelas koleksi standar,) tetapi tidak dengan menulis kelas generik. Sebagian besar tidak pernah menulis satu kelas generik dalam karier mereka, dan tampak seolah-olah mereka akan benar-benar hilang jika diminta untuk menulis satu. Jadi, jika Anda memaksakan penggunaan obat generik pada siapa pun yang ingin mengimplementasikan antarmuka Anda atau memperluas implementasi basis Anda, Anda mungkin menunda orang.
Namun, yang dapat Anda coba adalah menyediakan versi antarmuka dan generik non-generik antarmuka Anda dan implementasi basis Anda, sehingga orang-orang yang tidak menggunakan obat generik dapat hidup bahagia di dunia mereka yang sempit dan berat, sementara orang-orang yang do generics dapat menuai manfaat dari pemahaman mereka yang lebih luas tentang bahasa.
sumber
Ada keputusan yang dibuat untuk Anda. Jika Anda tidak memberikan obat generik, mereka perlu meningkatkan penerapannya
Item
setiap kali mereka menggunakan:Setidaknya Anda harus membuat
ItemStack
obat generik sesuai saran Anda. Manfaat terdalam dari obat generik adalah bahwa Anda hampir tidak pernah perlu melakukan apa pun, dan menawarkan kode yang memaksa pengguna untuk melemparkan adalah IMHO pelanggaran pidana.sumber
Wow ... Saya memiliki pandangan yang sangat berbeda dalam hal ini.
Ini sebuah kesalahan. Anda tidak boleh menulis kode "untuk masa depan".
Juga, antarmuka ditulis atas-bawah. Anda tidak melihat kelas dan berkata "Hei, kelas ini benar-benar bisa mengimplementasikan antarmuka dan kemudian saya bisa menggunakan antarmuka itu di tempat lain juga". Itu adalah pendekatan yang salah, karena hanya kelas yang menggunakan antarmuka yang benar-benar tahu antarmuka apa yang seharusnya. Alih-alih, Anda harus berpikir, "Di tempat ini kelas saya membutuhkan dependensi. Biarkan saya mendefinisikan antarmuka untuk dependensi itu. Ketika saya selesai menulis kelas ini, saya akan menulis implementasi dependensi itu." Apakah seseorang akan pernah menggunakan kembali antarmuka Anda dan menggantikan implementasi default Anda dengan antarmuka Anda sama sekali tidak relevan. Mereka mungkin tidak pernah melakukannya. Ini tidak berarti antarmuka itu tidak berguna. Itu membuat kode Anda mengikuti prinsip Inversion of Control, yang membuat kode Anda sangat bisa diperluas di banyak tempat "
sumber
Saya pikir menggunakan obat generik dalam situasi Anda terlalu rumit.
Jika Anda memilih versi antarmuka generik, desain menunjukkan hal itu
Asumsi dan pembatasan implisit ini adalah hal yang sangat penting untuk diputuskan dengan hati-hati. Jadi terutama di tahap awal, desain prematur ini tidak boleh diperkenalkan. Sederhana, mudah dimengerti, desain yang umum diinginkan.
sumber
Saya akan mengatakan itu terutama tergantung pada pertanyaan ini: Jika seseorang perlu memperluas fungsionalitas
Item
danItemStackFactory
,Dalam kasus pertama, tidak ada kebutuhan untuk obat generik, yang kedua, mungkin ada.
sumber
Mungkin, Anda dapat memiliki hierarki antarmuka, di mana Foo adalah satu antarmuka, Bar adalah antarmuka lainnya. Kapan pun suatu tipe harus keduanya, itu adalah FooAndBar.
Untuk menghindari desgin, buat saja tipe FooAndBar saat diperlukan, dan simpan daftar antarmuka yang tidak akan pernah memperpanjang apa pun.
Ini jauh lebih nyaman bagi sebagian besar programmer (paling suka memeriksa tipenya atau tidak pernah berurusan dengan pengetikan statis apa pun). Sangat sedikit orang yang menulis kelas obat generik sendiri.
Juga sebagai catatan: antarmuka adalah tentang tindakan apa yang mungkin dapat dijalankan. Mereka seharusnya benar-benar menjadi kata kerja, bukan kata benda.
sumber