thảo luận [Thảo luận] Repository Pattern là cái bullsh*t nhất khi đã có ORM framework?

Có nên sử dụng repository pattern khi đã có ORM framework rồi ko?

  • Có - có lợi nhiều lắm để tôi cmt bên dưới

    Votes: 18 18.0%
  • Có - thấy người ta hay xài thì mình xài thôi (chắc là cũng có lợi gì đó nhưng dek biết)

    Votes: 17 17.0%
  • Không - tốn công vô ích, đẽ ra cho thêm việc phức tạp chứ ko lợi lộc gì đáng kể

    Votes: 9 9.0%
  • Không - code nhiều mệt vãi, xài trực tiếp ORM cho nhanh (cũng ko biết là có lợi hay ko)

    Votes: 16 16.0%
  • Tuỳ - tuỳ dự án, tuỳ yêu cầu

    Votes: 40 40.0%

  • Total voters
    100

joonkim

Member
Ơ kìa các lập trình viên

Làm Repository pattern mà không nhắc đến Unit of work là vứt đi rồi. :beat_brick:

Còn anh nào bảo swap từ sql sang mongo cũng vứt nốt.

Một cái lợi ích của nó là tách layer ra thể DDD và tiện cho unit test. :go:
 

ngolebaotrung

Senior Member
Custom ORM cũng được. Nhưng cái logic custom đấy đặt ở đâu. Thế thì viết trong repo class chả gọn code hơn à
 

Kân team v2

Senior Member
Còn anh nào bảo swap từ sql sang mongo cũng vứt nốt.
có lẽ swap từ nosql sang sql thì có lý hơn
uq1dgnk.png
làm thế nào để swap sang mà vẫn giữ được cái interface data access như cũ thì ngon.

mà mới có thằng EdgeDB gì ra 1.0 nè https://www.edgedb.com/blog/edgedb-1-0, tự xưng là graph-relational database, "Modern, lean query language designed to surpass SQL in expressive power," nhưng thấy ghi là power by postgres. Biết đâu tương lai nó làm trùm thì sao. Thay vì xài ORM/Entity Framework như chủ thớt cũng là 1 dạng repo pattern, viết thẳng repo pattern luôn, data fake/relational/graph/nosql/xml/cloud kiểu nào cũng chấp hết.

thớt chửi cũng có lý, kiểu như nhìn xa quá lại thành viển vông, mất thời gian reinvent the wheel v.v... Cái gì cũng có pros & cons ko làm lead tự chọn được thì phải ngồi chửi thôi
1xEuo02.gif
 

Pepe.The.Frog

Senior Member
@Pepe.The.Frog anh thấy ko cần thì ko xài thôi. Ráng cố gắng lên chức Lead hay Software Architect rồi bỏ hết cái Repository Pattern đi là được.

Còn tôi chỉ có cái case như vầy mới làm hôm qua. Tui có tài khoản Msdn Enterprise. Muốn làm cái database để quản lý đống license key. Một product có nhiều product keys. Tức là 1:n.

Giờ tui muốn có 1 hàm nhận vào Product. Trong object Product đó có cái List của Product Keys. Hàm đó lưu Product vào bảng Products, lưu Product Keys vào bảng ProductKeys với ProductId. Rồi giờ tui bỏ cái hàm đó ở đâu đây nếu ko bỏ vào Repository?

Repository Pattern và Orm Framework về ý nghĩa nó chả cùng một loại. Như đũa với chén. Chả hiểu tại sao lại kêu có đũa rồi ko cần chén ăn cơm?

Cái hàm đó anh viết trực tiếp ở service. Lúc này sẽ inject dbContext vào service. dbContext sẽ THAY THẾ cho repository của anh.
Ví du: IProductManagementSerivce.Save(Product product);

Còn trường hợp muốn sử dụng hàm đó ở nhiều service thì anh viết extension methods cho dbContext, để gom cái logic đó vào 1 chổ.

Repository và ORM ko phải là đũa với chén, nó là 1.

@Pepe.The.Frog ừ anh trả lời tui câu trên.

Rồi có một cái case nhỏ khác. Ví dụ tui có cái Entity Product. Nó có ExpiredDate và IsDisable.

