Tối giản việc đọc tin nổi bật, comment chất lượng nhiều reaction trên voz cho các fen bận rộn.
VozFen.com: [thảo luận] [Thảo luận] Repository Pattern là cái bullsh*t nhất khi đã có ORM framework?
@Pepe.The.Frog
#1

[thảo luận] [Thảo luận] Repository Pattern là cái bullsh*t nhất khi đã có ORM framework?
Như tít. Theo tôi nó chẳng lợi lộc gì cả. Đẽ ra cho rách việc thêm. Thế mà đi dự án nào cũng thấy ng ta setup cái này.
Update từ #10:
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)
Update:
Để tránh mọi sự hiểu lầm tôi đang nói cụ thể cách Implement Repository Pattern sử dụng Generic Repository như trong link này là bullshit khi đã có ORM:
https://docs.microsoft.com/en-us/as...f-work-patterns-in-an-asp-net-mvc-application
Theo cách dùng Generic Repository như này thì mổi repo tương ứng 1-1 với Entity. Lúc này nó implement ngu là ko có abstract ra IQueryable nên ko join/query đươc. Và quan trọng là useless vì đã có Ef rồi.
Còn anh nào implement Repository xem như Data Access Class trong mô hình 3 layers cổ điển thì tôi ko tranh cãi vì bản chất 2 design support 2 chuyện khác nhau:
1. Generic Repository là để abstract luôn cả cách query/update data cho từng entity type /table riêng lẽ. (việc mà ngày xưa chưa có ORM mới phải làm).
2. Data Access Class (trong 3 layers) là để gom các query logic, business rules. Dự án anh nào lớn thì xài 3 layers, dự án nào nhỏ thì xài 2 layers nhưng điểm chung là đều sử dụng ORM như dbContext, Hibernate session. Nhiều anh sử dụng tên DAL class là Repository luôn nên dễ hiểu lầm với cái implement Generic Repository kia.
https://www.thereformedprogrammer.net/is-the-repository-pattern-useful-with-entity-framework-core/

Update từ #10:
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)
Update:
Để tránh mọi sự hiểu lầm tôi đang nói cụ thể cách Implement Repository Pattern sử dụng Generic Repository như trong link này là bullshit khi đã có ORM:
https://docs.microsoft.com/en-us/as...f-work-patterns-in-an-asp-net-mvc-application
Theo cách dùng Generic Repository như này thì mổi repo tương ứng 1-1 với Entity. Lúc này nó implement ngu là ko có abstract ra IQueryable nên ko join/query đươc. Và quan trọng là useless vì đã có Ef rồi.
Còn anh nào implement Repository xem như Data Access Class trong mô hình 3 layers cổ điển thì tôi ko tranh cãi vì bản chất 2 design support 2 chuyện khác nhau:
1. Generic Repository là để abstract luôn cả cách query/update data cho từng entity type /table riêng lẽ. (việc mà ngày xưa chưa có ORM mới phải làm).
2. Data Access Class (trong 3 layers) là để gom các query logic, business rules. Dự án anh nào lớn thì xài 3 layers, dự án nào nhỏ thì xài 2 layers nhưng điểm chung là đều sử dụng ORM như dbContext, Hibernate session. Nhiều anh sử dụng tên DAL class là Repository luôn nên dễ hiểu lầm với cái implement Generic Repository kia.
https://www.thereformedprogrammer.net/is-the-repository-pattern-useful-with-entity-framework-core/

Meete
11/2016
@Meete
11/2016
#32

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

joonkim
01/2012
@joonkim
01/2012
#51

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

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

joonkim
01/2012
@joonkim
01/2012
#68

Nói chúng các anh ko quan tâm đến DDD hoặc microservices thì bỏ qua. Hoặc application của các anh ko yêu cầu đến mức đó thì bỏ qua nó đi.
Tôi thấy tranh cãi vô nghĩa vcl
Tôi thấy tranh cãi vô nghĩa vcl


lazloq
03/2020
@lazloq
03/2020
#81

