thảo luận Clean Architecture có thật sự giúp ta code tốt hơn?

  • Người tạo chủ đề Người tạo chủ đề soibac123bk
  • Ngày bắt đầu Ngày bắt đầu
Sẵn topic về clean architecture nên mình tiện hỏi luôn. Khi các bác dùng clean architecture thì các bác có dùng DDD để modeling business logic không? Hay vẫn theo cách cũ là data objects + xử lý trong services?
 
Chừng nào làm project hạng nặng một vài năm , hoặc bussiness xong hết rồi hoặc framework , ko thì cứ copy patse thôi , framework cho sao thì theo vậy mà làm chế cháo suy nghĩ trăng sao rôi sau này cũng xoá thôi 😹, copy&paste find&replace là quá đủ
 
Sẵn topic về clean architecture nên mình tiện hỏi luôn. Khi các bác dùng clean architecture thì các bác có dùng DDD để modeling business logic không? Hay vẫn theo cách cũ là data objects + xử lý trong services?
cái này tuỳ hoàn cảnh, em thì có, đã là DDD thì business logic k được dính với bất kỳ một cái gì liên quan đến tầng infrastructure trong đó, đó là nguyên tắc, Còn khi apply vào thực tế thì em nghĩ còn tuỳ vào điều kiện cuj thể để đưa ra quyết định
 
đây là pet project mình đang tạm setup.
1696257974414.png


