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

  • Người tạo chủ đề Người tạo chủ đề Pepe.The.Frog
  • Ngày bắt đầu Ngày bắt đầu

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

    Bình chọn: 59 22,4%
  • 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)

    Bình chọn: 45 17,1%
  • 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ể

    Bình chọn: 32 12,2%
  • 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)

    Bình chọn: 42 16,0%
  • Tuỳ - tuỳ dự án, tuỳ yêu cầu

    Bình chọn: 85 32,3%

  • Tổng số người bình chọn
    263
Theo e thấy thì cả bác Frog và các bác kia đều có ý đúng, nhưng em bổ sung thêm 1 góc nhìn support cho việc dùng repository pattern khi dự án dùng ORM là layer Repository mang lại lợi ích trong việc đóng vai trò là 1 layer bọc bussinesslogic.

HIểu đơn giản là ORM bọc technical, còn Repo bọc nghiệp vụ. Rõ ràng nếu là 1 SA hay dev bác không muốn đem cục này ở khắp nơi
_dbContext.Invoices
.Where(x => x.TaxEntityId == taxEntityId
&& x.Status != 1
&& x.IssueDate >= from
&& x.IssueDate <= to);

Thay vì chỉ cần

invoiceRepository.GetInvoicesInPeriod();
1 cái expose Iqueryable<> còn 1 cái expose business intent. Với 1 dự án chỉ crud vài chục bảng thì không sao nhưng nếu dự án có nghiệp vụ phức tạp chút theo em là khác biệt rõ ràng đấy.

Chưa kể việc mock _dbContext để unitest cũng có cả tỷ vấn đề khi mock các dbset và return iqueryable<>, trong khi cái em cần ở unit test là test business logic, em chỉ cần mock result cho repository là được.

CHung quy lại thì pattern nào cũng có ưu nhược điểm và luôn phải trade-off thôi. Không có đúng sai mà chỉ có phù hợp hay không thôi.
 
Sửa lần cuối:
Theo e thấy thì cả bác Frog và các bác kia đều có ý đúng, nhưng em bổ sung thêm 1 góc nhìn support cho việc dùng repository pattern khi dự án dùng ORM là layer Repository mang lại lợi ích trong việc đóng vai trò là 1 layer bọc bussinesslogic.

HIểu đơn giản là ORM bọc technical, còn Repo bọc nghiệp vụ. Rõ ràng nếu là 1 SA hay dev bác không muốn đem cục này ở khắp nơi

1 cái expose Iqueryable<> còn 1 cái expose business intent. Với 1 dự án chỉ crud vài chục bảng thì không sao nhưng nếu dự án có nghiệp vụ phức tạp chút theo em là khác biệt rõ ràng đấy.

Chưa kể việc mock _dbContext để unitest cũng có cả tỷ vấn đề khi mock các dbset và return iqueryable<>, trong khi cái em cần ở unit test là test business logic, em chỉ cần mock result cho repository là được.

CHung quy lại thì pattern nào cũng có ưu nhược điểm và luôn phải trade-off thôi. Không có đúng sai mà chỉ có phù hợp hay không thôi.
invoiceRepository.GetInvoicesInPeriod();
Repository thuộc infrastructure layer thì sao lại chứa GetInvoicesInPeriod() thuộc về domain được bác.

invoiceDomain.GetInvoicesInPeriod(); thì nó sẽ rõ ràng hơn. Giả sử GetInvoicesInPeriod là nghiệp vụ mà lại nằm trong repo thì invoiceDomain đang không mô tả đầy đủ business logic của nó và
GetInvoicesInPeriod() đang nằm ở vùng xám của Domain layer và Infrastructure layer
 
Như e đang làm có case này do thiết kế db lỏ mà ko dùng repository code nó dài ngoằng. Giả sử có bảng Category chứa các record cũng như các version của nó trong đó. Muốn lấy ra version hiện tại của 1 record nào phải viết đoạn query khá dài vì phải join do .net cũ quá ko xài đc window function. Giờ đoạn ấy ko viết 1 hàm trong repo rồi dùng lại mà đẩy code lên chỗ services chắc e xỉu mất
Keaa7zY.gif
 
invoiceRepository.GetInvoicesInPeriod();
Repository thuộc infrastructure layer thì sao lại chứa GetInvoicesInPeriod() thuộc về domain được bác.

