Prinsip penyongsangan kebergantungan dilaksanakan menggunakan. Penyongsangan Ketergantungan

rumah / bergaduh

Malah, semua prinsip PADAT berkait rapat dan matlamat utama mereka adalah untuk membantu mencipta perisian berskala yang berkualiti tinggi. Tetapi prinsip terakhir PADAT benar-benar menonjol terhadap mereka. Pertama, mari kita lihat rumusan prinsip ini. Jadi, prinsip penyongsangan kebergantungan (Prinsip Penyongsangan Kebergantungan - DIP): "Pergantungan pada abstraksi. Tidak ada pergantungan pada sesuatu yang khusus.. Pakar pembangunan perisian terkenal, Robert Martin, juga menonjolkan prinsip itu DIP dan membentangkannya hanya sebagai hasil daripada mengikuti prinsip lain PADAT— prinsip terbuka/tertutup dan prinsip penggantian Liskov. Ingat bahawa yang pertama mengatakan bahawa kelas tidak boleh diubah suai untuk membuat perubahan baru, dan yang kedua berkaitan dengan warisan dan menganggap penggunaan selamat jenis terbitan beberapa jenis asas tanpa melanggar operasi program yang betul. Robert Martin pada asalnya merumuskan prinsip ini seperti berikut:

satu). Modul peringkat atas tidak boleh bergantung pada modul peringkat bawah. Modul pada kedua-dua peringkat mesti bergantung pada abstraksi.

2). Abstraksi tidak boleh bergantung pada butiran. Butiran harus bergantung pada abstraksi.

Iaitu, adalah perlu untuk membangunkan kelas dari segi abstraksi, dan bukan pelaksanaan khusus mereka. Dan jika anda mengikuti prinsip OCP dan LSP, maka inilah yang akan kita capai. Oleh itu, mari kita kembali sedikit kepada pelajaran. Di sana, sebagai contoh, kami mempertimbangkan kelas bard, yang pada awalnya telah dirangkaikan ke kelas Gitar, mewakili alat muzik tertentu:

Bard kelas awam ( gitar Gitar peribadi; Bard awam(Gitar gitar) ( ini.gitar = gitar; ) main void awam() ( guitar.play(); ) )

