Kapan menggunakan pola repositori

20

Saya telah membaca baru-baru ini bahwa bukan praktik yang baik untuk menggunakan pola repositori dalam hubungannya dengan ORM. Dari pemahaman saya ini adalah karena abstraksi yang mereka berikan atas database SQL terlalu bocor untuk dikandung oleh polanya.

Saya punya beberapa pertanyaan tentang ini:

  1. Apa yang Anda lakukan jika Anda ingin keluar dari ORM? Anda akan memiliki kode spesifik ORM dalam aplikasi Anda jika Anda tidak memuatnya dalam repositori.

  2. Apakah pola repositori masih valid ketika tidak menggunakan ORM dan Anda menggunakan ADO.NET untuk mengakses data dan mengisi sendiri data objek?

  3. Jika Anda menggunakan ORM tetapi bukan pola repositori di mana Anda menyimpan kueri yang biasa digunakan? Apakah bijaksana untuk mewakili setiap permintaan sebagai kelas dan memiliki semacam pabrik permintaan untuk membuat instance?

pengguna1450877
sumber
1
1) Anda tidak akan pernah bisa menukar ORM karena perilaku mereka yang berbeda, bahkan jika keduanya mendukung LINQ, mereka akan berperilaku cukup berbeda untuk aplikasi Anda untuk istirahat. misalnya perilaku pemuatan yang malas, pelacakan yang kotor, proxy hantu dll. Namun menyenangkan untuk dapat menukar ORM dengan implementasi in-mem untuk pengujian ..
Roger Johansson
Untuk apa nilainya, pendapat saya tentang diskusi Repositori / ORM ada di sini: stackoverflow.com/questions/13180501/…
Eric King
Di mana Anda membaca bahwa ini adalah praktik yang buruk?
Dave Hillier

Jawaban:

3

1) Benar, tetapi seberapa sering Anda mengganti ORM?
2) Saya akan mengatakan demikian, karena konteks ORM adalah semacam repositori dan menyembunyikan banyak pekerjaan yang melibatkan pembuatan kueri, pengambilan data, pemetaan, dll. Jika Anda tidak menggunakan ORM, logika itu masih harus berada di suatu tempat. Saya tidak tahu apakah itu akan memenuhi syarat sebagai pola repositori dalam arti kata yang paling ketat sekalipun ...
3) Mengenkripsi pertanyaan adalah sesuatu yang sering saya lihat, tetapi itu biasanya lebih untuk tujuan pengujian / penghentian. Selain itu, saya akan berhati-hati ketika menggunakan kembali kueri di berbagai bagian aplikasi, karena Anda berisiko membuat ketergantungan pada sesuatu yang dapat berubah n-kali (n menjadi jumlah tempat di mana Anda menggunakan kueri).

Stefan Billiet
sumber
1
1) Anda mengajukan pertanyaan yang salah. Tidak masalah seberapa sering, hanya harus sekali saja. Mengingat jumlah opsi ORM yang tersedia, mungkin ada satu yang lebih baik daripada apa yang sudah Anda gunakan. Pertanyaannya sekarang menjadi: apa yang terjadi ketika Anda melakukannya? Repositori memberi Anda abstraksi yang bagus. Saya pernah ke sana dan saya berharap saya membuat abstraksi seperti itu sejak awal.
devnull
3
@ Devnull saya tidak setuju. Jika itu akan terjadi paling banyak sekali, saya akan menganggapnya sebagai risiko yang dapat diterima. Jika Anda takut membuat pilihan yang salah: bereksperimen lebih banyak sebelum berkomitmen untuk melakukan satu. Secara teori, abstraksi semacam itu kedengarannya bagus, tetapi dalam praktiknya Anda akhirnya menciptakan kembali sebagian besar api ORM Anda, semua karena Anda akhirnya dapat memilih yang lain suatu hari nanti, di suatu tempat. Bagi saya, itu adalah usaha yang sia-sia, kode yang berlebihan dan lebih banyak kode yang Anda sendiri harus pertahankan dan jamin. Selain itu, mengganti ORM seharusnya tidak memengaruhi seluruh aplikasi; belajar menempatkan batas domain.
Stefan Billiet
Perubahan ORM bukan satu-satunya alasan repositori. Jika Anda perlu memperkenalkan cache [didistribusikan] di aplikasi Anda - semua perubahan akan dilakukan dalam repositori dan BL Anda tidak akan berubah karena perubahan lapisan akses data.
Valery
bukankah cache terdistribusi dibangun ke dalam ORM dalam banyak kasus?
user1450877
Saya pikir itu tergantung pada ORM. Anda dapat memutuskan untuk menggunakan ORM yang lebih ringan daripada NHibernate atau EF.
Valery
2