Share các thím 1 study case apply repository. Tôi có tình huống thế này:
Trong hệ thống e-commerce, model SalesOrder của tôi gồm những property sau:
SalesOrder
-> Customer information
-> Shipping/Billing address
-> Item list
Tôi có các lớp Services xử lý business logic, nhận input đầu vào là 1 object SalesOrder. (Gồm các nghiệp vụ trừ tồn, pick hàng, đóng gói, vận chuyển logistic v.v..)
Một ngày đẹp trời, công ty tôi ký hợp đồng với 1 đối tác bên ngoài, vận hành khâu xử lý đơn hàng. Trong hợp đồng ghi rõ là công ty tôi không được phép lưu dữ liệu khách hàng, thông tin khách hàng buộc phải gọi API về xử lý.
————————
Tôi xử dụng pattern repository từ đầu, trong repository, tôi viết các logic để build 1 model SalesOrder hoàn chỉnh (bao gồm collect thông tin các property customer, address, items) với SalesOrderRepository.get(order_code) trả về 1 model SalesOrder.
Với tình huống trên, tôi có 2 trường hợp:
Khi apply, tôi chỉ cần update ở phần repository, các lớp service business logic không update gì.
(*) Thông tin khách hàng là dữ liệu input để xử lý, không thay đổi trong suốt quá trình vận hành.
Trong hệ thống e-commerce, model SalesOrder của tôi gồm những property sau:
SalesOrder
-> Customer information
-> Shipping/Billing address
-> Item list
Tôi có các lớp Services xử lý business logic, nhận input đầu vào là 1 object SalesOrder. (Gồm các nghiệp vụ trừ tồn, pick hàng, đóng gói, vận chuyển logistic v.v..)
Một ngày đẹp trời, công ty tôi ký hợp đồng với 1 đối tác bên ngoài, vận hành khâu xử lý đơn hàng. Trong hợp đồng ghi rõ là công ty tôi không được phép lưu dữ liệu khách hàng, thông tin khách hàng buộc phải gọi API về xử lý.
————————
Tôi xử dụng pattern repository từ đầu, trong repository, tôi viết các logic để build 1 model SalesOrder hoàn chỉnh (bao gồm collect thông tin các property customer, address, items) với SalesOrderRepository.get(order_code) trả về 1 model SalesOrder.
Với tình huống trên, tôi có 2 trường hợp:
- Đơn hàng thường, thông tin khách hàng tôi query trực tiếp trong DB của công ty
- Đơn hàng đối tác, thông tin khách hàng tôi gọi API để fetch về
Khi apply, tôi chỉ cần update ở phần repository, các lớp service business logic không update gì.
(*) Thông tin khách hàng là dữ liệu input để xử lý, không thay đổi trong suốt quá trình vận hành.
tdat00
11/2008
@tdat00
11/2008
#83

Case của thím tôi cũng từng làm rồi, nhưng dùng API của bên thứ 3 nó lại phát sinh nhiều vấn đề như bên đó đổi schema không giống db của mình, response time chậm hoặc timeout, khó làm transaction cho nhiều api create/update... Thế nên bên tôi chốt làm riêng cái service mới chứ không phải repository.
Tôi không chê repository pattern dở, chỉ là thấy giờ ít nơi xài thôi.
Sent from Samsung SM-G973F using vozFApp

servuskevin
08/2021
@servuskevin
08/2021
#89

Ở đầu topic tui có nêu 2 ví dụ cần repository pattern mà anh em ko ai để ý. Chủ thớt thì trả lời như trên.
Tui có ý vầy thôi.
Ông thớt @Pepe.The.Frog ơi, cái cách giải quyết của ông chỉ là ông cố tình bỏ đi cái lớp Repository rồi đưa logic của nó lên lớp service hoặc static class hoặc extension methods. Rồi ông nhấn mạnh ko cần Repo Pattern. Ông bỏ Repository Pattern để đưa vào 1 đống anti pattern khác mà vẫn cho là đúng thì thôi.
Rồi DbContext rồi extension method nó là của Microsoft.net. thế giới lập trình nó ko chỉ có .net. Nó còn có Java,Python, Php,... nên cái Repository Pattern nó là cái abstract chung cho mọi ngôn ngữ. Nó giải quyết vấn đề chung.
Ông còn nói đũa với chén là một thì thôi tui đi. Nói gì nữa giờ.


Daibac6996
02/2022
@Daibac6996
02/2022
#96

