Baru-baru ini saya membaca tentang @ImplementedBy
anotasi yang tersedia di Google Guice . Hal ini memungkinkan programmer untuk menentukan pengikatan antara antarmuka dan implementasinya untuk digunakan di masa depan dalam injeksi dependensi. Ini adalah contoh penjilidan just-in-time .
Saya cukup terbiasa mendefinisikan binding eksplisit dalam modul saya, menggunakan sintaks berikut:
bind(SomeInterface.class).to(SomeInterfaceImplementation.class);
Menurut dokumentasi, ini setara dengan penggunaan @ImplementedBy
anotasi berikut:
@ImplementedBy(SomeInterfaceImplementation.class)
public interface SomeInterface {
//method declarations
}
Satu-satunya keuntungan yang saya dapat lihat di sini adalah bahwa kode ini sedikit lebih pendek. Pada saat yang sama, pendekatan ini memiliki kelemahan yang ditunjukkan oleh dokumen yang sama:
Gunakan
@ImplementedBy
dengan hati-hati; itu menambah ketergantungan waktu kompilasi dari antarmuka ke implementasinya.
Ketergantungan seperti itu mungkin tidak menjadi masalah dalam banyak kasus tapi saya pribadi melihatnya sebagai bau kode.
Kasus penggunaan apa yang membuat @ImplementedBy
anotasi layak digunakan?
Salah satu cara yang mungkin tampaknya adalah menggunakannya dalam kode perpustakaan atau kerangka kerja. Seperti dijelaskan dalam dokumen, anotasi dapat memberikan pengikatan default yang mudah ditimpa oleh yang eksplisit.
Jika suatu tipe ada dalam kedua
bind()
pernyataan (sebagai argumen pertama) dan memiliki@ImplementedBy
anotasi,bind()
pernyataan tersebut digunakan. Anotasi menyarankan implementasi standar yang dapat ditimpa dengan pengikatan.
Dengan cara ini, sebagai pengembang perpustakaan, saya dapat memberikan kepada pengguna saya pengikatan di luar kotak yang dapat dikustomisasi di suatu tempat dalam kode klien.
Apakah ini satu-satunya alasan agar anotasi itu ada? Atau ada sesuatu yang saya lewatkan? Bisakah saya mendapatkan sesuatu dengan menggunakannya dalam kode yang hanya merupakan aplikasi yang mengurus beberapa logika bisnis dan bukan perpustakaan / kerangka kerja yang akan diperluas?
sumber
Jawaban:
Saya pikir bahaya di sini adalah menggunakan hanya satu
@ImplementedBy
penjelasan. Digunakan dengan tepat, dalam hubungannya denganbind()
pernyataan dalam modul Anda dan sebagainya, tidak apa-apa.Memiliki implementasi standar sangat bagus untuk pengujian; Anda tidak perlu ingin secara eksplisit mendefinisikan injeksi tiruan setiap kali Anda menguji kelas yang memiliki banyak dependensi, atau jika Anda memiliki kelas yang bergantung pada banyak hal (jadi Anda harus mendefinisikan tiruan setiap kali ).
Misalnya, Anda mungkin memiliki kelas:
Dan kemudian
NoOpDataService
adalah:Anda tidak akan pernah menggunakan ini dalam kode aktual Anda, jelas; dalam modul Guice Anda, Anda akan mengikat implementasi yang benar-benar melakukan sesuatu. Tetapi semua tes pada kelas yang mendapatkan suntikan
DataService
tidak perlu memiliki ikatan tiruan lagi.tl; dr Saya setuju dengan Anda bahwa memiliki antarmuka Anda bergantung pada implementasi Anda bisa menjadi bau kode; tetapi juga dapat menghapus kode boilerplate membuat pengujian lebih mudah. Ini bukan fitur yang sulit untuk diimplementasikan; dan sementara ada beberapa potensi kecil untuk pelecehan, pada akhirnya konsekuensinya tidak bisa terlalu buruk (layanan dimulai dengan kejutan), dan itu tidak akan terlalu sulit untuk diperbaiki bahkan jika itu terjadi.
sumber