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

Vozer cấp tiến

Senior Member
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...
Cảm ơn thím nhiều, vậy nó cũng là bussiness logic nhưng ở nghiệp vụ phức tạp hơn ạ.
 

cuoc_song

Đã tốn tiề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
Ủa thế anh ko đọc à ? Tôi trình bày chi tiết là tôi làm gì mà. Và những cái tôi làm nếu dùng ORM thì nó rác, và thậm chí là không làm được. Ví dụ như nghiệp vụ của tôi là không cho phép trực tiếp tạo sửa OrderContent, thì tôi không có OrderContentRepository => trong code nghiệp vụ của tôi không thể có thằng nào trực tiếp thay đổi cái này được cả. Còn nếu chỉ dùng ORM thì làm sao tôi biết được là bọn nó có trực tiếp sửa OrderContent ở đâu không ?
 

Meete

Senior Member
Cảm ơn thím nhiều, vậy nó cũng là bussiness logic nhưng ở nghiệp vụ phức tạp hơn ạ.
Ở những project có business logic phức tạp người ta sẽ muốn isolate toàn bộ phần logic đó vào một nơi nào đó để dễ dev, test...

Cái nơi đó người ta thường gọi là domain layer. Nó đơn giản là nhận input tính toán xong trả output, còn lại lưu trữ ntn thì nó ko quan tâm.

Thực tế thì ít project nào cần tới mức như vậy, trên mạng đầy ví dụ nhưng mà cơ bản là nó đơn giản quá nên áp dụng nó khá là cưỡng ép.
 

Pepe.The.Frog

Senior Member
Ủa thế anh ko đọc à ? Tôi trình bày chi tiết là tôi làm gì mà. Và những cái tôi làm nếu dùng ORM thì nó rác, và thậm chí là không làm được. Ví dụ như nghiệp vụ của tôi là không cho phép trực tiếp tạo sửa OrderContent, thì tôi không có OrderContentRepository => trong code nghiệp vụ của tôi không thể có thằng nào trực tiếp thay đổi cái này được cả. Còn nếu chỉ dùng ORM thì làm sao tôi biết được là bọn nó có trực tiếp sửa OrderContent ở đâu không ?

Đấy chính xác là cái hiểu lầm tào lao của các anh. ORM nó support hết và các anh chỉ là ko biết xài nó thế nào thôi. Còn chuyện ko xài ORM thì nó là phạm trù về Persistance layer anh chọn ORM hay draw sql thôi.
 

Vozer cấp tiến

Senior Member
Ở những project có business logic phức tạp người ta sẽ muốn isolate toàn bộ phần logic đó vào một nơi nào đó để dễ dev, test...

Cái nơi đó người ta thường gọi là domain layer. Nó đơn giản là nhận input tính toán xong trả output, còn lại lưu trữ ntn thì nó ko quan tâm.

Thực tế thì ít project nào cần tới mức như vậy, trên mạng đầy ví dụ nhưng mà cơ bản là nó đơn giản quá nên áp dụng nó khá là cưỡng ép.
Cảm ơn thím, quay lại thớt thì là tuỳ nhu cầu sử dụng, cần tổng hợp dữ liệu ở nhiều repository khác nhau thì dùng, đơn giản không cần dùng thì bỏ mà gọi trực tiếp orm, có dùng cũng là cưỡng ép phải không thím?
 

joonkim

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

Repository chỉ đi cùng UOW thôi, còn Aggregate là của DDD rồi và nó tách rời khỏi pattern kia.

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

Chính xác là DI ở đây, các layer làm việc với nhau qua interface và không quan trọng bên dưới dùng sql hay nosql. Hơn nữa khi cần replace service dùng provider này sang provider khác sẽ chỉ cần unit test lại trên repo đó thôi.

Còn thớt có thể dùng hay không thì tùy bạn ấy, nhưng nói nó bullshit thì :beat_brick: vì bạn ấy nhìn hơi gần rồi :haha:
 

Pepe.The.Frog

Senior Member
Repository chỉ đi cùng UOW thôi, còn Aggregate là của DDD rồi và nó tách rời khỏi pattern kia.



Chính xác là DI ở đây, các layer làm việc với nhau qua interface và không quan trọng bên dưới dùng sql hay nosql. Hơn nữa khi cần replace service dùng provider này sang provider khác sẽ chỉ cần unit test lại trên repo đó thôi.

Còn thớt có thể dùng hay không thì tùy bạn ấy, nhưng nói nó bullshit thì :beat_brick: vì bạn ấy nhìn hơi gần rồi :haha:

Khai sáng cho tôi đi anh. Nếu anh đưa ra ví dụ cụ thể (có code) nào phải cần repo pattern mà ko dùng ORM hay design pattern dc ngoài mấy cái tôi đã nêu ở trên thì tôi tụt quần xin lỗi... :feel_good:
 

joonkim

Member
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.





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.



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.



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?



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 đó.

