Cơ bản là repository pattern nó nằm ở repository layer, mục đích cũng để loose coupling cái tầng service với Orm.
Repository layer nó cần data model, config db, migration, integration với service khác ... Rồi implement mấy cái interface mà thằng service xài, thằng service nó chỉ cần refer vô interface thôi là đã giải quyết được vấn đề tight coupling rất nhiều rồi.
Chứ mấy ông reference trực tiếp từ Orm vào service layer thì cái app nó như 1 cái nồi cám lợn éo khác gì nhau. Load vô 5 thằng junior xong cái app nó phình to ra, tight coupling đủ thứ rồi mới thấy cảnh ăn c*t thay cơm.
Mà tôi cũng ít thấy mấy thằng senior ở Vn code đẹp lắm, toàn đẻ ra c*t là c*t. Ông nào cũng vỗ ngực nhận mình code đẹp cả

làm outsource thì chạy theo khách hàng, làm product, startup thì toàn chạy theo tiền.
Chỉ có đi làm thuê cho tụi tư bản Eu cho các cty enterprise lâu đời thì mới có code gọi là đẹp được tí. Ko giải quyết được bài toán architecture design từ đầu thì mọi thứ như cái nồi cám heo. Còn code tụi Mỹ thì thôi rồi nát vcl vì mấy anh Ấn Độ
via theNEXTvoz for iPhone Reactions:
asida118, Call me David, me0wMe0w and 8 others
Các thím làm backend, mobile thì thường chia ra những layer nào và layer đó đảm nhiệm những nhiệm vụ gì ạ?
Bạn đã bao giờ viết unit test cho service layer chưa? Đã thử mock database chưa?
Thấy cái này nhiều nhất ở Clean Architecture, toàn repository hoặc service để tách ra dependency ở Application layer.
Nhưng: database thì ít khi thay đổi + ef có cái phần include tùy từng command hay query sao cho tối ưu thì thằng repository có mỗi Get hoặc List nên cứ thấy sao sao.
CA thì mình hay chỉ tách mấy cái service bên ngoài như redis hoặc elasticsearch, còn dbcontext thì dùng luôn đi nhỉ:V
Reactions:
GeniVN
Có option Tùy thế này mà vẫn có thím chọn Có hoặc Không à

Repository Pattern dùng để có thêm 1 tầng phòng khi thay đổi về cách triển khai tác vụ lưu sửa xóa dữ liệu. Nếu hệ thống không có gì thay đổi thì thấy nó trùng lặp với ORM là phải rồi.
Thằng repository pattern sinh ra là để giảm sự phụ thuộc vào db, thư viện mà nhỉ, liên quan gì ORM đâu @@, có thằng repo thì khi có sự thay đổi vì thư viện hoặc db thì nó sẽ dễ dàng hơn, nếu anh chắc chắc 100% trong tương lai không có sự thay đổi thì không cần repo làm gì cả.
Thằng repository pattern sinh ra là để giảm sự phụ thuộc vào db, thư viện mà nhỉ, liên quan gì ORM đâu @@, có thằng repo thì khi có sự thay đổi vì thư viện hoặc db thì nó sẽ dễ dàng hơn, nếu anh chắc chắc 100% trong tương lai không có sự thay đổi thì không cần repo làm gì cả.
Nhưng mà nếu mình dùng SQL với C# entity framework vậy thì chỉ cần migrate sang thôi mà nhỉ, entity framework support lấy ra các DbSet y như Repository rồi -> bản chất DbContext nó đã là Repository.
Có đợi em migrate từ MSSQL sang PostgreSQL vẫn oke mà
Em nghĩ là k ai chuyển từ SQL sang NoSQL giữa chừng, vì họ design system từ đầu cả rồi nhỉ bác
Thằng repository pattern sinh ra là để giảm sự phụ thuộc vào db, thư viện mà nhỉ, liên quan gì ORM đâu @@, có thằng repo thì khi có sự thay đổi vì thư viện hoặc db thì nó sẽ dễ dàng hơn, nếu anh chắc chắc 100% trong tương lai không có sự thay đổi thì không cần repo làm gì cả.
Thằng ORM nó cũng dư sức làm được việc này rồi, ông repository lại đi viết lại từng hàm của ORM, kiểu như:
ORM.DbContext.Insert()
thì ông repository lại đi viết lại 1 đống code với 1 cách cực kỳ buồn cười:
Repository.Insert()
{
ORM.DbContext.Insert()
}
Reactions:
asida118 and tungwtrg
Repository chỉ là 1 abstraction giữa service và data access layer, để decouple 2 thằng này ra. Mục đích thì ai cũng biết rồi, dễ thấy nhất là switch được nhiều implementation. Ví dụ query data từ SQL, NoSQL, 3rd service,...
Vấn đề có dùng repository hay không cũng giống việc nên inject trực tiếp service class (impl) hay là interface. Đa số trường hợp service chỉ có 1 implementation, nhưng người ta vẫn dùng interface để dự trù (mặc dù chưa thấy xảy ra bao giờ

).
Thêm nữa, việc repository có dính tới framework (như PageRequest của JPA), hoặc có các method CRUD như findFriendsByActive(true), insertOne() thì nên xem lại.
Thứ nhất đây có thể là generic repository (như đã discuss trong thread). Thứ hai là abstraction đang bị phụ thuộc vào details (DB), thay vì phụ thuộc vào nhu cầu service (tên method nên là listActiveFriends(), createNewUser()).
Reactions:
Tommisterio, phuctienn, freedom.9 and 1 other person
Thằng ORM nó cũng dư sức làm được việc này rồi, ông repository lại đi viết lại từng hàm của ORM, kiểu như:
ORM.DbContext.Insert()
thì ông repository lại đi viết lại 1 đống code với 1 cách cực kỳ buồn cười:
Repository.Insert()
{
ORM.DbContext.Insert()
}
Tôi không dùng ORM đó nữa thì sao?? Tôi đổi sang ORM khác, thế là phải sửa một đống code lằng nhằng à