Thôi bạn ah, chiều t6 rảnh rỗi vào đọc mấy cái thread trong này, tôi cay đến mức phải reg nick để phát biểu ý kiến, nhưng anh ếch kia vẫn ngồi trong cái giếng của ảnh, có nghe ai đâu

tdat00
11/2008
@tdat00
11/2008
#115

Vàng quan điểm
Mới đi uống cafe về giờ vẫn thấy còn cãi nhau à 
Đã gọi là pattern thì có bao giờ đúng hay sai đâu, nó chỉ là cách tổ chức code, anh thích dùng pattern nào thì dùng.
Anh gom hết đống code vào controller xử lý cũng chạy được, anh tách nó ra controller service repository cũng chạy được. Tóm lại là chả có cái gì đúng hay sai cả, tùy từng team mà xài cách phù hợp thôi.

Đã gọi là pattern thì có bao giờ đúng hay sai đâu, nó chỉ là cách tổ chức code, anh thích dùng pattern nào thì dùng.
Anh gom hết đống code vào controller xử lý cũng chạy được, anh tách nó ra controller service repository cũng chạy được. Tóm lại là chả có cái gì đúng hay sai cả, tùy từng team mà xài cách phù hợp thôi.
gamest
10/2006
@gamest
10/2006
#129

Tks ông, nhưng ít nhất cả 2 case thì repository pattern cũng có giá trị của nó phải không. Giống như việc abstraction trong oop thôi ấy, tùy yêu cầu mà cần thiết kế open for change hay không. Nếu SA tính đến khả năng phải sửa đổi thì vẫn cần dùng, việc dùng hay không thì phải do context chứ t ko nghĩ nó là vô dụng.

servuskevin
08/2021
@servuskevin
08/2021
#130

@Pepe.The.Frog tui già quá rồi nên ko hiểu nổi suy nghĩ của mấy anh trẻ bây giờ.
Tui và bạn bè già của tui thì ráng sống vui vẻ, hoà đồng, tạo không khí vui vẻ để mọi người chia sẻ trao đổi, làm việc.
Còn giờ thì câu view, click bait, khích bác lẫn nhau.
Tôi không hiểu cái kiểu quái thai gì đang diễn ra bây giờ nữa.
Thời tui là sống sao để mọi người yêu thương. Còn giờ càng bị chửi càng dzui hay sao vậy?
Meete
11/2016
@Meete
11/2016
#131

Vàng quan điểm
Anh em máu quá, vô xem mà chửi nhau vậy 
Sự nghiệp chục năm đi code của mình mới ngộ ra một cái cực kỳ quan trọng đó là sự cân bằng. Mềm mại ôn nhu như dòng nước, cân bằng âm dương thái cực, cái gì quá đều không tốt.
Như mình đã còm ở trên, nghệ thuật Architect phải cân bằng được các yếu tố trong project. Có những cái dùng luôn Spring JPA, có những cái phải định nghĩa Repository concept từ domain layer trước.
Việc thay đổi ORM hay thậm chí DBMS là việc hiếm trong vòng đời của một project nhưng có những trường hợp thực sự phải cần Repository concept trước.
Lấy ví dụ trong thực tế là một project mình đang triển khai. Entity nó được fetch từ nhiều source khác nhau, có thể internal từ RDBMS mà cũng có thể external từ Web Service.
Entity có nghiệp vụ nằm trong đó nên ko thể vứt nó ra chỗ khác vì gây rò rỉ domain.

Sự nghiệp chục năm đi code của mình mới ngộ ra một cái cực kỳ quan trọng đó là sự cân bằng. Mềm mại ôn nhu như dòng nước, cân bằng âm dương thái cực, cái gì quá đều không tốt.
Như mình đã còm ở trên, nghệ thuật Architect phải cân bằng được các yếu tố trong project. Có những cái dùng luôn Spring JPA, có những cái phải định nghĩa Repository concept từ domain layer trước.

Việc thay đổi ORM hay thậm chí DBMS là việc hiếm trong vòng đời của một project nhưng có những trường hợp thực sự phải cần Repository concept trước.
Lấy ví dụ trong thực tế là một project mình đang triển khai. Entity nó được fetch từ nhiều source khác nhau, có thể internal từ RDBMS mà cũng có thể external từ Web Service.
Entity có nghiệp vụ nằm trong đó nên ko thể vứt nó ra chỗ khác vì gây rò rỉ domain.