kelas awam Bard(

gitar gitar peribadi;

awam Bard (gitar gitar)

ini. gitar = gitar ;

permainan kekosongan awam ()

gitar. main();

Jika kami ingin menambah sokongan untuk alat muzik lain pada kelas ini, maka kami entah bagaimana perlu mengubah suai kelas ini. Ini jelas melanggar prinsip OCP. Dan anda mungkin telah menyedari bahawa ini juga merupakan pelanggaran prinsip DIP, kerana dalam kes kami abstraksi kami ternyata bergantung pada butiran. Dari sudut pandangan pengembangan selanjutnya kelas kami, ini tidak bagus sama sekali. Untuk menjadikan kelas kami memenuhi syarat prinsip OCP kami telah menambah antara muka pada sistem alat, yang melaksanakan kelas khusus yang mewakili jenis alat muzik tertentu.

Fail Instrument.java:

Instrumen antara muka awam (void play(); )

Instrumen antara muka awam(

voidplay();

Fail Guitar.java:

class Guitar implements Instrument( @Override public void play() ( System.out.println("Main Gitar!"); ) )

kelas Guitar melaksanakan Instrumen(

@Override

permainan kekosongan awam ()

Sistem. keluar . println("Main Gitar!");

Fail lute.java:

Lute kelas awam melaksanakan Instrumen( @Override public void play() ( System.out.println("Main Lute!"); ) )

Lute kelas awam melaksanakan Instrumen(

@Override

permainan kekosongan awam ()

Sistem. keluar . println("Main Lute!");

Selepas itu kami menukar kelas bard supaya, jika perlu, kita boleh menggantikan pelaksanaan dengan tepat yang kita perlukan. Ini membawa fleksibiliti tambahan kepada sistem yang dicipta dan mengurangkan kesepaduannya (kebergantungan kelas yang kuat antara satu sama lain).

Bard kelas awam ( instrumen Instrumen peribadi; Bard awam() ( ) main void awam() ( instrument.play(); ) set void awamInstrument(Instrument instrument) ( this.instrument = instrument; ) )

kelas awam Bard(

instrumen Instrumen persendirian ;

2 balasan

Perkara yang baik - penyongsangan perkataan agak mengejutkan (memandangkan selepas menggunakan DIP , modul pergantungan peringkat rendah nampaknya kini tidak bergantung pada modul pemanggil peringkat lebih tinggi: sama ada pemanggil atau tanggungan kini lebih longgar digandingkan melalui abstraksi tambahan ).

Anda mungkin bertanya mengapa saya menggunakan perkataan "inversi". Secara terang-terangan, ini adalah kerana kaedah pembangunan perisian yang lebih tradisional seperti analisis berstruktur dan reka bentuk cenderung untuk mencipta struktur perisian di mana modul peringkat tinggi bergantung pada modul peringkat rendah dan di mana abstraksi bergantung pada butiran. Malah, salah satu tujuan kaedah ini adalah untuk mentakrifkan hierarki subrutin yang menerangkan cara modul peringkat tinggi membuat panggilan ke modul peringkat rendah.... Oleh itu, struktur pergantungan program berorientasikan objek yang direka dengan baik adalah "terbalik" berkenaan dengan struktur pergantungan, yang biasanya hasil daripada kaedah prosedur tradisional.

Satu perkara yang perlu diberi perhatian apabila membaca kertas Uncle Bob tentang DIP ialah C++ tidak (dan pada masa penulisan, tidak) mempunyai antara muka, jadi mencapai abstraksi ini dalam C++ biasanya dicapai melalui kelas asas maya abstrak/tulen, sedangkan di Java atau C# abstraksi untuk melonggarkan gandingan biasanya untuk menyahikat dengan mengabstrakkan antara muka daripada kebergantungan dan mengikat modul peringkat lebih tinggi kepada antara muka.

Sunting Hanya untuk menjelaskan:

"Di sesetengah tempat saya juga melihat ia dipanggil penyongsangan pergantungan"

Penyongsangan: Terbalikkan pengurusan pergantungan daripada aplikasi kepada bekas (seperti Spring).

Suntikan Ketergantungan:

Daripada menulis corak kilang, bagaimana pula dengan menyuntik objek terus ke dalam kelas pelanggan. Jadi mari kita biarkan kelas pelanggan merujuk kepada antara muka dan kita sepatutnya dapat menyuntik jenis konkrit ke dalam kelas pelanggan. Dengan ini, kelas pelanggan tidak perlu menggunakan kata kunci baharu dan diasingkan sepenuhnya daripada kelas konkrit.

Bagaimana pula dengan penyongsangan kawalan (IoC)?

Dalam pengaturcaraan tradisional, aliran logik perniagaan ditakrifkan oleh objek yang ditugaskan secara statik antara satu sama lain. Dengan penyongsangan kawalan, aliran bergantung pada graf objek yang diwujudkan oleh pemasang dan dimungkinkan oleh interaksi objek yang ditakrifkan melalui abstraksi. Proses penggabungan dicapai melalui suntikan pergantungan, walaupun ada yang berpendapat bahawa menggunakan pencari perkhidmatan juga menyediakan penyongsangan kawalan.

Penyongsangan kawalan sebagai panduan reka bentuk berfungsi untuk tujuan berikut:

  • Terdapat penyahgandingan pelaksanaan tugas tertentu daripada pelaksanaan.
  • Setiap modul boleh memberi tumpuan kepada apa yang dimaksudkan untuknya.
  • Modul tidak membuat sebarang andaian tentang perkara yang dilakukan oleh sistem lain, tetapi bergantung pada kontrak mereka.
  • Menggantikan modul tidak menjejaskan modul lain.

Lihat untuk maklumat lanjut.

Kemas kini terakhir: 03/11/2016

Prinsip Inversi Ketergantungan(Prinsip Penyongsangan Ketergantungan) digunakan untuk mencipta entiti ganding longgar yang mudah untuk diuji, diubah suai dan dikemas kini. Prinsip ini boleh dirumuskan seperti berikut:

Modul peringkat atas tidak boleh bergantung pada modul peringkat rendah. Kedua-duanya mesti bergantung pada abstraksi.

Abstraksi tidak boleh bergantung pada butiran. Butiran harus bergantung pada abstraksi.

Untuk memahami prinsip, pertimbangkan contoh berikut:

Buku Kelas ( Teks rentetan awam ( get; set; ) Pencetak ConsolePrinter awam ( get; set; ) public void Print() ( Printer.Print(Teks); ) ) class ConsolePrinter ( public void Print(string text) ( Console.WriteLine (teks); ))

Kelas Buku, yang mewakili buku, menggunakan kelas ConsolePrinter untuk mencetak. Apabila ditakrifkan seperti ini, kelas Buku bergantung pada kelas ConsolePrinter. Selain itu, kami telah mentakrifkan dengan tegas bahawa mencetak buku hanya boleh dilakukan pada konsol menggunakan kelas ConsolePrinter. Pilihan lain, sebagai contoh, output ke pencetak, output ke fail atau menggunakan beberapa elemen antara muka grafik - semua ini dikecualikan dalam kes ini. Abstraksi pencetakan buku tidak terpisah daripada butiran kelas ConsolePrinter. Semua ini adalah pelanggaran prinsip penyongsangan kebergantungan.

Sekarang mari kita cuba membawa kelas kita selaras dengan prinsip penyongsangan kebergantungan dengan memisahkan abstraksi daripada pelaksanaan peringkat rendah:

Interface IPprinter ( void Print(string text); ) class Book ( public string Text ( get; set; ) public IPprinter Printer ( get; set; ) public Book(IPrinter printer) ( this.Printer = printer; ) public void Print( ) ( Printer.Print(Teks); ) ) class ConsolePrinter: IPrinter ( public void Print(string text) ( Console.WriteLine("Cetak ke Console"); ) ) class HtmlPrinter: IPrinter ( public void Print(string text) ( Console.WriteLine("Cetak ke html"); ) )

Sekarang abstraksi percetakan buku diasingkan daripada pelaksanaan konkrit. Akibatnya, kedua-dua kelas Buku dan kelas ConsolePrinter bergantung pada abstraksi IPrinter. Di samping itu, kini kami juga boleh membuat pelaksanaan peringkat rendah tambahan bagi abstraksi IPrinter dan menerapkannya secara dinamik dalam program:

Buku buku = Buku baharu(Pencetak Konsol baharu()); book.Cetak(); book.Printer = new HtmlPrinter(); book.Cetak();

Penyongsangan ketergantungan adalah salah satu simpulan bahasa pengaturcaraan yang paling penting. Terdapat sedikit penerangan mengenai simpulan bahasa (prinsip) ini di Internet berbahasa Rusia. Jadi saya memutuskan untuk cuba membuat penerangan. Saya akan melakukan contoh dalam Java, pada masa ini lebih mudah bagi saya, walaupun prinsip penyongsangan kebergantungan boleh digunakan untuk mana-mana bahasa pengaturcaraan.

Penerangan ini dibangunkan bersama Vladimir Matveev sebagai persediaan untuk kelas dengan pelajar Java.

Artikel lain dari siri ini:

Mari kita mulakan dengan definisi "kebergantungan". Apakah ketagihan? Jika kod anda menggunakan beberapa kelas secara dalaman atau secara eksplisit memanggil kaedah statik bagi sesetengah kelas atau fungsi, ini ialah pergantungan. Biar saya terangkan dengan contoh:

Di bawah kelas A di dalam kaedah yang dipanggil someMethod() secara eksplisit mencipta objek kelas B dan mengakses kaedahnya someMethodOfB()

Kelas awam A ( void someMethod() ( B b = new B(); b.someMethodOfB(); ) )

Begitu juga, sebagai contoh, kelas B merujuk secara eksplisit kepada medan statik dan kaedah kelas Sistem:

Kelas awam B ( void someMethodOfB() ( System.out.println("Hello world"); ) )

Dalam semua kes di mana mana-mana kelas (jenis A) sendiri mencipta mana-mana kelas (jenis B) atau secara eksplisit mengakses medan statik atau ahli kelas, ini dipanggil lurus ketagihan. Itu. penting: jika kelas di dalam dirinya berfungsi di dalam dirinya dengan kelas lain, ini adalah kebergantungan. Jika dia juga mencipta kelas ini di dalam dirinya, maka ini lurus ketagihan.

Apa yang salah dengan kebergantungan langsung? Kebergantungan langsung adalah buruk kerana kelas yang secara bebas mencipta kelas lain di dalam dirinya sendiri "terikat" dengan kelas ini. Itu. jika ditulis dengan jelas bahawa B = new B(); , maka kelas A akan sentiasa berfungsi dengan kelas B dan tiada kelas lain. Atau jika tertera System.out.println("..."); maka kelas akan sentiasa output ke System.out dan tiada tempat lain.

Untuk kelas kecil, kebergantungan tidaklah mengerikan. Kod sedemikian mungkin berfungsi dengan baik. Tetapi dalam beberapa kes, untuk membolehkan kelas A anda berfungsi secara universal dalam persekitaran kelas yang berbeza, ia mungkin memerlukan pelaksanaan kelas pergantungan yang lain. Itu. anda perlukan, sebagai contoh, bukan kelas B , tetapi kelas lain dengan antara muka yang sama, atau bukan System.out , tetapi, sebagai contoh, output kepada logger (contohnya, log4j).

Kebergantungan langsung boleh dipaparkan secara grafik seperti ini:

Itu. apabila anda mencipta kelas A dalam kod anda: A a = new A(); sebenarnya, bukan satu kelas A dicipta, tetapi keseluruhan hierarki kelas bergantung, contohnya dalam gambar di atas. Hierarki ini adalah "tegar": tanpa mengubah kod sumber kelas individu, tiada kelas dalam hierarki boleh diganti. Oleh itu, kelas A dalam pelaksanaan sebegini kurang boleh disesuaikan dengan persekitaran yang berubah-ubah. Kemungkinan besar, ia tidak akan dapat digunakan dalam mana-mana kod, kecuali untuk kod khusus yang anda tulis.

Untuk memisahkan kelas A daripada kebergantungan tertentu, gunakan suntikan pergantungan. Apakah suntikan pergantungan? Daripada mencipta kelas yang dikehendaki dalam kod secara eksplisit, kebergantungan dihantar ke kelas A melalui pembina:

Kelas awam A ( swasta akhir B b; awam A(B b) ( ini.b = b; ) awam tidak sah someMethod() ( b.someMethodOfB(); ) )

Itu. kelas A kini mendapat pergantungannya melalui pembina. Sekarang, untuk mencipta kelas A, anda perlu mencipta kelas bergantungnya terlebih dahulu. Dalam kes ini, ia adalah B:

B b = baru B(); A a = baru A(b); a.someMethod();

Jika prosedur yang sama diulang untuk semua kelas, i.e. luluskan contoh kelas D kepada pembina kelas B , kepada pembina kelas D — kebergantungannya E dan F , dsb., maka anda akan mendapat kod, semua kebergantungan yang dibuat dalam susunan terbalik:

G g = baru G(); H h = baru H(); F f = baru(g,h); E e = baru E(); D d = baharu D(e,f); B b = baru B(d); A a = baru A(b); a.someMethod();

Secara grafik, ini boleh dipaparkan seperti ini:

Jika anda membandingkan 2 gambar - gambar di atas dengan kebergantungan langsung dan gambar kedua dengan suntikan ketergantungan - anda dapat melihat bahawa arah anak panah telah berubah ke arah yang bertentangan. Atas sebab ini, simpulan bahasa dipanggil "inversi ketergantungan". Dalam erti kata lain, penyongsangan kebergantungan terletak pada fakta bahawa kelas tidak mencipta kebergantungan sendiri, tetapi menerimanya dalam bentuk yang dicipta dalam pembina (atau sebaliknya).

Mengapa penyongsangan kebergantungan adalah baik? Dengan penyongsangan kebergantungan, anda boleh menggantikan semua kebergantungan dalam kelas tanpa mengubah kodnya. Dan ini bermakna bahawa kelas A anda boleh dikonfigurasikan secara fleksibel untuk digunakan dalam atur cara lain daripada program yang asalnya ia ditulis. Itu. Prinsip penyongsangan kebergantungan (kadangkala dipanggil prinsip suntikan kebergantungan) adalah kunci untuk membina kod yang fleksibel, modular, boleh digunakan semula.

Kelemahan suntikan pergantungan juga boleh dilihat pada pandangan pertama - objek kelas yang direka bentuk menggunakan corak ini sukar untuk dibina. Oleh itu, suntikan kebergantungan (penyongsangan) biasanya digunakan bersama dengan beberapa perpustakaan yang direka untuk memudahkan tugas ini. Contohnya, salah satu perpustakaan Google Guice. Cm. .

© 2022 skudelnica.ru -- Cinta, pengkhianatan, psikologi, perceraian, perasaan, pertengkaran