Reactions:
asida118, Tommisterio and tonghoangvu
thấy thay vì duplicate code inject DbContext nhiều chỗ, quy tất cả các truy vấn sql về unitOfWork. có thể viết abstract thì việc viết thêm method cho repo trong trường hợp truy vấn quá đặc biệt. Trước viết mình viết lộn xộn inject DBContext ở khắp nơi, trông lộn xộn thực sự.
Ý kiến cá nhân, mong dc góp ý
cá nhân em thấy thì thằng ORM nó cũng bullsh*t nốt, tự nhiên thêm một layer nữa làm cho mọi thứ complex hơn, performance thì cá đuối hơn, ca nào khoai sẵn quá chắc vẫn phải vác raw sql ra chơi. haizz
Reactions:
GeniVN, pvpbg and freedom.9
ý kiến của một vô danh tiểu tốt: Repository pattern nguyên bản là để phân tách concern giữa code sql và code business. Thường là phải viết sql raw trong code rất khó để maintain, nên viết một lớp riêng để implement tách riêng 2 tụi nó ra. Thằng EF Core nó đã thực hiện 2 pattern là Repository với Unit Of Work. Repository như đã nói ở trước (rõ ràng bạn muốn thì chỉ việc gọi hàm chứ đâu cần quan tâm sql nó viết như thế nào, nhưng thực ra bên dưới nó vẫn là chạy sql raw). Còn về phần Unit Of Work, bản chất của pattern này là wrap các cái action lại với nhau thành một cái transaction để đảm bảo tính atomic (tức là tất cả hoặc không). Bản chất của UoW ko phải để cho nhiều dbcontext vô để tiện lấy ra ở một chỗ, mà là như trước (thể hiện thông qua thằng EF Core hỗ trợ transaction). Còn như hiện tại, cái khái niệm repository pattern với UoW nó bị bóp méo đi. Như việc tại sao ta phải tạo repository cho EF Core mặc dù nó đã có sẵn 2 pattern repo với UoW, điều này hoàn toàn bình thường nếu ta muốn abstract việc sử dụng một database cụ thể nào đó (mongo, postgres, sql server,...) chỉ việc thông qua thay đổi implementation của interface, điều này cũng khiến dễ mock (thay đổi implement của interface) và test hơn. Nhưng đây ko phải là repository pattern, dù điều này đúng là có ích.
thấy thay vì duplicate code inject DbContext nhiều chỗ, quy tất cả các truy vấn sql về unitOfWork. có thể viết abstract thì việc viết thêm method cho repo trong trường hợp truy vấn quá đặc biệt. Trước viết mình viết lộn xộn inject DBContext ở khắp nơi, trông lộn xộn thực sự.
Ý kiến cá nhân, mong dc góp ý
về cơ bản thì đó ko phải gọi là unit of work.
chẳng hạn thím chỉ dùng cái gì orm cho thím, k hơn k kém, thì bản thân dbcontext nó cũng là 1 repository rồi. Nó đã có đủ abstraction về datasource, swap DB tẹt ga luôn.
Câu chuyện nó khó hơn khi cần mở rộng repository ra. Trong dự án mình nhiều khi có nhiều query params lắm, tới khi đó thì nó vượt khả năng của ef core rồi, thì quay sang dùng query builder. Tới lúc này phải có 1 trong 2 quyết định được đưa ra: CustomRepository mới sẽ extends DbContext, hoặc wrap lại những cái cần dùng trong CustomRepository.
Mình thấy cách số 2 dễ thở hơn, thì lúc này mình lại xem dbcontext ngang hàng với query builder & SQL executor - thành 1 cách để giao tiếp với DB, k còn là repository nữa thì lại thấy câu chuyện nó quay trở về làm sao cho code nó consistency, vì có nơi dùng dbcontext thẳng, có nơi custom repository thì nó inconsistent thôi
k bàn tới trường hợp switch DB, vì hầu như 2 cách trên đều đáp ứng sương sương, nếu dùng dbcontext trực tiếp, đổi qua DB k theo relational model thì cụt. Đa phần ít dự án đổi DB lắm, nếu có là đổi từ single instance qua cơ chế distributed, thì protocol nhiều khi vẫn thế. Nma wrap lại repository nhiều khi cũng chả tốn công lắm đâu, cứ làm cho nó consistent
Ngứa tay vào còm.
1) Về việc đổi database, mọi người bảo hiếm, nhưng thực ra rất phổ biến trong giai đoạn đầu phát triển sản phẩm. Vì design database nhiều khi rất lâu mới xong vì dính tới rất nhiều thứ về hiệu năng/bảo mật. Cho nên ông nào code front-end hay business logic thay vì chờ làm xong database thì tạo abstract layer với database lúc code với unit test có thể dùng in-memory hay SQLite database để code mà ko bị phụ thuộc, bao giờ team database xong thì switch qua. Khi database đã thiết kế xong và chạy ổn định thì bắt đầu từ lúc này mới hiếm khi cần switch.
2) Cần switch database ko phải lý do dùng repository pattern, vì như mọi người đã nói bản thân ORM support chuyện đó rồi. Lý do tại sao dùng thì là từ bài học của Google ngày xưa, code sử dụng trực tiếp Linux kernel và bỏ quên sau 5 năm. Thế rồi sau đó là ác mộng khi update kernel version mới. Đây cũng giống vậy thôi, đã là software, đã dính tới code với update là phải có lỗi, ORM cũng ko ngoại lệ. Cho nên nếu bỏ repository pattern dùng trực tiếp ORM thì nhỡ update ORM lên version mới mà phát sinh lỗi do thay đổi của ORM thì sẽ rất khó để fix. Còn ko update thì chẳng lẽ cứ tiếp tục dùng version cũ sau 10 năm, 20 năm?
3) Quan điểm cá nhân mình là cái gì hay thay đổi thì nên có abstract layer, tất nhiên thêm boilerplate code vô nghĩa chỉ để phục vụ cho abstract layer là rất khó chịu, nhưng trade-off nhiều khi cũng đáng, quan trọng là life time business dự tính thế nào.
Reactions:
codecmartin, asida118, Call me David and 10 others
Từng vào topic này và vote cái này, nhưng giờ thì nghĩ khác
Nãy mình có đọc được bài này, bài đăng dc 1 tháng, tác giả cũng có góc nhìn giống với chủ thread
Why You Don't Need a Repository in EF Core (https://antondevtips.com/blog/why-you-dont-need-a-repository-in-ef-core)
Sau 1 thời gian đi làm có trải qua dự án dùng repository, và không dùng repository, ngẫm lại thì thấy nó rườm rà thật, dùng thẳng dbcontext code rất nhanh và linh hoạt, không phải tốn thời gian suy nghĩ nên để code ở repository nào, có nên tạo repo mới không, nhiều entity mà join với nhau thì làm sao... Và tất nhiên là dbcontext vẫn hỗ trợ unit test, code common thì vẫn có thể tách ra extension method để reuse
Rồi cái vụ dùng repo tạo tầng abstract nên để dễ đổi database, thấy mấy thím overthinking/overengineer chứ đa phần business đang chạy nếu có issue với database thì người ta sẽ hướng tới optimize lại database/code. Và nếu có đổi database thì người ta cũng sẽ dành rất nhiều effort vào để sửa lại những thứ liên quan trong code chứ không hẳn là 1 cái config bụp vào là đổi sang database khác => vậy thì có đáng không khi phải đánh đổi bằng việc hằng ngày phải bỏ thêm nhiều thời gian để suy nghĩ nên code thế nào cho đúng với cái đám repository pattern hiện tại
Reactions:
Frederick I Barbarossa
Mục đích của repository pattern là để tách phần truy vấn dữ liệu khỏi business logic, nó ko chỉ giúp code gọn hơn mà còn có thể tái sử dụng đc. ORM thì cũng chỉ là 1 hình thức khác so với với viết query thuần, bản chất nó vẫn là lớp thao tác với DB nên chả ảnh hưởng gì tới Repository pattern hay ko. Ví dụ có 1 query cần filter nhiều trường dữ liệu và cần điều kiện so sánh khác nhau, nếu define hẳn thành 1 hàm trong repository thì có thể tái sử dụng được ở nhiều nơi trong service. DBContext trong .NET chính là entity ánh xạ với table trong DB, còn Repository layer chính lớp bên trên ngăn cách việc thao tác dữ liệu với Business logic
Về vấn đề này thì chắc cách implement của Java Spring có vẻ hay hơn hơn .NET core. Trong JPA Spring thì có sẵn Repository layer để kế thừa, và có thể custom function ngay trên cái layer ấy luôn

