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
Ưng 3

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

Kâ…
Kân team v2

01/2022

@Kân team v2 01/2022
#6
Ưng 6
Vàng quan điểm
phải cái này ko: https://stackoverflow.com/questions/10155517/repository-pattern-vs-orm

The repository abstract persistence access, whatever storage it is. That is its purpose. The fact that you're using a db or xml files or an ORM doesn't matter. The Repository allows the rest of the application to ignore persistence details. This way, you can easily test the app via mocking or stubbing and you can change storages if it's needed. Today you might use MySql, tomorrow you'll want to use NoSql or Cloud Storage. Do that with an ORM!

đọ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à

Me…
Meete

11/2016

@Meete 11/2016
#32
Ưng 4
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...

jo…
joonkim

01/2012

@joonkim 01/2012
#51
Ưng 4
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...

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

jo…
joonkim

01/2012

@joonkim 01/2012
#68
Ưng 5
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

la…
lazloq

03/2020

@lazloq 03/2020
#81
Ưng 5
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:
  • Đơ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.

td…
tdat00

11/2008

@tdat00 11/2008
#83
Ưng 4
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:
  • Đơ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.

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

se…
servuskevin

08/2021

@servuskevin 08/2021
#89
Ưng 4
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ổ.

....

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.

Ở đầ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ờ.

Da…
Daibac6996

02/2022

@Daibac6996 02/2022
#96
Ưng 4
@Pepe.The.Frog Tui xài NHibernate hơn 6 năm. Từ 2010 đến 2016. Và vâng, tui xài Repository Pattern. Tui cũng ko hiểu với mô hình session như NHibernate thì anh ko xài Repository Pattern anh xài kiểu gì chia sẻ tôi biết.

Còn Helper Class aka Static class , Extension method là anti-pattern. Anh wtf tôi làm gì khi ai cũng biết điều đó? Còn tui chán lên chém gió vậy thôi. Chứng minh với ảnh có mang tui đồng nào nuôi con đâu. Thôi nhé.
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

td…
tdat00

11/2008

@tdat00 11/2008
#115
Ưng 5
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.

ga…
gamest

10/2006

@gamest 10/2006
#129
Ưng 4
1. Domain model và object mapping model (trong EF nó gọi là Entity) không phải là một -> Đúng vì Entity thật sự là thuộc tầng Data Access Layer. Về mặt tổ chức code có thể phân tụi nó ra 2 module và dùng AutoMapper/DTO để map 2 thằng này khi lấy data lên.

2. Trường hợp ko sử dụng EF nữa thì tất nhiên anh phải đập đi xây lại tầng Data Access layer và effort bỏ ra là như nhau giữa việc có xài Repository hay ko vì:
  1. Nếu xài Repository: -> Re-implement lại Repository bỏ đi cái EF, xài cái mới
  2. Nếu ko xài Repository -> Re-implement lại Service bỏ đi cái EF, xài cái mới
Vấn đề là logic nặng là ở tầng Data Access layer chứ Business Service khá ít nên việc tôi gọi trực tiếp EF bên trong business service cũng chẳng có gì sai và vẫn support Unit Test/Mock bình thường vì bản thân EF nó support chuyện đó rồi.

Hơn hết, việc đổi ORM là việc rất hiếm và đa số là ko đáng như tôi đã nói ở #12:
https://voz.vn/t/thao-luan-reposito...khi-da-co-orm-framework.490455/#post-15758632
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.

se…
servuskevin

08/2021

@servuskevin 08/2021
#130
Ưng 5
Tôi cố tình khích các anh vào để kéo page đấy. Ai khó chịu thì lượn thôi.

@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?

Me…
Meete

11/2016

@Meete 11/2016
#131
Ưng 6
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.

td…
tdat00

11/2008

@tdat00 11/2008
#133
Ưng 4
Gạch 1
@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?

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

cu…
cuoc_song

03/2007

@cuoc_song 03/2007
#143
Ưng 4
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

Therefore, use a Repository, the purpose of which is to encapsulate all the logic needed to obtain object references. The domain objects won’t have to deal with the infrastructure to get the needed references to other objects of the domain. They will just get them from the Repository and the model is regaining its clarity and focus. The Repository may store references to some of the objects. When an object is created, it may be saved in the Repository, and retrieved from there to be used later. If the client requested an object from the Repository, and the Repository does not have it, it may get it from the storage. Either way, the Repository acts as a storage place for globally accessible objects.

Da…
Daibac6996

02/2022

@Daibac6996 02/2022
#168
Ưng 4
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