1) Apa yang Anda lakukan jika Anda ingin keluar dari ORM, Anda akan memiliki kode ORM spesifik dalam aplikasi Anda jika Anda tidak memuatnya dalam repositori.

Saya belum dalam posisi di mana perusahaan tiba-tiba memutuskan untuk beralih teknologi akses data. Jika ini terjadi, beberapa pekerjaan akan diperlukan. Saya cenderung abstrak operasi akses data melalui antarmuka. Repositori adalah salah satu cara untuk menyelesaikan ini.

Saya kemudian akan memiliki majelis berbeda untuk implementasi konkret dari lapisan akses data saya. Misalnya, saya mungkin punya:

Company.Product.Datadan Company.Product.Data.EntityFrameworkmajelis. Perakitan pertama akan digunakan sepenuhnya untuk antarmuka, ketika yang lain akan menjadi implementasi konkret dari logika akses data Entity Framework.

2) Apakah pola repositori masih valid ketika tidak menggunakan ORM dan Anda menggunakan ADO.net untuk mengakses data dan mengisi sendiri data objek?

Saya pikir itu terserah Anda untuk memutuskan pola mana yang valid atau tidak. Saya telah menggunakan pola repositori di lapisan presentasi. Satu hal yang perlu diingat adalah bahwa orang suka membuang tanggung jawab ke dalam repositori. Sebelum Anda menyadarinya, kelas repositori Anda akan menari, menyanyi dan melakukan semua hal. Anda ingin menghindari ini.

Saya telah melihat kelas repositori yang dimulai dengan memiliki tanggung jawab GetAll, GetById, Update, dan Delete, yang tidak masalah. Pada saat proyek selesai, kelas yang sama memiliki banyak metode (tanggung jawab) yang seharusnya tidak pernah ada. Misalnya GetByForename, GetBySurname, UpdateWithExclusions, dan segala macam hal gila.

Di sinilah kueri dan perintah berperan.

3) Jika Anda menggunakan ORM tetapi bukan pola repositori di mana Anda menyimpan kueri yang biasa digunakan. Apakah bijaksana untuk mewakili setiap permintaan sebagai kelas dan memiliki semacam pabrik permintaan untuk membuat instance?

Saya pikir itu ide yang sangat bagus untuk menggunakan kueri dan perintah alih-alih repositori. Saya melakukan hal berikut:

  • Tetapkan antarmuka untuk kueri. Ini akan membantu Anda menguji unit. Misalnyapublic interface IGetProductsByCategoryQuery { ... }

  • Tetapkan implementasi konkret untuk kueri. Anda akan dapat menyuntikkan ini melalui kerangka kerja IoC pilihan Anda. Misalnyapublic class GetProductsByCategoryQuery : IGetProductsByCategoryQuery

Sekarang alih-alih mencemari repositori dengan banyak tanggung jawab, saya hanya mengelompokkan pertanyaan saya ke dalam ruang nama. Misalnya, antarmuka untuk kueri di atas dapat hidup di:Company.SolutionName.Products.Queries dan implementasinya dapat hidupCompany.SolutionName.Products.Queries.Implementation

Ketika datang untuk memperbarui atau menghapus data, saya menggunakan pola perintah dengan cara yang sama.

Beberapa mungkin tidak setuju dan mengatakan bahwa sebelum proyek selesai Anda akan memiliki lusinan kelas dan ruang nama. Ya kamu akan. Dalam pikiran saya itu adalah hal yang baik karena Anda dapat menelusuri solusi dalam IDE pilihan Anda dan langsung melihat tanggung jawab apa yang dimiliki komponen tertentu. Jika Anda telah memutuskan untuk menggunakan pola repositori sebagai gantinya, Anda harus melihat ke dalam masing-masing kelas repositori mencoba mencari tahu tanggung jawabnya.

CodeART
sumber
Saya suka gagasan memiliki perintah, bukan fungsi generik. Di mana saya bisa membaca lebih lanjut tentang cara mengimplementasikannya dalam konteks akses data?
ankush981
1

PENOLAKAN: Berikut ini berdasarkan pada pemahaman dan pengalaman singkat saya dari pola tersebut (Repositori). Saya mungkin melakukan kesalahan ... pada kenyataannya, saya cukup positif bahwa saya melakukan kesalahan :). Jadi, sementara ini merupakan upaya untuk jawaban, itu juga merupakan pertanyaan yang menyamar.

