Pola desain yang sering saya hindari: Pola repositori

Pola desain memberikan solusi yang terbukti untuk masalah dunia nyata yang dihadapi dalam desain perangkat lunak. Pola Repositori digunakan untuk memisahkan logika bisnis dan lapisan akses data di aplikasi Anda.

Lapisan akses data biasanya berisi kode dan metode khusus penyimpanan untuk mengoperasikan data ke dan dari penyimpanan data. Lapisan akses data yang abstrak repositori dapat berupa ORM (yaitu, Entity Framework atau NHibernate), file XML, layanan web, dll. Bahkan dapat berupa kumpulan pernyataan SQL.

Dalam menggunakan pola desain Repositori, lapisan logika bisnis aplikasi Anda tidak perlu memiliki pengetahuan tentang bagaimana persistensi data terjadi di bawahnya. Pada dasarnya, repositori menjadi perantara antara domain dan lapisan pemetaan data aplikasi Anda. Ini seharusnya memberi Anda enkapsulasi tentang cara data sebenarnya disimpan di lapisan penyimpanan data.

Pola Repositori mungkin bermanfaat jika Anda memiliki banyak entitas dan memiliki banyak kueri kompleks untuk dikerjakan dengan entitas tersebut. Lapisan abstraksi tambahan dalam hal ini dapat membantu Anda menghilangkan duplikasi logika kueri.

Repositori generik

Repositori generik adalah tipe yang terdiri dari serangkaian metode umum untuk melakukan operasi CRUD. Namun, ini hanyalah anti pola dan sering digunakan dengan Entity Framework untuk mengabstraksi panggilan ke lapisan akses data. Menurut pendapat saya, menggunakan repositori generik adalah generalisasi yang terlalu jauh. Ide yang buruk untuk mengabstraksi panggilan ke Entity Framework menggunakan repositori generik.

Izinkan saya menjelaskan ini dengan sebuah contoh.

Daftar kode berikut menggambarkan repositori generik - ini berisi metode umum untuk melakukan operasi CRUD dasar.

public interface IRepository

   {

       IEnumerable GetAll();

       T GetByID(int id);

       void Add(T item);

       void Update(T item);

       void Delete(T item);

   }

Untuk membuat repositori tertentu, Anda perlu mengimplementasikan antarmuka generik seperti yang ditunjukkan dalam daftar kode di bawah ini.

public class AuthorRepository : IRepository

   {

       //Implemented methods of the IRepository interface

   }

Seperti yang Anda lihat, untuk membuat kelas repositori tertentu, Anda perlu mengimplementasikan setiap metode dari antarmuka repositori generik. Kelemahan utama dari pendekatan ini adalah Anda harus membuat repositori baru untuk setiap entitas.

Berikut adalah kelemahan lain dari pendekatan ini: Maksud dasar dari pola repositori adalah untuk memisahkan lapisan domain Anda dari bagaimana data sebenarnya disimpan oleh lapisan akses data. Berikut adalah versi terbaru dari kelas repositori yang baru saja kita buat.

public class AuthorRepository : IRepository

   {

       private AuthorContext dbContext;

       //Methods of the IRepository interface

   }

Seperti yang Anda lihat dalam daftar kode yang diberikan sebelumnya, AuthorRepository memerlukan instance AuthorContext untuk melakukan operasi CRUD yang dimaksudkan. Jadi, di mana decouplingnya? Idealnya, lapisan domain tidak memiliki pengetahuan tentang logika persistensi.

Lapisan abstraksi ekstra

Model domain dan model ketekunan dalam aplikasi memiliki tanggung jawab yang sangat berbeda. Sementara perilaku model sebelumnya, yaitu memodelkan masalah kehidupan nyata dan solusi untuk masalah tersebut, yang terakhir digunakan untuk memodelkan bagaimana data aplikasi sebenarnya disimpan di penyimpanan data.

Maksud dari pola repositori adalah untuk mengabstraksi logika persistensi dan menyembunyikan implementasi internal tentang bagaimana data disimpan. Operasi repositori harus cukup ekspresif dan tidak generik. Anda tidak bisa memiliki repositori yang generik dan yang bisa berisi operasi yang bisa muat dalam skenario apa pun. Ini menjadi abstraksi yang tidak perlu dan karenanya membuat pola repositori generik menjadi anti-pola. Anda dapat memodelkan semua objek domain Anda dengan cara yang sama. Repositori generik tidak mendefinisikan kontrak yang berarti dan Anda akan membutuhkan repositori khusus yang memperluas repositori generik Anda dan menyediakan rangkaian operasi spesifik yang berarti bagi entitas tertentu itu.

Sekarang setelah Anda memiliki beberapa teknologi persistensi data yang matang (NHibernate, Entity Framework, dll.), Mengapa Anda tetap membutuhkan lapisan abstraksi tambahan ini? Sebagian besar teknologi ORM dewasa yang tersedia saat ini memiliki kemampuan yang sama. Dalam mencoba menggunakan repositori, Anda cukup menambahkan lapisan abstraksi tambahan tanpa alasan apa pun. Sebagai contoh, Anda mungkin memerlukan metode seperti berikut untuk AuthorRepository Anda.

FindAuthorById()

FindAuthorByCountry()

Ini menjadi lebih buruk karena Anda memiliki lebih banyak metode dan pencarian yang kompleks - Anda akan berakhir dengan memiliki repositori yang akan secara dekat memetakan dengan lapisan penyimpanan persisten yang digunakan di bawahnya.