Giờ tui muốn lấy valid products list. Tui tạo một hàm trong Repository để kiểm Expired Date > DateTime.Now và IsDisable = false.

Tui gọi hàm này ở chục cái Services.

Giờ bỏ Repository rồi hổng lẽ tui copy code ra chục vị trí khác ở tầng Service?

Custom ORM cũng được. Nhưng cái logic custom đấy đặt ở đâu. Thế thì viết trong repo class chả gọn code hơn à

Cũng như trên, anh tạo extension methods cho dbContext hoặc DbSet<Product>, hoặc helper class để gom cái logic đó lại thôi. Cái hàm này sẽ đứng ngang hàng với các hàm save, update của ORM. Nó ko phải là 1 layer cao hơn như Repository để wrap cái logic này lại.

Trong ddd, repository là một design pattern cực kỳ quan trọng, còn ORM là cái vứt đi vì Object–relational impedance mismatch. Nếu model của bạn có thể map trực tiếp với các bảng trong database thì project của bạn chỉ phức tạp ngang contoso university.

Bullshit! Repository là cái phiên bản quái thai và khuyết tật của ORM, tôi ko biết từ bao giờ thánh nào tạo ra cái đó. Ngày xưa chỉ có Data Acess Layer, nó tạo repository để map model + table, bây giờ có ORM full support rồi còn tạo Repository là tào lao.

Ơ kìa các lập trình viên

Làm Repository pattern mà không nhắc đến Unit of work là vứt đi rồi. :beat_brick:

Còn anh nào bảo swap từ sql sang mongo cũng vứt nốt.

Một cái lợi ích của nó là tách layer ra thể DDD và tiện cho unit test. :go:

Bullshit! ORM đã implement cả unit of work rồi. ORM cũng support unit test với fake dbContext các kiểu. Anh thấy anh đẽ ra cái Repository tào lao chưa?

có lẽ swap từ nosql sang sql thì có lý hơn
uq1dgnk.png
làm thế nào để swap sang mà vẫn giữ được cái interface data access như cũ thì ngon.


mà mới có thằng EdgeDB gì ra 1.0 nè https://www.edgedb.com/blog/edgedb-1-0, tự xưng là graph-relational database, "Modern, lean query language designed to surpass SQL in expressive power," nhưng thấy ghi là power by postgres. Biết đâu tương lai nó làm trùm thì sao. Thay vì xài ORM/Entity Framework như chủ thớt cũng là 1 dạng repo pattern, viết thẳng repo pattern luôn, data fake/relational/graph/nosql/xml/cloud kiểu nào cũng chấp hết.

thớt chửi cũng có lý, kiểu như nhìn xa quá lại thành viển vông, mất thời gian reinvent the wheel v.v... Cái gì cũng có pros & cons ko làm lead tự chọn được thì phải ngồi chửi thôi
1xEuo02.gif

Anh dùng ORM cũng có thể mock dbContext và cái interface data access của anh chính là dbContext của ORM đó.
 

soihoang

Senior Member
orm hay active record là 1 dạng RAD (Rapid Application Development), lúc đầu phát triển dự án mình thường tương thẳng orm vào controller luôn cho nhanh, khi nào business phát triển hay thay đổi mới refactor các layer
 

Pepe.The.Frog

Senior Member
orm hay active record là 1 dạng RAD (Rapid Application Development), lúc đầu phát triển dự án mình thường tương thẳng orm vào controller luôn cho nhanh, khi nào business phát triển hay thay đổi mới refactor các layer

tight couple giữa ORM và Controller thì hơi chặt quá thím. Setup đẹp nhất là như này:

Controller -> Service -> ORM (dbContext)

Như này thì có thay đổi protocol (ví dụ từ REST -> grpc)/unit test controller vẫn đảm bảo vì có thằng service abstract rồi.

Còn các anh nào đòi như này là tào lao: :beat_brick:
Controller -> Service -> Repository -> ORM (dbContext)
 

Kân team v2