Saya menggunakan pola Repositori untuk mengabstraksi lapisan akses data, yang dalam kebanyakan kasus adalah ORM. Ini adalah antarmuka umum, dengan metode untuk kelas Buat, Baca, Perbarui, Hapus dan implementasi untuk LINQ ke SQL dan EF sejauh ini. Saya bisa membuat implementasi yang menulis ke file XML pada disk (hanya contoh liar dari apa yang bisa saya lakukan dengannya). Saya tidak menerapkan Unit Kerja karena didukung oleh ORM. Jika perlu, saya mungkin bisa menerapkannya. Saya suka seperti ini karena, sejauh ini, telah memberi saya pemisahan yang bagus. Saya tidak mengatakan bahwa tidak ada alternatif yang lebih baik.

Untuk menjawab pertanyaan Anda:

  1. Suka atau tidak suka, perubahan akan terjadi. Dan jika Anda telah menulis banyak aplikasi dan waktu telah tiba untuk memeliharanya, tetapi merasa sakit untuk bekerja dengan ORM saat ini dan ingin mengubahnya, Anda akan memuji diri sendiri karena membuat abstraksi semacam itu. Cukup gunakan apa pun yang Anda rasa nyaman, baik itu Repositori atau pola / konsep lain.
  2. Ya, asalkan Anda menggunakannya untuk memisahkan akses data. Seperti yang saya sebutkan sebelumnya, Anda dapat membuat implementasi yang menulis data dalam file datar.
  3. Saya menggunakan Repositori untuk menyimpan kueri dan Objek Kueri yang biasa saya gunakan ketika saya memiliki pertanyaan yang ingin saya ubah (yang tidak banyak).

Untuk memberi Anda contoh lain, orang-orang di Umbraco telah mengabstraksikan wadah DI, kalau-kalau mereka mungkin ingin beralih ke sesuatu yang lain.

devnull
sumber
0

Jika ORM menawarkan fleksibilitas LINQ, bersemangat memuat dll. Saya tidak akan menyembunyikannya di balik lapisan tambahan.
Jika itu melibatkan sql mentah (ORM mikro) maka "metode per permintaan" harus digunakan untuk mencapai usabilitas, sehingga membuat pola repositori cocok.

What do you do if you want to switch out ORMs? 
You would have ORM specific code in your application if you do not contain it in a repository.

Mengapa Anda perlu beralih?
Salah satu yang memiliki sebagian besar fitur yang Anda butuhkan harus digunakan. Mungkin saja rilis ormX baru menghadirkan fitur baru dan ternyata lebih baik daripada yang sekarang, tetapi ...
Jika Anda memilih untuk menyembunyikan orm, Anda hanya dapat menggunakan fitur yang dimiliki semua kandidat.
Misalnya Anda tidak bisa menggunakanDictionary<string, Entity> properti di entitas Anda karena ormY tidak bisa mengatasinya.

Dengan asumsi LINQ digunakan, sebagian besar orm switch hanya mengganti referensi pustaka dan menggantinya session.Query<Foo>()dengan context.Foosatau serupa hingga kompilasi. Tugas yang membosankan, tetapi membutuhkan waktu lebih sedikit daripada mengkodekan lapisan abstraksi.

Is the repository pattern still valid when not using an ORM and you are using ADO.NET for data access and populating object data yourself?

Iya nih. Kode harus dapat digunakan kembali dan itu berarti menempatkan bangunan sql, materialisasi objek dll di satu tempat (kelas terpisah). Anda juga dapat memanggil kelas "XRepository" dan mengekstrak antarmuka darinya.

If you use an ORM but not the repository pattern where do you keep commonly used queries? 
Would it be wise to represent each query as a class and have some sort of query factory to create instances?

Dengan asumsi LINQ digunakan pembungkus kelas akan terlalu banyak IMHO. Cara yang lebih baik adalah metode ekstensi

public static IQueryable<T> Published<T>(this IQueryable<T> source) where T : Page
{
    // at some point someone is going to forget to check that status
    // so it makes sense to extract this thing
    return source.Where(x => x.Status == Status.Published && x.PublishTime <= DateTime.UtcNow);
}

Kode apa pun yang digunakan di banyak tempat (atau memiliki potensi) dan cukup rumit (rawan kesalahan), harus diekstraksi ke tempat terpusat.

Mike Koder
sumber