invoiceDomain.GetInvoicesInPeriod(); thì nó sẽ rõ ràng hơn. Giả sử GetInvoicesInPeriod là nghiệp vụ mà lại nằm trong repo thì invoiceDomain đang không mô tả đầy đủ business logic của nó và
GetInvoicesInPeriod() đang nằm ở vùng xám của Domain layer và Infrastructure layer
fen cứ nghĩ đơn giản thôi. Repository là 1 nơi chứa query thuộc cái domain fen đang code. Invoices thì InvoiceRepository để câu GetInvoicesInPeriod là chuẩn rồi. Giả sử GetInvoicesInPeriod có thể cache được, hay phải query trên nhiều partition, shard, etc. thì nó phải nằm ở Repository để những thằng Service khác dùng được chứ k để chung, chạy thẳng DbContext hay ORM gì đó được, thế thì cái service nó bát nháo cực kỳ

fen cứ nghĩ Repository là lớp truy vấn dữ liệu của 1 domain cụ thể thì cái ý của fen trên make sense liền
 
Như e đang làm có case này do thiết kế db lỏ mà ko dùng repository code nó dài ngoằng. Giả sử có bảng Category chứa các record cũng như các version của nó trong đó. Muốn lấy ra version hiện tại của 1 record nào phải viết đoạn query khá dài vì phải join do .net cũ quá ko xài đc window function. Giờ đoạn ấy ko viết 1 hàm trong repo rồi dùng lại mà đẩy code lên chỗ services chắc e xỉu mất
Keaa7zY.gif
viết trong service luôn, wrap toàn bộ query trong private method của service class là được mà. :rolleyes:
 
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 :sad:


via theNEXTvoz for iPhone
bac co the share mot vai repo implement ngon dc k bac
 
tôi add thêm rồi đó. Nói chung đây là 1 kiểu như insurance cho các thay đổi trong tương lai ấy. Có thể bây giờ anh thấy bullshit nhưng 5 năm 10 năm mấy thằng khác vật vã thì anh phẻ re. Có lẽ người ta ko biết tương lai nó thay đổi yêu cầu gì, nên xài cái generic nhất để đón đầu thoy
pzGVwuf.png


ví dụ anh viết sql cho mysql only, thằng lead đòi orm cho mọi loại sql, anh chửi vẽ chuyện, nhưng tương lai 10 năm nữa oracle nó giết mysql lại phải đổi sang postgres thì sao, orm nó đỡ cho anh hết. Lúc thay đổi đó anh ko phải chuyển code mysql trong 10 năm đó thành code postgresql. Cái repo pattern này có lẽ tương tự.
Bác tiên đoán cũng ghê đấy thằng oracle sút nguyên team code mysql rồi
 
Lần cuối các bác thực sự đổi database là khi nào vậy (ví dụ case simple nhất từ Postgres sáng MySQL), tôi thì chưa gặp nên chưa có kn.
 
Theo e thấy thì cả bác Frog và các bác kia đều có ý đúng, nhưng em bổ sung thêm 1 góc nhìn support cho việc dùng repository pattern khi dự án dùng ORM là layer Repository mang lại lợi ích trong việc đóng vai trò là 1 layer bọc bussinesslogic.

HIểu đơn giản là ORM bọc technical, còn Repo bọc nghiệp vụ. Rõ ràng nếu là 1 SA hay dev bác không muốn đem cục này ở khắp nơi

1 cái expose Iqueryable<> còn 1 cái expose business intent. Với 1 dự án chỉ crud vài chục bảng thì không sao nhưng nếu dự án có nghiệp vụ phức tạp chút theo em là khác biệt rõ ràng đấy.

Chưa kể việc mock _dbContext để unitest cũng có cả tỷ vấn đề khi mock các dbset và return iqueryable<>, trong khi cái em cần ở unit test là test business logic, em chỉ cần mock result cho repository là được.

CHung quy lại thì pattern nào cũng có ưu nhược điểm và luôn phải trade-off thôi. Không có đúng sai mà chỉ có phù hợp hay không thôi.
Nếu ko muốn đẩy 1 cục đi khắp nơi thì mình có thể cho xuống Application layer mà gọi. Và nếu Repo chỉ để bọc business logic, thì nói thật là chẳng cần nó cũng có thể làm được, quan trọng người code là ai.

Về việc test, mình nghĩ quan trọng là cách bạn xây dựng hệ thống test thế nào. Như cá nhân mình, nếu đã dùng ORM thì build thêm luôn InMemory hoặc SQLite Database local trên môi trường Dev cho việc test, và mình thấy test còn nhanh và tiện hơn nhiều. Vì mình chỉ việc đẩy vào raw data là test được ngay, chứ bạn Mock thì cái input cần để test nó là processed data rồi, cho nên ko nhanh được, ko cẩn thận vớ vẩn data để test còn sai nữa ấy chứ.
 

Thống kê chủ đề

Ngày tạo
Pepe.The.Frog,
Người trả lời cuối
never_can_tell_1,
Trả lời
251
Lượt xem
43.453
Quay lại
Lên đầu trang