Senior Member
Anh dùng ORM cũng có thể mock dbContext và cái interface data access của anh chính là dbContext của ORM đó.
ORM nó cũng là 1 dạng repo pattern đấy nhưng có chữ R là relation trong đó, nghĩa là nó tập trung cho RDBMS rồi. Anh ép ORM nó sang cloud/xml/nosql gì cũng được thôi, nhưng ép thế thì thà tự viết repo pattern từ đầu/hoặc từ đầu xài cái repo pattern luôn thay vì 1 cái orm nào đấy, về sau dễ thở/dễ custom hơn. Trade-offs hết, trước khổ sau sướng hoặc trước sướng sau khổ thoy
JiZo9zf.png
 

Meete

Senior Member
Thế repository nó là lớp nào trong 3 lớp trên hả thím?
Repository concept thuộc về domain layer.
Repository implementation thuộc về persistence layer.

Để trả lời cho câu hỏi Repository có cần thiết hay không thì phải hiểu định nghĩa Repository nó là cái gì đã.

Repository là một cái cổng hay cái cầu nối đi qua đi lại giữa 2 thế giới domain layer và persistence layer.

Muốn lưu trữ lại state của Entity thì ném cái Entity đó qua Repository. Repository sẽ lưu state của Entity xuống data storage.

Muốn phục hồi lại state của Entity thì móc nó lên từ Repository. Repository sẽ chạy xuống storage để fetch state lên, nó sẽ tái tạo lại một Entity với đầy đủ state mà lần cuối cùng nó được lưu trữ.

Data Storage ở đây có thể là RDBMS, NoSQL, Flat File, Web Service... Cho nên bản chất Repository chỉ là một cái concept thể hiện bằng một interface để trừu tượng persistence layer bên dưới. Không cần quan tâm storage bên dưới là gì!?

Quay trở lại câu hỏi ORM có thay thế được Repository hay không?
Xin trả lời là có thể nếu thấy nó hợp lý.

Lấy ví dụ món ăn yêu cầu thành phần là Táo nói chung mà không nói rõ là táo tươi, táo khô hay mứt táo vì tất cả đều ok miễn có vị táo. Táo là Repository là high-level concept, táo khô là ORM là cụ thể hóa rồi, bạn có thể dùng táo khô cho món ăn mà vẫn ngon.

Bản thân mình làm nhiều project vẫn dùng thực tiếp Repository của ORM luôn vì đơn giản project nó chỉ đơn giản vậy thôi, ko cần thiết phải thêm Repository interface để trừu tượng hóa nữa.
Nhưng mà có những project nó cần trừu tượng hóa cao độ thì phải định nghĩa Repository concept (interface) trước, vì thực sự mình ko thể biết dc storage nó là RDBMS, DBMS hay Web Service...
 

Vozer cấp tiến

Senior Member
Repository concept thuộc về domain layer.
Repository implementation thuộc về persistence layer.

Để trả lời cho câu hỏi Repository có cần thiết hay không thì phải hiểu định nghĩa Repository nó là cái gì đã.

Repository là một cái cổng hay cái cầu nối đi qua đi lại giữa 2 thế giới domain layer và persistence layer.

Muốn lưu trữ lại state của Entity thì ném cái Entity đó qua Repository. Repository sẽ lưu state của Entity xuống data storage.

Muốn phục hồi lại state của Entity thì móc nó lên từ Repository. Repository sẽ chạy xuống storage để fetch state lên, nó sẽ tái tạo lại một Entity với đầy đủ state mà lần cuối cùng nó được lưu trữ.

Data Storage ở đây có thể là RDBMS, NoSQL, Flat File, Web Service... Cho nên bản chất Repository chỉ là một cái concept thể hiện bằng một interface để trừu tượng persistence layer bên dưới. Không cần quan tâm storage bên dưới là gì!?

Quay trở lại câu hỏi ORM có thay thế được Repository hay không?
Xin trả lời là có thể nếu thấy nó hợp lý.

Lấy ví dụ món ăn yêu cầu thành phần là Táo nói chung mà không nói rõ là táo tươi, táo khô hay mứt táo vì tất cả đều ok miễn có vị táo. Táo là Repository là high-level concept, táo khô là ORM là cụ thể hóa rồi, bạn có thể dùng táo khô cho món ăn mà vẫn ngon.