Bạn hiểu UOW ở khía cạnh nó là 1 transaction như ORM xử lý rồi, còn chắc bạn chưa từng làm hệ thống có UOW wrap nhiều service trong đó và xử lý resolve mutil tenant trong đó rồi.
 

Pepe.The.Frog

Senior Member
Bạn hiểu UOW ở khía cạnh nó là 1 transaction như ORM xử lý rồi, còn chắc bạn chưa từng làm hệ thống có UOW wrap nhiều service trong đó và xử lý resolve mutil tenant trong đó rồi.

Khai sáng cho tôi cái này luôn nhá anh. Cái anh nói là transaction scope. Hoặc trong microservice có thể dùng SAGA để quản lý unit of work cho việc gọi nhiều service. Cái này là phạm trù khác và ngay cả việc đó thì repository pattern của anh cũng ko làm dc.
 

cuoc_song

Đã tốn tiền
Khai sáng cho tôi đi anh. Nếu anh đưa ra ví dụ cụ thể (có code) nào phải cần repo pattern mà ko dùng ORM hay design pattern dc ngoài mấy cái tôi đã nêu ở trên thì tôi tụt quần xin lỗi... :feel_good:
Ví dụ tôi có 1 bảng History và chỉ có Create, Get, List, Count và không được phép Update hay Delete. Làm sao tôi có thể kiểm soát được việc không có thằng nào code ngu đi update lại History với việc chỉ sử dụng ORM. Bảng History này sẽ được dùng trong rất nhiều chỗ bởi rất nhiều các service khác nhau.

Ví dụ khác là tôi có 1 cái bảng Master Data được dùng cực nhiều nhưng rất ít thay đổi. Tôi muốn đưa nó lên cache mà không phải động chạm vào nghiệp vụ cũ của tôi vì nó quá phức tạp. Vậy tôi phải làm sao với ORM. Cache tôi sử dụng là Redis
 

joonkim

Member
Khai sáng cho tôi đi anh. Nếu anh đưa ra ví dụ cụ thể (có code) nào phải cần repo pattern mà ko dùng ORM hay design pattern dc ngoài mấy cái tôi đã nêu ở trên thì tôi tụt quần xin lỗi... :feel_good:

Chả có cái code nào bắt buộc dùng repo pattern cả. Kể cả anh có dùng ADO để code cũng được, chả cần đến ORM.

Vấn đề anh đang vin vào để cãi là vì anh cảm thấy thừa thãi. Thế như trên tôi thấy ORM cũng thừa và performance ko tốt bằng ADO à. Tranh cãi thế thì hết ngày chả giải quyết được gì.

Còn keyword nhiều ae ở đây nói rồi, tự ngồi mà search thôi. Chứ áp dụng pattern mà cứ như rau muống lên mạng hỏi có người cấp cho thì cái nghề ltv này nó rẻ rách quá. :beat_brick:

Tôi thấy anh đang có trouble gì với cái pattern này, chứ cá nhân tôi chả thấy nó bullshit ở đâu cả.
 

Pepe.The.Frog

Senior Member
Chả có cái code nào bắt buộc dùng repo pattern cả. Kể cả anh có dùng ADO để code cũng được, chả cần đến ORM.

Vấn đề anh đang vin vào để cãi là vì anh cảm thấy thừa thãi. Thế như trên tôi thấy ORM cũng thừa và performance ko tốt bằng ADO à. Tranh cãi thế thì hết ngày chả giải quyết được gì.

Còn keyword nhiều ae ở đây nói rồi, tự ngồi mà search thôi. Chứ áp dụng pattern mà cứ như rau muống lên mạng hỏi có người cấp cho thì cái nghề ltv này nó rẻ rách quá. :beat_brick:

Tôi thấy anh đang có trouble gì với cái pattern này, chứ cá nhân tôi chả thấy nó bullshit ở đâu cả.

Anh đọc lại #1 của tôi. Bullshit ở chổ nó thừa thải khi trong dự án đã dùng ORM rồi còn đi tạo thêm cái Repository nữa.

Còn chuyện ko dùng ORM mà dùng thẳng ADO thì tôi cũng có nói ở post trước là chuyện này đúng! Ko có gì bàn cãi.

Cái tôi tranh cãi ở đây là trường hợp dự án đang dùng ORM!
 

levinhtin

Senior Member
Cũng có thể do thằng EntityFramework quá tốt nên có thể sử dụng và điều chỉnh dễ dàng trong nhiều trường hợp. Tôi cũng khá đồng ý nếu dùng DotNet EntityFramework thì cũng không cần thêm Repository làm gì.
Nhưng ở một ngôn ngữ khác thì ORM không support tốt thì sao.
Hay trong cả DotNet nếu dùng ORM Dapper thì sao. Phải viết repository chứ, không lẻ gọi Dapper + query trong tất cả các service.
 

cuoc_song

