Generic Repository
Repository<Customer> repository = new Repository<Customer>(); foreach(Customer c in repository.FetchAllMatching(CustomerAgeQuery.ForAge(19)) { }
apa kesimpulan yg dapat ditarik dari code di atas ?
oke. mulai. yg pertama adalah intentionnya jelas. Mudah dipahami. Tetapi juga dapat menimbulkan kekacauan. Overuse atau pemakaian yg berlebihan.
kita diajarkan dari dulu bahwa reusable itu adalah sesuatu yg baik. mencegah duplikasi. mulailah kita membawa2 hal tersebut ke repository yg generic.
interface IRepository<T> { IList<T> FindAllBy(IQuery<T> query); void Add(T item); void Delete(T item); ... }
Nah sekarang kita sudah memiliki editor object yg generic. Kita bisa menyimpan, delete atau apapun yg bisa dilakukan oleh IRepository. namanya juga kontrak. tul ga .. interface == contract
Tapi terkadan requirement dari setiap object berbeda. Ada object yg tidak bisa didelete. Ada juga yg tidak bisa diedit. dll. PurchaseOrder ga bisa diupdate. ShoppingCart hanya bisa dicreate. Nah bila kita menextends dari IRepository yg generic itu. Sudah pasti berbeda maknanya. Dan konstrain menjadi tidak jelas. Kabur mengenai hal2 yg dapat dilakukan pada lifecyle sebuah object. Repository berperan dalam siklus hidup object bukan??
Bisa diatasin sih .. ya sudah. klo emang ga bisa delete. throw exception saja. Not Supported Exception. mmm. Bisa aja. Tapi bagaimana dengan OO principle nya ?
Nah muncul pemikiran lain. Bikin aja interface yg lebih spesific. ICanDelete, ICanUpdate, ICanCreate. Iya. Bisa aja. Tapi code yg bisa direuse jadi sedikit. Dan mungkin saja terjadi duplikasi code.
Nah sekarang kita kembali dulu ke pengertian Repository yang sebenarnya menurut Eric Evans. Tujuan repository dibuat adalah supaya orang menganggap bahwa repository itu seakan2, seolah2, sekonyong2 adalah kumpulan dari object didalam memory. Jadi kita bisa lepas dari pikiran2 tentang persistence. Mw disimpan dimana juga ga soal. Mw di xml. Txt, database dll.
Jadi domain harus bebas dari pikiran2 dan pertimbangan2 jahat tentang persistence (bagaimana dia disimpan). Jadi domain lebih mudah ditest, bisa ditest independent, tidak tergantung framework tertentu. dan bisa dipindahkan dari satu persistence ke tempat lain. Klo sekarang make xml besok bisa cepat ditukar ke database tanpa merubah domain.
jadi repository adalah kontrak. Kontraknya berisi apa2 saja yg bisa dilakukan kepada domain terhadap persistence mechanism untuk aggregrate root yg disupportnya. Apa2an ini ? Ga ngerti ? Dengan kata lain kontrak mengenai apa yg bisa dilakuakan terhadap domain tersebut ke datastore. Terlepas dari data storenya apa . Itu urusan infrastructure. Tp kontrak tersebut baru berguna atau jelas jika dia spesifik. contohnya perbandingkanlah dua baris code berikut
Repository<T>.FindAllMatching(QueryObject o); CustomerRepository.FindCustomerByFirstName(string);
Coba perhatikan contoh yg pertama. Kontraknya tidak jelas. Karena semua ditentukan oleh query object. Jadi querynya bisa apa saja. Nah klo misalnya kita mw tau kontraknya sebenarnya apa itu bukan lagi tanggung jawab repository tetapi menjadi tanggung jawab QueryObject. Jadi kita harus melihat darimana query object tersebut dicreate. Kita mungkin bisa membuat query yg lebih spesifik tetapi mungkin saja terjadi class explotion.
Contoh yg kedua lebih jelas. Jadi kita bisa mencari customer berdasarkan nama depan.
Nah sekarang apakah kita akan mendahulukan reuse atau kontrak
Kita tetap akan menggunakan generic base repository tetapi tidak mengextendsnya. Tetapi melalui composition saja reusenya.
public interface ICustomerRepository { IEnumerable<Customer> GetCustomersWithFirstNameOf(string _Name); }
Nah kita dapat menggunakan komposisi di sini
public class CustomerRepository { private Repository<Customer> internalGenericRepository; Public IEnumerable<Customer> GetCustomersWithFirstNameOf(string _Name) { internalGenericRepository.FetchByQueryObject(new CustomerFirstNameOfQuery(_Name)); //could be hql or whatever } }
Buatlah repository se-explicit mungkin. Sehingga dengan melihat repository kita dapat mengetahui lifecylce object tersebut.