Bản thân mình làm nhiều project vẫn dùng thực tiếp Repository của ORM luôn vì đơn giản project nó chỉ đơn giản vậy thôi, ko cần thiết phải thêm Repository interface để trừu tượng hóa nữa.
Nhưng mà có những project nó cần trừu tượng hóa cao độ thì phải định nghĩa Repository concept (interface) trước, vì thực sự mình ko thể biết dc storage nó là RDBMS, DBMS hay Web Service...
Cảm ơn thím, thím giải thích rất dễ hiểu, tiện thím giải thích thêm cho mình về domain layer với ạ, cảm ơn thím nhiều.
 

Pepe.The.Frog

Senior Member
ORM nó cũng là 1 dạng repo pattern đấy nhưng có chữ R là relation trong đó, nghĩa là nó tập trung cho RDBMS rồi. Anh ép ORM nó sang cloud/xml/nosql gì cũng được thôi, nhưng ép thế thì thà tự viết repo pattern từ đầu/hoặc từ đầu xài cái repo pattern luôn thay vì 1 cái orm nào đấy, về sau dễ thở hơn. Trade-offs hết, trước khổ sau sướng hoặc trước sướng sau khổ thoy
JiZo9zf.png

Repository concept thuộc về domain layer.
Repository implementation thuộc về persistence layer.

Để trả lời cho câu hỏi Repository có cần thiết hay không thì phải hiểu định nghĩa Repository nó là cái gì đã.

Repository là một cái cổng hay cái cầu nối đi qua đi lại giữa 2 thế giới domain layer và persistence layer.

Muốn lưu trữ lại state của Entity thì ném cái Entity đó qua Repository. Repository sẽ lưu state của Entity xuống data storage.

Muốn phục hồi lại state của Entity thì móc nó lên từ Repository. Repository sẽ chạy xuống storage để fetch state lên, nó sẽ tái tạo lại một Entity với đầy đủ state mà lần cuối cùng nó được lưu trữ.

Data Storage ở đây có thể là RDBMS, NoSQL, Flat File, Web Service... Cho nên bản chất Repository chỉ là một cái concept thể hiện bằng một interface để trừu tượng persistence layer bên dưới. Không cần quan tâm storage bên dưới là gì!?

Quay trở lại câu hỏi ORM có thay thế được Repository hay không?
Xin trả lời là có thể nếu thấy nó hợp lý.

Lấy ví dụ món ăn yêu cầu thành phần là Táo nói chung mà không nói rõ là táo tươi, táo khô hay mứt táo vì tất cả đều ok miễn có vị táo. Táo là Repository là high-level concept, táo khô là ORM là cụ thể hóa rồi, bạn có thể dùng táo khô cho món ăn mà vẫn ngon.

Bản thân mình làm nhiều project vẫn dùng thực tiếp Repository của ORM luôn vì đơn giản project nó chỉ đơn giản vậy thôi, ko cần thiết phải thêm Repository interface để trừu tượng hóa nữa.
Nhưng mà có những project nó cần trừu tượng hóa cao độ thì phải định nghĩa Repository concept (interface) trước, vì thực sự mình ko thể biết dc storage nó là RDBMS, DBMS hay Web Service...


Anh tự viết Repository Pattern từ đầu với anh custom ORM để support cloud/xml/nosql là NHƯ NHAU!

Cái lợi của việc sử dụng trực tiếp ORM là tận dụng được đầy đủ chức năng của ORM đó, chứ ko phải mổi lần cần lại abstract nó lên repository.

Những dự án xài repository thì thấy toàn là khổ trước chứ lúc sướng thì thật sự tôi chưa thấy. Tới lúc cần đổi thì các anh re-implement lại repository cũng sml chứ ở đó mà sướng. Effort bỏ ra cũng y như custom ORM. :ah:
 

Kân team v2

Senior Member
Anh tự viết Repository Pattern từ đầu với anh custom ORM để support cloud/xml/nosql là NHƯ NHAU!

Cái lợi của việc sử dụng trực tiếp ORM là tận dụng được đầy đủ chức năng của ORM đó, chứ ko phải mổi lần cần lại abstract nó lên repository.

Những dự án xài repository thì thấy toàn là khổ trước chứ lúc sướng thì thật sự tôi chưa thấy. Tới lúc cần đổi thì các anh re-implement lại repository cũng sml chứ ở đó mà sướng. Effort bỏ ra cũng y như custom ORM. :ah:
https://www.infoworld.com/article/3117713/design-patterns-that-i-often-avoid-repository-pattern.html