Đã tốn tiền
Anh đọc lại #1 của tôi. Bullshit ở chổ nó thừa thải khi trong dự án đã dùng ORM rồi còn đi tạo thêm cái Repository nữa.

Còn chuyện ko dùng ORM mà dùng thẳng ADO thì tôi cũng có nói ở post trước là chuyện này đúng! Ko có gì bàn cãi.

Cái tôi tranh cãi ở đây là trường hợp dự án đang dùng ORM!
Cái anh thấy nó thừa là vì thằng build Repository nó build ngu thôi
 

Pepe.The.Frog

Senior Member
Cũng có thể do thằng EntityFramework quá tốt nên có thể sử dụng và điều chỉnh dễ dàng trong nhiều trường hợp. Tôi cũng khá đồng ý nếu dùng DotNet EntityFramework thì cũng không cần thêm Repository làm gì.
Nhưng ở một ngôn ngữ khác thì ORM không support tốt thì sao.
Hay trong cả DotNet nếu dùng ORM Dapper thì sao. Phải viết repository chứ, không lẻ gọi Dapper + query trong tất cả các service.

Nếu xài dapper thì thằng dapper này coi như là extensioncủa Ado.net thôi, cái repository pattern chính là data access layer nên tôi ko tranh cãi, vẫn nên có 1 data access layer.

Cái anh thấy nó thừa là vì thằng build Repository nó build ngu thôi

Tôi cũng nghĩ thế :))

2 anh này... vấn đề tôi muốn nói là thậm chí cái thằng build repository nó "khôn" thì cũng là thừa vì ORM như Entity Framework/Hibernate nó làm hết rồi. Các anh build lại là phát minh lại cái banh xe nên tôi mới nói bullshit!
 

cuoc_song

Đã tốn tiền
Ví dụ tôi có 1 bảng History và chỉ có Create, Get, List, Count và không được phép Update hay Delete. Làm sao tôi có thể kiểm soát được việc không có thằng nào code ngu đi update lại History với việc chỉ sử dụng ORM. Bảng History này sẽ được dùng trong rất nhiều chỗ bởi rất nhiều các service khác nhau.

Ví dụ khác là tôi có 1 cái bảng Master Data được dùng cực nhiều nhưng rất ít thay đổi. Tôi muốn đưa nó lên cache mà không phải động chạm vào nghiệp vụ cũ của tôi vì nó quá phức tạp. Vậy tôi phải làm sao với ORM. Cache tôi sử dụng là Redis
@Pepe.The.Frog anh trả lời cái câu này của tôi đi
 

levinhtin

Senior Member
Nếu xài dapper thì thằng dapper này coi như là extensioncủa Ado.net thôi, cái repository pattern chính là data access layer nên tôi ko tranh cãi, vẫn nên có 1 data access layer.

Là sao bác, vậy vẫn phải viết Repository + ORM là đúng hay sai.
 
Ví dụ tôi có 1 bảng History và chỉ có Create, Get, List, Count và không được phép Update hay Delete. Làm sao tôi có thể kiểm soát được việc không có thằng nào code ngu đi update lại History với việc chỉ sử dụng ORM. Bảng History này sẽ được dùng trong rất nhiều chỗ bởi rất nhiều các service khác nhau.

Ví dụ khác là tôi có 1 cái bảng Master Data được dùng cực nhiều nhưng rất ít thay đổi. Tôi muốn đưa nó lên cache mà không phải động chạm vào nghiệp vụ cũ của tôi vì nó quá phức tạp. Vậy tôi phải làm sao với ORM. Cache tôi sử dụng là Redis

Lần cuối t dùng repo là năm 2016.

Tôi trả lời cho bạn là 2 cái ví dụ này ko cần repository pattern gì cả. Để đảm bảo 1 record ko bị delete/update có cả trăm cách làm. Thêm nữa là dùng repo cũng chẳng đảm bảo đc record ko update.

Cache cũng vậy thôi.

Tư duy của bạn bó buộc quá thành ra ko chịu sáng tạo tìm tòi.
 

cuoc_song

Đã tốn tiền
Lần cuối t dùng repo là năm 2016.

Tôi trả lời cho bạn là 2 cái ví dụ này ko cần repository pattern gì cả. Để đảm bảo 1 record ko bị delete/update có cả trăm cách làm. Thêm nữa là dùng repo cũng chẳng đảm bảo đc record ko update.

Cache cũng vậy thôi.

Tư duy của bạn bó buộc quá thành ra ko chịu sáng tạo tìm tòi.
Đang hỏi cách nào với ORM thì anh lại bảo là cả trăm cách làm là sao ? Với Repo thì tôi làm đơn giản thôi là interface của nó không có cho phép update. Thì trừ khi bọn nó sửa interface hoặc break cấu trúc code chung còn không thì nó không có cách nào cả. Và tôi là thằng thiết kế tôi đi kiểm soát các thứ qua interface.
 
Top