Spring : Dependency Inversion : Precursor ke Dependency Injection

Oleh : Reza Ervani

بسم الله الرحمن الرحيم

Referensi : http://www.springbyexample.org/examples/core-concepts.html

Dependency Inversion: Pengantar ke Dependency Injection

Referensi pertama ke apa yang kemudian disebut Dependency Injection muncul pada tahun 1994 dalam paper oleh Robert C. Martin berjudul “The Dependency Inversion Principle”.

Dalam “The Dependency Inversion Principle” (DIP), penulis menyatakan tiga hal yang mendefinisikan faktor “pengkodean yang buruk”

In “The Dependency Inversion Principle” (or DIP), the author states the three defining factors of “bad code”:

  • Susah dirubah karena setiap perubahan memberikan efek pada banyak bagian dari sistem (Rigidity)
  • Saat kita membuat perubahan, bagian yang tidak diharapkan pada sistem menjadi rusak (Fragility)
  • Susah untuk digunakan ulang pada aplikasi lain dikarenakan tidak dapat dipisahkan dari aplikasinya (Immobility)

Menurut Martin, ketergantungan satu sama lain (interdependency) menyebabkan masalah pengkodean tersebut (kita akan menyebutnya RFI untuk Rigidity, Fragility dan Immobility). Untuk memperbaiki masalah RFI dalam kode OO kita, DIP memiliki dua aturan dasar :

Modul level tinggi seharusnya tidak bergantung pada modul level rendah, keduanya seharusnya bergantung pada abstraksi.

Dengan kata lain, modul level tinggi – yang berisi logik bisnis kita dan semua bagian penting dari aplikasi kita – seharusnyat tidak bergantung pada komponen di level lebih rendah. Alasan untuk ini karena komponen level lebih rendah cenderung berubah, dan perubahan itu dapat berefek pada komponen level tinggi. Hal ini mendefinisikan konsep di belakang dependency inversion, yakni kebijaksanaan untuk mencegah modul dengan level yang lebih tinggi bergantung pada modul di level yang lebih rendah, karena itu adalah ide yang buruk.

Abstraksi seharusnya tidak bergantung pada detail, detail seharusnya bergantung pada abstraksi

Ini adalah cara lain untuk mengatakan bahwa sebelum kita memulai kode ke abstraksi – class interface atau abstrak – kita seharusnya mengetahui terlebih dahulu prilaku kode dan bekerja mundur. Interface atau abstraksi kita seharusnya memenuhi irisan kebutuhan antara logika bisnis dan prilaku umum dari modul-modul level yang lebih rendah. Kita sebaiknya juga meninggalkan detail-detail terkait bagaimana prilaku tersebut diimplementasikan pada class-class implementasi.

Contoh sederhana ini menunjukkan program voting untuk menunjukkan suatu program yang tidak menggunakan DIP


package org.springbyexample.vote;

public class VotingBooth {

VoteRecorder voteRecorder = new VoteRecorder();

public void vote(Candidate candidate) {
voteRecorder.record(candidate);
}

class VoteRecorder {
Map hVotes = new HashMap();

public void record(Candidate candidate) {
int count = 0;

if (!hVotes.containsKey(candidate)){
hVotes.put(candidate, count);
} else {
count = hVotes.get(candidate);
}

count++; 1

hVotes.put(candidate, count); 2

}
}

}

Program ini :

  1. Melakukan increment pada variabel count
  2. Menambahkan kandidat dan vote ke Map

Pada contoh tersebut, class VotingBooth secara langsung bergantung pada VoteRecorder, yang tidak memiliki abstraksi dan adalah merupakan class implementasi

Suatu versi dependency “terbalik” dari kode ini mungkin akan tampak sedikit berbeda. Pertama, kita akan mendefinisikan interface VoteRecorder :


package org.springbyexample.vote;

public interface VoteRecorder {

public void record(Candidate candidate) ;

}

Dan class implementasi kita

LocalVoteRecorder, yang mengimplementasikan interface VoteRecorder :


package org.springbyexample.vote;

public class LocalVoteRecorder implements VoteRecorder {

Map hVotes = new HashMap();

public void record(Candidate candidate) {
int count = 0;

if (!hVotes.containsKey(candidate)){
hVotes.put(candidate, count);
} else {
count = hVotes.get(candidate);
}

count++;

hVotes.put(candidate, count);
}

}

Dan class VotingBooth :


package org.springbyexample.vote;

public class VotingBooth {

VoteRecorder recorder = null;

public void setVoteRecorder(VoteRecorder recorder) {
this.recorder = recorder;
}

public void vote(Candidate candidate) {
recorder.record(candidate);
}

}

Kini class LocalVoteRecorder – class implementasi dari interface VoteRecorder – sepenuhnya terpisah dari class VotingBooth. Kita telah menghilangkan seluruh refernsi hard-coded ke class-class dengan level yang lebih rendah. Berdasarkan aturan DIP, inilah yang kita butuhkan untuk menghindarkan kode kita dari RFI.

Bagaimanapun, ada satu masalah dengan implementasi ini. Kita tidak memiliki metode main. Kita jelas membutuhkan satu dalam rangka menjalankan aplikasi kita, dan di suatu tempat di metode main kita perlu menginstansiasi LocalVoteRecorder.

Dengan menginstansiasi LocalVoteRecorder di metode main kita, maka kita akan melanggar peraturan #1 Dependency Inversion. Kita sudah mengkode ke abstraksi, kita sudah mengintegrasikan perubahan kita, tetapi aplikasi kita akan tetap memiliki suatu ketergantungan ke class-class yang lebih rendah.

Bersambung

About Reza Ervani 430 Articles
Adalah pendiri programming.rezaervani.com -

Be the first to comment

Leave a Reply

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.