cũng có người nói hệt như anh nè, làm cho MS 20 năm, ca ngợi EF là phải. Đem cho lead đọc cho ảnh/chỉ thay đổi các project sau
1xEuo02.gif
 

Meete

Senior Member
Anh tự viết Repository Pattern từ đầu với anh custom ORM để support cloud/xml/nosql là NHƯ NHAU!

Cái lợi của việc sử dụng trực tiếp ORM là tận dụng được đầy đủ chức năng của ORM đó, chứ ko phải mổi lần cần lại abstract nó lên repository.
Như tôi đã nói cái đó phải balance ko có công thức đâu.

Như tôi nhiều project tôi vẫn dùng trực tiếp Spring JPA luôn vì đơn giản project nó chỉ có vậy thôi, ko cần phải phức tạp lên.

Nhưng vẫn có project tôi phải định nghĩa concept trước. Ví dụ luôn một project tôi đã triển khai, công việc của nó là kết nối nhiều partner lại với nhau. Repository tôi phải trừu tượng vì ko biết dc Entity state của tôi được fetch từ đâu, vì có nhiều team khác impl cái Repository concept tôi định nghĩa tùy theo hệ thống của họ, tôi ko can thiệp dc.

Tôi là người làm high-level, còn impl ko phải là tôi mà là các team của các partner khác.
 

Pepe.The.Frog

Senior Member
Như tôi đã nói cái đó phải balance ko có công thức đâu.

Như tôi nhiều project tôi vẫn dùng trực tiếp Spring JPA luôn vì đơn giản project nó chỉ có vậy thôi, ko cần phải phức tạp lên.

Nhưng vẫn có project tôi phải định nghĩa concept trước. Ví dụ luôn một project tôi đã triển khai nó công việc là kết nối nhiều partner lại với nhau. Repository tôi phải trừu tượng vì ko biết dc Entity state của tôi được fetch từ đâu, vì có có nhiều team khác impl cái Repository concept tôi định nghĩa tùy theo hệ thống của họ, tôi ko can thiệp dc.

Anh ví dụ cụ thể, dc thi post code lên. Tôi sẽ chỉ cho anh thấy ko cần dùng repository vẫn có thể đáp ứng được yêu cầu của anh chỉ bằng dùng ORM và design pattern.

Cái tôi muốn nói là 90% các trường hợp hiếm mà các anh gặp đều giải quyết được bằng custom ORM hoặc design pattern. Trở ngại lớn nhất là các anh ko biết custom ORM thế nào thôi. :misdoubt:
 

cuoc_song

Đã tốn tiền
Tôi sẽ trả lời mọi câu hỏi của a sau. Giờ đi ngủ đã. Tốt nhất là a post code lên luôn.

P/s cho các anh khác:

