JavaRush /Java Blog /Random-ID /Cara mudah untuk memasukkan dependensi

Cara mudah untuk memasukkan dependensi

Dipublikasikan di grup Random-ID
Injeksi ketergantungan (DI) bukanlah konsep yang mudah untuk dipahami, dan menerapkannya pada aplikasi baru atau yang sudah ada bahkan lebih membingungkan. Jess Smith menunjukkan cara melakukan injeksi ketergantungan tanpa wadah injeksi dalam bahasa pemrograman C# dan Java. Cara sederhana injeksi ketergantungan - 1Pada artikel ini, saya akan menunjukkan cara mengimplementasikan injeksi ketergantungan (DI) di aplikasi .NET dan Java. Konsep injeksi ketergantungan pertama kali menjadi perhatian pengembang pada tahun 2000, ketika Robert Martin menulis artikel "Prinsip dan Pola Desain" (yang kemudian dikenal dengan akronim SOLID ). D dalam SOLID mengacu pada Dependency of Inversion (DOI), yang kemudian dikenal sebagai injeksi ketergantungan. Definisi asli dan paling umum: inversi ketergantungan adalah inversi cara kelas dasar mengelola dependensi. Artikel asli Martin menggunakan kode berikut untuk mengilustrasikan ketergantungan suatu kelas Copypada kelas tingkat yang lebih rendah WritePrinter:
void Copy()
	{
	 int c;
	 while ((c = ReadKeyboard()) != EOF)
		WritePrinter(c);
	}
Masalah pertama yang jelas adalah jika Anda mengubah daftar parameter atau tipe suatu metode WritePrinter, Anda perlu mengimplementasikan pembaruan di mana pun ada ketergantungan pada metode tersebut. Proses ini meningkatkan biaya pemeliharaan dan berpotensi menjadi sumber kesalahan baru.
Tertarik membaca tentang Java? Bergabunglah dengan grup Pengembang Java !
Masalah lainnya: kelas Copy tidak lagi berpotensi untuk digunakan kembali. Misalnya, bagaimana jika Anda perlu mengeluarkan karakter yang dimasukkan dari keyboard ke file, bukan ke printer? Untuk melakukan ini, Anda dapat memodifikasi kelas Copysebagai berikut (sintaks bahasa C++):
void Copy(outputDevice dev)
	{
	int c;
	while ((c = ReadKeyboard()) != EOF)
		if (dev == printer)
			WritePrinter(c);
		else
			WriteDisk(c);
	}
Meskipun ada pengenalan ketergantungan baru WriteDisk, situasinya tidak membaik (melainkan memburuk) karena prinsip lain dilanggar: “entitas perangkat lunak, yaitu kelas, modul, fungsi, dan sebagainya, harus terbuka untuk perluasan, tetapi tertutup untuk modifikasi." Martin menjelaskan bahwa pernyataan if/else bersyarat baru ini mengurangi stabilitas dan fleksibilitas kode. Solusinya adalah dengan membalikkan ketergantungan sehingga metode tulis dan baca bergantung pada Copy. Alih-alih "memunculkan" dependensi, dependensi tersebut diteruskan melalui konstruktor. Kode yang dimodifikasi terlihat seperti ini:
class Reader
	{
		public:
		virtual int Read() = 0;
	};
	class Writer
	{
		public:
		virtual void Write(char) = 0;
	};
	void Copy(Reader& r, Writer& w)
	{
		int c;
		while((c=r.Read()) != EOF)
		w.Write(c);
	}
Sekarang kelas tersebut Copydapat dengan mudah digunakan kembali dengan implementasi metode kelas Readerdan Writer. Kelas Copytidak memiliki informasi apa pun tentang struktur internal tipe Readerdan Writer, sehingga memungkinkan untuk menggunakannya kembali dengan implementasi berbeda. Namun jika semua ini tampak seperti omong kosong bagi Anda, mungkin contoh di Java dan C# berikut ini akan memperjelas situasinya.

Contoh di Java dan C#

