Apa motivasi di balik anotasi @ImplementedBy di Guice?

10

Baru-baru ini saya membaca tentang @ImplementedByanotasi 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 @ImplementedByanotasi 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 @ImplementedBydengan 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 @ImplementedByanotasi 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 @ImplementedByanotasi, 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?

toniedzwiedz
sumber
2
Terkait, mungkin pertanyaan duplikat (meskipun judul Anda lebih jelas): Apakah @ImplementedBy milik Guice jahat?
Jeff Bowman
Bukan duplikat yang ketat, tetapi ada beberapa diskusi menarik tentang hal ini di sini: stackoverflow.com/questions/6197178/…
Richard Vodden

Jawaban:

8

Saya pikir bahaya di sini adalah menggunakan hanya satu @ImplementedBypenjelasan. Digunakan dengan tepat, dalam hubungannya dengan bind()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:

@ImplementedBy(NoOpDataService.class)
interface DataService {
    Map<String, MyPOJO> getData();
}

Dan kemudian NoOpDataServiceadalah:

class NoOpDataService implements DataService {
    @Override
    public Map<String, MyPOJO> getData() {
        return Collections.emptyMap();
    }
}

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 DataServicetidak 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.

durron597
sumber
3
Menambahkan kode uji ke produksi?
Basilevs