Gồm có: DDD + CQRS + Clean Architecture (C#)
Có vài điều mình vẫn còn đang khá lăn tăn.
1/ DDD khá cồng kềnh, mapping giữa internal properties(getters, setters bên Java) bằng constructor --> constructor bị phình to khá nhiều nếu entity có nhiều properties
2/ để gọi là clean thực sự thì ko hẳn, vì để tháo bớt depedency từ Domain Layer thì lại dùng interface để "cheat" dependency diagram.
3/Khi thử sử dụng DDD, khi load cả AggregateRoot (nhiều entities) lên memory thì kinh khủng. Phải kèm thêm rất nhiều Design khác đi kèm để tăng performance. Tầng Domain ko kèm DB ở bên trong, nên hầu như mọi thứ đều làm trên memory. Trước đây cũng vì code kiểu này mà product mình từng làm chết trên production vì host trên con server lởm (share resource VPS)
4/ DDD + Clean code + CQRS thực sự RẤT CỒNG KỀNHRẤT NHIỀU BOILERPLATE code. Cụ thể là boilerplate ở CQRS.
Flow Cơ bản của mình là: API Controller -> Command -> Command Handler -> Repository -> UnitOfWork(Db)
5/ Phần test, mình không thích xài Mock Test lắm, nhưng khá là đồng tình là có thể setup và móc thẳng 1 DB test(in memory db)
 
đây là pet project mình đang tạm setup.
Xem tệp đính kèm 2105121

Gồm có: DDD + CQRS + Clean Architecture (C#)
Có vài điều mình vẫn còn đang khá lăn tăn.
1/ DDD khá cồng kềnh, mapping giữa internal properties(getters, setters bên Java) bằng constructor --> constructor bị phình to khá nhiều nếu entity có nhiều properties
2/ để gọi là clean thực sự thì ko hẳn, vì để tháo bớt depedency từ Domain Layer thì lại dùng interface để "cheat" dependency diagram.
3/Khi thử sử dụng DDD, khi load cả AggregateRoot (nhiều entities) lên memory thì kinh khủng. Phải kèm thêm rất nhiều Design khác đi kèm để tăng performance. Tầng Domain ko kèm DB ở bên trong, nên hầu như mọi thứ đều làm trên memory. Trước đây cũng vì code kiểu này mà product mình từng làm chết trên production vì host trên con server lởm (share resource VPS)
4/ DDD + Clean code + CQRS thực sự RẤT CỒNG KỀNHRẤT NHIỀU BOILERPLATE code. Cụ thể là boilerplate ở CQRS.
Flow Cơ bản của mình là: API Controller -> Command -> Command Handler -> Repository -> UnitOfWork(Db)
5/ Phần test, mình không thích xài Mock Test lắm, nhưng khá là đồng tình là có thể setup và móc thẳng 1 DB test(in memory db)
Thường thì nếu như domain object to quá thì fence nên nghĩ tới việc tìm cách chia nhỏ nó ra là được.
Còn từ Api Controller -> Command Handler -> Repo thì fence ko phải implement tầng service như bình thường thì mình ko nghĩ là phải boilerplate nhiều gì đâu. Xài Cqrs không thôi với flow như fence kể thì ổn mà.
 
Thường thì nếu như domain object to quá thì fence nên nghĩ tới việc tìm cách chia nhỏ nó ra là được.
Còn từ Api Controller -> Command Handler -> Repo thì fence ko phải implement tầng service như bình thường thì mình ko nghĩ là phải boilerplate nhiều gì đâu. Xài Cqrs không thôi với flow như fence kể thì ổn mà.
mình còn tính làm thêm phần event sourcing nữa. Đã setup thử cho 1 entity, cũng khá ổn, mà để stress test thử xem coi chịu đc nhiệt ko. Ko đc thì phải coi lại phần design :D.

Tựu chung lại là app CRUD ko nên làm DDD, xài clean arch + CQRS là ổn.
 
Đợt tôi có xem video này quan điểm khá hay về clean code. Chung quy lại là tùy dự án mà áp dụng thôi, code tốt và dễ maintain chưa chắc cần follow clean code :angry:. Dev hay bị cuốn vào Overengineering, nhiều khi một cái service rất đơn giản vài ngàn user, mà nhồi một lố architect + công nghệ vô :canny:
 
Đợt tôi có xem video này quan điểm khá hay về clean code. Chung quy lại là tùy dự án mà áp dụng thôi, code tốt và dễ maintain chưa chắc cần follow clean code :angry:. Dev hay bị cuốn vào Overengineering, nhiều khi một cái service rất đơn giản vài ngàn user, mà nhồi một lố architect + công nghệ vô :canny:
đúng. Để áp dụng DDD đúng như Martin Flower hay như trong sách thì nó rất là bí bách, vì quá nhiều layer. Cứ mỗi layer thì phải làm data mapping -> rất dễ bị convert data error hoặc bị duplicate data model.

Clean code có nghĩa là clean ở mức readable, chứ ko có nghĩa là clean code là best performance code.

Cụ thể nếu như post trước của mình, nếu làm task bulk import, thì connect thẳng db và dump data vào db sẽ bao nhanh hơn là clean code gọi qua CQRS để insert từng record.
 
mình còn tính làm thêm phần event sourcing nữa. Đã setup thử cho 1 entity, cũng khá ổn, mà để stress test thử xem coi chịu đc nhiệt ko. Ko đc thì phải coi lại phần design :D.

Tựu chung lại là app CRUD ko nên làm DDD, xài clean arch + CQRS là ổn.
Cái mapping thì đúng là khá cồng kềnh nhưng mà nên follow như thế. Mỗi layers nên có 1 mapping riêng để tránh bug, nhiều thằng dev nó get set loạn xạ cả lên mà ko qui định rõ ràng thì nhiều lúc sẽ dính reference change + việc set nó dupplicate rất nhiều nơi.
Nên thằng domain object sẽ chỉ có private set thôi.
Fence code nhiều thì thấy nó ổn :D 1 phần nữa thường fence sẽ thiếu đó là phần integration với các services khác qua rest hoặc qua message queue thường thì sẽ đặt ở sau tầng repository. Và tầng này cũng phải có data object riêng vì liên quan nhiều tới external communication.
Cái mình bực nhất là các mapper thôi, kinh nghiệm của mình thì nên né những cái như AutoMapper ra và tuyệt đối ko dùng. Vừa tốn thời gian học library code vừa khó clean.
 
Cái mapping thì đúng là khá cồng kềnh nhưng mà nên follow như thế. Mỗi layers nên có 1 mapping riêng để tránh bug, nhiều thằng dev nó get set loạn xạ cả lên mà ko qui định rõ ràng thì nhiều lúc sẽ dính reference change + việc set nó dupplicate rất nhiều nơi.
Nên thằng domain object sẽ chỉ có private set thôi.
Fence code nhiều thì thấy nó ổn :D 1 phần nữa thường fence sẽ thiếu đó là phần integration với các services khác qua rest hoặc qua message queue thường thì sẽ đặt ở sau tầng repository. Và tầng này cũng phải có data object riêng vì liên quan nhiều tới external communication.
Cái mình bực nhất là các mapper thôi, kinh nghiệm của mình thì nên né những cái như AutoMapper ra và tuyệt đối ko dùng. Vừa tốn thời gian học library code vừa khó clean.
cứ qua mỗi 1 mapper là chắc chắn sẽ có bug nếu map sai. Vì thế phải thêm 1 tầng test nữa, khá rối rắm. Mình cứ đơn giản, đã thêm service layer và đã bỏ.

mình cũng ko dùng Mapper lib nào cả. Tự map tay thôi vì kinh nghiệm trước có làm 1 dự án nó map projection bị sai. Nên từ đó map tay sẽ tốt hơn.

Mình cũng code khá nhiều nên cũng muốn làm gì đó đơn giản là đc, vừa đủ tầng cho clean, vừa ko quá cồng kềnh.
 
cứ qua mỗi 1 mapper là chắc chắn sẽ có bug nếu map sai. Vì thế phải thêm 1 tầng test nữa, khá rối rắm. Mình cứ đơn giản, đã thêm service layer và đã bỏ.

mình cũng ko dùng Mapper lib nào cả. Tự map tay thôi vì kinh nghiệm trước có làm 1 dự án nó map projection bị sai. Nên từ đó map tay sẽ tốt hơn.

Mình cũng code khá nhiều nên cũng muốn làm gì đó đơn giản là đc, vừa đủ tầng cho clean, vừa ko quá cồng kềnh.
Cẩn thận thôi, code nhiều thì sẽ ko có cái bug nào cả. Xưa dính mấy bug về reference mới khó chứ bug về việc mapping liếc mắt cái nhìn ra ngay, sửa đơn giản :D
 
Nhiều khi bị lỗi mapping nhưng không phải ở service throw exception mà là những service trước map data sai nữa. Tụi nó không throw exception, phải trace lòi mắt :mad:
 
đây là pet project mình đang tạm setup.
Xem tệp đính kèm 2105121

Gồm có: DDD + CQRS + Clean Architecture (C#)
Có vài điều mình vẫn còn đang khá lăn tăn.
1/ DDD khá cồng kềnh, mapping giữa internal properties(getters, setters bên Java) bằng constructor --> constructor bị phình to khá nhiều nếu entity có nhiều properties
2/ để gọi là clean thực sự thì ko hẳn, vì để tháo bớt depedency từ Domain Layer thì lại dùng interface để "cheat" dependency diagram.
3/Khi thử sử dụng DDD, khi load cả AggregateRoot (nhiều entities) lên memory thì kinh khủng. Phải kèm thêm rất nhiều Design khác đi kèm để tăng performance. Tầng Domain ko kèm DB ở bên trong, nên hầu như mọi thứ đều làm trên memory. Trước đây cũng vì code kiểu này mà product mình từng làm chết trên production vì host trên con server lởm (share resource VPS)
4/ DDD + Clean code + CQRS thực sự RẤT CỒNG KỀNHRẤT NHIỀU BOILERPLATE code. Cụ thể là boilerplate ở CQRS.
Flow Cơ bản của mình là: API Controller -> Command -> Command Handler -> Repository -> UnitOfWork(Db)
5/ Phần test, mình không thích xài Mock Test lắm, nhưng khá là đồng tình là có thể setup và móc thẳng 1 DB test(in memory db)
1. b làm cách nào thì nếu đã clean code, mỗi component sẽ đều có prop riêng, chứ ai lại đi dùng ouput của 1 component khác.
2. Domain layer exposes các behavior của nó cho các layer khác (= aggregate root). b k thể tháo bớt vì business nó define thế.
3. case này mình sẽ k load cái collection đó lên. các behavior lên collection đó sẽ chuyển về event -> projection
5. code sẽ luôn có ít nhất unit và intergration test. unit thì phải mock r chạy sao đc
 
1. b làm cách nào thì nếu đã clean code, mỗi component sẽ đều có prop riêng, chứ ai lại đi dùng ouput của 1 component khác.
mình chưa hiểu ý này của bạn phàn output của component khác lắm.

Thì đây là trải nghiệm nói chung của mình về DDD,
 
DDD k phải fix cứng cách làm, nó cho b cách tiếp cận và cũng k lwan đến clean code. Mình thấy nhiều người cứng nhắc về cách làm, nhưng theo mình cái quan trọng là làm sao isolate đc bussiness code. đạt được level code chính là document, là nghiệp vụ là ổn.
về ý này có thể là mình type quá lẹ, mình lấy vd về mô hình n tier
1 request create comment, khi ở layer MVC nó là CreateCommentRequest -> vào layer service/repository nó lại là Comment Entity -> qua layer Notification -> nó lại là CommentCreatedEvent ...
qua mỗi layer thì cái Comment nó transfer sang 1 type khác, điều này đảm bảo cái flow data/data của bạn chạy đúng.
 

Thống kê chủ đề

Ngày tạo
soibac123bk,
Người trả lời cuối
CSharpCorner,
Trả lời
253
Lượt xem
50.376
Quay lại
Lên đầu trang