Tôi sẽ tiếp tất cả các anh nào còn chém về cái sự “hữu ích” của Repository ngoài việc đổi db và ORM (vốn là 1 việc rất hiếm và thực tế hỏi 1 câu thật lòng mà tôi biết chắc câu trả lời là: “các a đã gặp dự án thực tế nào đang chạy rồi có yêu cầu đổi db như vậy chưa?” Đổi qua db khác tới mức mà ORM ko support?

Tôi đồng ý Repository Pattern chỉ có lợi DUY NHẤT 1 việc là đổi DB và ORM nhưng tác hại thì rất nhiều và ko đáng.

via theNEXTvoz for iPhone

Tôi tạm thời giải thích thế này, bác nghe xem có xuôi không nhé.
Nhắc đến Repository Pattern thì phải nhắc thêm 2 khái niệm là:
1. Unit Of Work và Aggregate. Trong đó Unit Of Work dùng để handle transaction và đơn giản hơn cho việc Inject ( ngang với DbContext).
2. Aggregate mới là cái quan trọng trong Repository Pattern này. Lấy 1 cái ví dụ 1 cái Aggregate đơn giản là 1 cái đơn hàng (Order) thì nó phải đi kèm với dòng chi tiết của đơn hàng (OrderContent). 1 cái OrderRepository sẽ xác định 1 cái Aggregate Root là Order và cả cái Aggregate là Order + OrderContent.
2.1 Từ cái khái niệm này sẽ suy ra danh sách các method tương ứng cho Repository này là CRUD hay chỉ có CR và nghiệp vụ lưu trữ chung nhất cho cái Repository này.
2.2 Việc gom các code phục vụ lưu trữ ở đây gồm 2 tác dụng
2.2.1 Đơn giản logic trong service. Service sẽ chỉ cần xác định lưu 1 cái đơn hàng thì nó có đủ thông tin theo Aggegate là nó lưu thôi. Làm sao build đúng cái Aggregate đó là được
2.2.2 với Read thì sẽ cho phép thực hiện bổ sung cache hoặc các kĩ thuật tối ưu query tương ứng, mà không phải đi từng chỗ trong service để tối ưu cái này

1 tác dụng bổ sung là cho phép mix các nguồn dữ liệu lại và cung cấp interface cho service. Cụ thể các nguồn dữ liệu bao gồm HTTP sang hệ thống ngoài, SQL, NoSQL.

Bên trên là 1 số các tác dụng của Repository Pattern nhé. Cụ thể thì nó còn nhiều thứ hơn nữa. Nhưng ý tưởng chung là thêm 1 không gian đệm để có các cải tiến phù hợp cho dự án
 

Meete

Senior Member
Cảm ơn thím, thím giải thích rất dễ hiểu, tiện thím giải thích thêm cho mình về domain layer với ạ, cảm ơn thím nhiều.
Domain layer thường chỉ xuất hiện trong các bài toán có nghiệp vụ phức tạp chứ bình thường ít thấy.
Hiểu đơn giản nó là 1 cái core đóng gói mọi business logic. Nhận input trả output vậy thôi, còn lại nó ko quan tâm dùng DB gì, Framework nào...
 

Pepe.The.Frog

Senior Member
Tôi tạm thời giải thích thế này, bác nghe xem có xuôi không nhé.
Nhắc đến Repository Pattern thì phải nhắc thêm 2 khái niệm là:
1. Unit Of Work và Aggregate. Trong đó Unit Of Work dùng để handle transaction và đơn giản hơn cho việc Inject ( ngang với DbContext).
2. Aggregate mới là cái quan trọng trong Repository Pattern này. Lấy 1 cái ví dụ 1 cái Aggregate đơn giản là 1 cái đơn hàng (Order) thì nó phải đi kèm với dòng chi tiết của đơn hàng (OrderContent). 1 cái OrderRepository sẽ xác định 1 cái Aggregate Root là Order và cả cái Aggregate là Order + OrderContent.
2.1 Từ cái khái niệm này sẽ suy ra danh sách các method tương ứng cho Repository này là CRUD hay chỉ có CR và nghiệp vụ lưu trữ chung nhất cho cái Repository này.
2.2 Việc gom các code phục vụ lưu trữ ở đây gồm 2 tác dụng
2.2.1 Đơn giản logic trong service. Service sẽ chỉ cần xác định lưu 1 cái đơn hàng thì nó có đủ thông tin theo Aggegate là nó lưu thôi. Làm sao build đúng cái Aggregate đó là được
2.2.2 với Read thì sẽ cho phép thực hiện bổ sung cache hoặc các kĩ thuật tối ưu query tương ứng, mà không phải đi từng chỗ trong service để tối ưu cái này

1 tác dụng bổ sung là cho phép mix các nguồn dữ liệu lại và cung cấp interface cho service. Cụ thể các nguồn dữ liệu bao gồm HTTP sang hệ thống ngoài, SQL, NoSQL.

Bên trên là 1 số các tác dụng của Repository Pattern nhé. Cụ thể thì nó còn nhiều thứ hơn nữa. Nhưng ý tưởng chung là thêm 1 không gian đệm để có các cải tiến phù hợp cho dự án

Anh ko cần phải giải thích với tôi Repository Pattern đó là gì vì ở đây ai cũng biết cả.

Những gì mà anh nói chính là cái ORM nó làm đó anh! Thế tôi mới nói là:

Repository Pattern là phiên bản quái thai, khuyết tật, ko đầy đủ của ORM
 
Top