Untuk mengilustrasikan kemudahan injeksi ketergantungan tanpa wadah ketergantungan, mari kita mulai dengan contoh sederhana yang dapat disesuaikan untuk digunakan DIhanya dalam beberapa langkah. Katakanlah kita mempunyai kelas HtmlUserPresentationyang, ketika metodenya dipanggil, menghasilkan antarmuka pengguna HTML. Berikut ini contoh sederhananya:
HtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
Proyek apa pun yang menggunakan kode kelas ini akan memiliki ketergantungan pada kelas tersebut HtmlUserPresentation, yang mengakibatkan masalah kegunaan dan pemeliharaan yang dijelaskan di atas. Perbaikan segera muncul: membuat antarmuka dengan tanda tangan dari semua metode yang saat ini tersedia di kelas HtmlUserPresentation. Berikut adalah contoh antarmuka ini:
public interface IHtmlUserPresentation {
	String createTable(ArrayList rowVals, String caption);
	String createTableRow(String tableCol);
	// Оставшиеся сигнатуры
}
Setelah membuat antarmuka, kami memodifikasi kelas HtmlUserPresentationuntuk menggunakannya. Kembali ke pembuatan instance type HtmlUserPresentation, sekarang kita dapat menggunakan tipe antarmuka alih-alih tipe dasar:
IHtmlUserPresentation htmlUserPresentation = new HtmlUserPresentation();
String table = htmlUserPresentation.createTable(rowTableVals, "Login Error Status");
Membuat antarmuka memungkinkan kita dengan mudah menggunakan implementasi lain dari IHtmlUserPresentation. Misalnya, jika kita ingin menguji tipe ini, kita dapat dengan mudah mengganti tipe dasar HtmlUserPresentationdengan tipe lain yang disebut HtmlUserPresentationTest. Perubahan yang dilakukan sejauh ini membuat kode lebih mudah untuk diuji, dipelihara, dan diskalakan, namun tidak melakukan apa pun untuk digunakan kembali karena semua HtmlUserPresentationkelas yang menggunakan tipe tersebut masih mengetahui keberadaannya. Untuk menghilangkan ketergantungan langsung ini, Anda dapat meneruskan tipe antarmuka IHtmlUserPresentationke konstruktor (atau daftar parameter metode) dari kelas atau metode yang akan menggunakannya:
public UploadFile(IHtmlUserPresentation htmlUserPresentation)
Konstruktor UploadFilesekarang memiliki akses ke semua fungsionalitas tipe tersebut IHtmlUserPresentation, tetapi tidak mengetahui apa pun tentang struktur internal kelas yang mengimplementasikan antarmuka ini. Dalam konteks ini, injeksi tipe terjadi ketika sebuah instance kelas dibuat UploadFile. Tipe antarmuka IHtmlUserPresentationdapat digunakan kembali dengan meneruskan implementasi berbeda ke kelas atau metode berbeda yang memerlukan fungsionalitas berbeda.

Kesimpulan dan rekomendasi untuk memantapkan materi

Anda telah mempelajari tentang injeksi ketergantungan dan bahwa kelas-kelas dikatakan secara langsung bergantung satu sama lain ketika salah satu dari mereka membuat instance yang lain untuk mendapatkan akses ke fungsionalitas tipe target. Untuk memisahkan ketergantungan langsung antara kedua jenis tersebut, Anda harus membuat antarmuka. Antarmuka memberi suatu tipe kemampuan untuk menyertakan implementasi yang berbeda, bergantung pada konteks fungsionalitas yang diperlukan. Dengan meneruskan tipe antarmuka ke konstruktor kelas atau metode, kelas/metode yang memerlukan fungsionalitas tersebut tidak mengetahui detail apa pun tentang tipe yang mengimplementasikan antarmuka. Oleh karena itu, tipe antarmuka dapat digunakan kembali di kelas berbeda yang memerlukan perilaku serupa, namun tidak identik.
  • Untuk bereksperimen dengan injeksi ketergantungan, lihat kode Anda dari satu atau lebih aplikasi dan coba ubah tipe dasar yang sering digunakan menjadi antarmuka.

  • Ubah kelas yang secara langsung membuat instance tipe dasar ini untuk menggunakan tipe antarmuka baru ini dan meneruskannya melalui konstruktor atau daftar parameter metode kelas yang akan menggunakannya.

  • Buat implementasi pengujian untuk menguji jenis antarmuka ini. Setelah kode Anda difaktorkan ulang, DIpenerapannya akan menjadi lebih mudah, dan Anda akan melihat betapa lebih fleksibelnya aplikasi Anda dalam hal penggunaan kembali dan pemeliharaan.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION