Reka corak yang sering saya elakkan: Corak repositori

Corak reka bentuk memberikan penyelesaian yang terbukti untuk masalah dunia nyata yang dihadapi dalam reka bentuk perisian. Corak Repositori digunakan untuk mencabut logik perniagaan dan lapisan akses data dalam aplikasi anda.

Lapisan akses data biasanya mengandungi kod dan kaedah khusus penyimpanan untuk beroperasi pada data ke dan dari penyimpanan data. Lapisan akses data yang abstrak repositori boleh menjadi ORM (iaitu, Entity Framework atau NHibernate), fail XML, perkhidmatan web, dan lain-lain. Ia bahkan boleh menjadi kumpulan penyataan SQL.

Dalam menggunakan corak reka bentuk Repositori, lapisan logik perniagaan aplikasi anda tidak perlu mengetahui bagaimana ketekunan data berlaku di bawahnya. Pada dasarnya, repositori menjadi perantara antara domain dan lapisan pemetaan data aplikasi anda. Ini semestinya memberi anda enkapsulasi tentang bagaimana data sebenarnya ada di lapisan penyimpanan data.

Corak Repositori mungkin bermanfaat di mana anda mempunyai banyak entiti dan mempunyai banyak pertanyaan kompleks untuk bekerja dengan entiti tersebut. Lapisan abstraksi tambahan dalam kes ini dapat membantu anda menghilangkan penduaan logik pertanyaan.

Repositori generik

Repositori generik adalah jenis yang terdiri daripada sekumpulan kaedah generik untuk menjalankan operasi CRUD. Walau bagaimanapun, ia hanyalah satu lagi corak anti dan sering digunakan dengan Entity Framework untuk mengaburkan panggilan ke lapisan akses data. Pada pendapat saya, menggunakan repositori generik adalah generalisasi terlalu jauh. Sebaiknya abstrak panggilan ke Entity Framework menggunakan repositori generik.

Mari saya jelaskan ini dengan contoh.

Penyenaraian kod berikut menggambarkan repositori generik - ia mengandungi kaedah generik untuk menjalankan operasi CRUD asas.

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 melaksanakan antara muka generik seperti yang ditunjukkan dalam senarai kod di bawah.

public class AuthorRepository : IRepository

   {

       //Implemented methods of the IRepository interface

   }

Seperti yang anda lihat, untuk membuat kelas repositori tertentu, anda perlu melaksanakan setiap kaedah antara muka repositori generik. Kelemahan utama pendekatan ini ialah anda perlu membuat repositori baru untuk setiap entiti.

Berikut adalah kelemahan lain dari pendekatan ini: Tujuan asas corak repositori adalah untuk memisahkan lapisan domain anda dari bagaimana data sebenarnya diteruskan oleh lapisan akses data. Berikut adalah versi kemas kini kelas repositori yang baru kami buat.

public class AuthorRepository : IRepository

   {

       private AuthorContext dbContext;

       //Methods of the IRepository interface

   }

Seperti yang anda lihat dalam senarai kod yang diberikan sebelumnya, AuthorRepository memerlukan instance AuthorContext untuk menjalankan operasi CRUD yang dimaksudkan. Jadi, di manakah pemutusannya? Sebaik-baiknya, lapisan domain seharusnya tidak mempunyai pengetahuan mengenai logik kegigihan.

Lapisan abstraksi tambahan

Model domain dan model kegigihan dalam aplikasi mempunyai tanggungjawab yang berbeza. Walaupun perilaku model sebelumnya, misalnya, memodelkan masalah kehidupan nyata dan penyelesaian untuk masalah tersebut, yang terakhir digunakan untuk memodelkan bagaimana data aplikasi sebenarnya disimpan di penyimpanan data.

Maksud corak repositori adalah untuk menyusun logik kegigihan dan menyembunyikan pelaksanaan dalaman bagaimana data tersebut berterusan. Operasi repositori harus cukup ekspresif dan tidak bersifat generik. Anda tidak boleh mempunyai repositori yang bersifat generik dan yang boleh mengandungi operasi yang dapat dimasukkan dalam senario apa pun. Ini menjadi abstraksi yang tidak perlu dan dengan itu menjadikan corak repositori generik sebagai anti-pola. Anda boleh memodelkan semua objek domain anda dengan cara yang sama. Repositori generik tidak menentukan kontrak yang bermakna dan anda sekali lagi memerlukan repositori khusus yang memperluas repositori generik anda dan menyediakan kumpulan operasi khusus yang bermakna bagi entiti tersebut.

Sekarang kerana anda mempunyai beberapa teknologi ketekunan data yang matang (NHibernate, Entity Framework, dll) di sekitar, mengapa anda memerlukan lapisan tambahan ini? Sebilangan besar teknologi ORM matang yang ada sekarang mempunyai kemampuan yang sama. Dalam mencuba menggunakan repositori, anda hanya menambahkan lapisan abstraksi tambahan tanpa sebab. Sebagai contoh, anda mungkin memerlukan kaedah seperti berikut untuk AuthorRepository anda.

FindAuthorById()

FindAuthorByCountry()

Perkara ini menjadi semakin teruk kerana anda mempunyai lebih banyak kaedah dan carian yang kompleks - anda akan mempunyai repositori yang akan dipetakan dengan rapat dengan lapisan penyimpanan berterusan yang digunakan di bawahnya.