Reactions:
andinhtien, GeniVN, cuoc_song and 1 other person
Các anh đưa lý lẽ cho việc đổi databases để dùng Repository Pattern tôi càng thấy bullshit vì:
1. Bản thân ORM framework đã support rất nhiều loại database rồi.
2. Việc đổi database qua cái mới hoàn toàn mà ORM ko support như từ MSSQL sang MongoDB là cái chuyện trong thực tiễn rất hiếm xảy ra.
Chẳng có thằng điên nào đi đòi đổi db từ relation db sang Nosql chỉ bằng config cả.
Còn cái tào lao của thằng Repository Pattern mà dự án nào xài nó tôi cũng gặp là:
1. Code lặp lại những gì ORM đã làm như get, getall, save, update, delete… include.. join…
2. Khi gọi join giữa 2 repositories, hoặc cần quản lý transaction thì lại đi code lặp lại của thằng ORM. (Bullshit)
3. Toàn bộ những gì ORM support thì bị cái anh Repository Pattern này abstract lên hết nên nếu muốn xài thì phải code lặp lại, gọi lại của ORM (như vậy lại vô tình phụ thuộc vào chính ORM đó, ko còn abstract như ý tưởng ban đầu, bullshit lần 2)
via theNEXTvoz for iPhone
1. RP nó sinh ra méo phải cho việc đổi db
2. Chuyện đổi db là hoàn toàn có thể xảy ra, tất nhiên k phsir biến. Ví dụ dùng oracle xong sau nhiều năm tốn tiền quá -> move sang postgres, đổi 1 phần relation db sang nosql…
3. Mục đích chính của RP nó là tập trung domain logic lại 1 chỗ, tách domain service ra khỏi persistance,
4. Code lặp lại những gì ORM đã làm như get, getAll, save, update -> đây là do bad implement chứ k phải do bản thân RP
5. Quản lý transaction nên đc thực hiện ở tầng service, nếu ném vào repository thì là bad practice cmnr
Thôi ngại type tiếp quá, nhưng mà đây cũng là những cái ngày xưa tôi nghĩ về RP mà sau này lên SA mới clear hết đc
via theNEXTvoz for iPhone Reactions:
tonghoangvu
case nữa là phục vụ caching + syncing qua các nguồn khác (kiểu elasticsearch, vector db, etc.). Gói gọn lại cũng oke