tdat00
11/2008
@tdat00
11/2008
#133


Chắc thím 8x giống tôi, qua 9x thấy tụi nó khác nhiều rồi, đến 2k còn khác bạo nữa.
Dĩ hòa vi quý thím ơi, đi chơi ~gay~ với tôi đi

Sent from Samsung SM-G973F using vozFApp
cuoc_song
03/2007
@cuoc_song
03/2007
#143

Tôi nghĩ là các anh nên thống nhất lại cái định nghĩa về Repository đi. Cái GenericRepository là sai về mặt định nghĩa rồi, Output của nó là IQueryable cũng là sai định nghĩa rồi. Bàn luận trên 1 cái sai thì bàn đến bao giờ .
DDD Quickly
DDD Quickly

Daibac6996
02/2022
@Daibac6996
02/2022
#168

Anh Ếch cứ chửi vì bài toàn của ảnh ko cần Repository, còn của người khác lại cần. Dù EF nó implement sẵn nhưng đôi khi tự build cái Repository khác wrap ngoài lại dễ làm thêm những cái khác. Đơn giản như dự án của tôi, ở phần Repository các query của bọn tôi cần build thêm 1 số default param, và nó centralize ở cái repo đó thôi, ko muốn phải viết lại ở đống service. Hơn nữa nó liên quan đến bài toàn caching, cái Cache provider của của thằng EF nó ko đáp ứng dc, nên chúng tôi xử lý cache luôn ở Repository. Những thứ này có thể xử lý trong cái DbContext, nhưng nó phức tạp hơn việc bọn tôi xử lý ở thằng Repo
Mặt khác chúng tôi cũng ko muốn ở phía service nó access vào cái DbContext. Tôi đọc cái đoạn anh bảo review code để cấm dev làm cái này, tôi cười vl. Như anh gì trên kia bảo, thế cần đéo access modifier, cần đéo gì interface contract.
Anh cứ nhìn qua cái giếng của anh, thì anh còn thấy nhiều cái thối nữa
Mặt khác chúng tôi cũng ko muốn ở phía service nó access vào cái DbContext. Tôi đọc cái đoạn anh bảo review code để cấm dev làm cái này, tôi cười vl. Như anh gì trên kia bảo, thế cần đéo access modifier, cần đéo gì interface contract.
Anh cứ nhìn qua cái giếng của anh, thì anh còn thấy nhiều cái thối nữa
01/2022
đọc thấy thì có lẽ đây là thêm 1 layer of indirection, để xài đủ kiểu db bên dưới, ko nhất thiết phải là sql. Orm cũng là 1 layer of indirection cho cái loại sql như mysql/sqlite/postgresql,mssql,oracle v.v... Cái repository này là thêm 1 layer of indirection cho các loại db khác nhau luôn, sql, nosql, xml, v.v... Có câu "All problems in computer science can be solved by another level of indirection" cứ thêm con trỏ tới con trỏ tới con trỏ là giải quyết được hết, ko giải quyết được thì thêm con trỏ tới con trỏ tới con trỏ tới con trỏ
nói thêm, cần thêm 1 layer như vậy nữa để "đi tắt đón đầu". Viết code cái khó nhất ko phải là viết ra code chạy được mà là viết ra phần mềm dễ ứng phó với thay đổi. Business phát triển thì yêu cầu nó thay đổi liên tục, nay nó đòi mysql làm db, mai nó đòi mariadb, mốt nó đòi postgres thì anh xài orm, ví dụ đổi vài dòng orm config là đổi được khỏe re chẳng hạn. Nhưng rồi tháng sau nó bỏ sql đòi nosql v.v.. thì cái orm ko support nosql chẳng hạn thì anh lại phải viết code mới hoàn toàn... Nếu ngay từ đầu anh xài repo pattern này thì nó bao hàm luôn tất cả, lúc đầu anh viết code khổ nhưng về sau phẻ re. Đương nhiên tương lai ko ai nói trước được điều gì, có khi nó ko bắt thay đổi 180 độ như vậy thì công lao ban đầu của anh cũng coi như là insurance cho tương lai ấy mà