thảo luận Vấn đề về separate Repository/Service/Controller

  • Người tạo chủ đề Người tạo chủ đề soledad86
  • Ngày bắt đầu Ngày bắt đầu
1 file có 50+ function thôi mà bạn đã sợ à bạn. thế mời bạn xem redis source code với git source code.
https://github.com/redis/redis/blob/unstable/src/server.c
https://github.com/git/git/blob/master/diff.c
Ngoài ra anh em có thể xem root source tree của git và redis nó chia cực đơn giản
p/s: Hình như hồi đầu redis còn đút tất cả source code vào 1 file luôn cơ
Nói thật source của 2 ông trên mới có 6k LOC 1 file, tôi còn maintain 1 file source controller có 12k LOC cơ. Nhưng hệ thống nó vẫn ngon lành chả vấn đề gì căn bản mỗi hàm của nó chia ra cực kì clear, đọc tên hàm đã hiểu chưa cần đến comment
Những phần mềm phức tạp lại chia đơn giản. Còn mấy cái như thớt thì chia phức tạp. Mà chức năng nào cũng chia theo repository, model, entity, service, controller các thứ. Cũng tùy vì không phải phần mềm web nào cũng làm vậy và cách làm đó lại khá cứng nhắc.
 
Nếu vậy thì giải quyết vấn đề này như thế nào vậy bác?
Chia chương trình thành nhiều hàm nhỏ để tăng tính single responsibility + reuse.
Bỏ OOP chuyển sang FP.
Còn ông nào bảo source code gì 6k Sloc kia chắc là thánh rồi, tôi không hiểu merge code kiểu gì.

Sent from Samsung SM-G973F using vozFApp
6k loc là chỉ 1 người viết thôi, những người khác chỉ fix bug, nên không có chuyện conflict.

Những phần mềm phức tạp lại chia đơn giản. Còn mấy cái như thớt thì chia phức tạp. Mà chức năng nào cũng chia theo repository, model, entity, service, controller các thứ. Cũng tùy vì không phải phần mềm web nào cũng làm vậy và cách làm đó lại khá cứng nhắc.
CRUD mà.
 
Thì 1 ông cầm master thôi mà. Conflict (nếu có) cũng đâu có khó xử lí đâu. Mà tôi thấy merge 1 file đỡ đau đầu so với merge một đống file chứ
 
Những phần mềm phức tạp lại chia đơn giản. Còn mấy cái như thớt thì chia phức tạp. Mà chức năng nào cũng chia theo repository, model, entity, service, controller các thứ. Cũng tùy vì không phải phần mềm web nào cũng làm vậy và cách làm đó lại khá cứng nhắc.
Có thể nói mấy cái web chắc 99% chủ yếu là crud. Nâng cao hơn nữa thì kết nối api đến bên thanh toán hay google fb. Thực sự mà nói áp đống repo, service vào khác gì dùng nuke để giết gà con đâu.
 
Thì 1 ông cầm master thôi mà. Conflict (nếu có) cũng đâu có khó xử lí đâu. Mà tôi thấy merge 1 file đỡ đau đầu so với merge một đống file chứ

Tách nhỏ ra nhiều file mới đỡ conflict ông ơi. Gom chung vào 1 file rồi cái ông cầm master kia suốt ngày đi merge code hả.

Sent from Samsung SM-G973F using vozFApp
 
Lập luận logic là hơi kém à nha.

Giờ có 2 bảng: User và Order --> Có 2 repo UserRepo và OrderRepo.
Chắc chắn có 1 query liên quan tới cả User và Order, cứ gọi nó là 1 join query nhé.
Câu query này bảo đặt ở đâu cũng được phải ko nhỉ? Giờ đặt tạm ở UserRepo nhé.
Xong rồi trong OrderService cũng cần câu query ấy (logic rất thường gặp phải không nào?) thì lại phải invoke thằng UserRepo à? Thế thì làm sao còn đảm bảo tính 1 - 1 nữa :D
Đấy là anh nghĩ vậy thôi :) Tại sao anh không nghĩ đến việc sẽ có một repo khác handle những câu query kiểu liên quan đến cả 2 bảng user và order nhỉ. Ví dụ như UserOrdersJoinedRepo chẳng hạn (ví dụ nên bỏ qua tính đúng đắn của tên class đi nhé :)). Vẫn đảm bảo"repo xử lý table", vừa đảm bảo luôn cả single responsibility nhé :).
Còn cái cách bố trí câu query theo "lập luận logic" của anh nó có thuật ngữ gọi là "circular dependency" đấy :D
Nếu vậy thì giải quyết vấn đề này như thế nào vậy bác?
Đã nói ở trên nhé :)
 
Tách nhỏ ra nhiều file mới đỡ conflict ông ơi. Gom chung vào 1 file rồi cái ông cầm master kia suốt ngày đi merge code hả.

Sent from Samsung SM-G973F using vozFApp
Ông dùng pull/merge request bao giờ chưa. Ông master chỉ review rồi merge vào thôi mà có phải fix gì đâu. Ông mà phải fix conflict là ông dev fix bug kia ấy chứ
 
Ông dùng pull/merge request bao giờ chưa. Ông master chỉ review rồi merge vào thôi mà có phải fix gì đâu. Ông mà phải fix conflict là ông dev fix bug kia ấy chứ

Thôi, có vẻ ông ít gặp vụ code conflict rồi. Nó không đơn giản như ông nghĩ đâu, mà tôi cũng không biết giải thích sao cho dễ hiểu. Khi nào gặp ông sẽ ngộ ra.

Sent from Samsung SM-G973F using vozFApp
 
Thôi, có vẻ ông ít gặp vụ code conflict rồi. Nó không đơn giản như ông nghĩ đâu, mà tôi cũng không biết giải thích sao cho dễ hiểu. Khi nào gặp ông sẽ ngộ ra.

Sent from Samsung SM-G973F using vozFApp
Hờ tớ 10 năm exp, hiện đang lead team 7 người và quản lí 15 cái source base của 1 start up nhé. Bạn muốn chia sẻ kinh nghiệm gì với tớ cứ chia sẻ lên đây thôi :D Việc merge source code của member trong team một ngày t phải làm không dưới 10 lần đâu
 
Tách nhỏ ra nhiều file mới đỡ conflict ông ơi. Gom chung vào 1 file rồi cái ông cầm master kia suốt ngày đi merge code hả.

Sent from Samsung SM-G973F using vozFApp
file của anh nhiều người cùng thêm feature thì dễ conflict là đúng rồi. còn file của người ta chỉ có 1 người code feature, những người khác fix bug thì thêm unit test rồi tạo pull request, ông master chỉ việc merge, nên sẽ không có chuyện conflict.
 
Hờ tớ 10 năm exp, hiện đang lead team 7 người và quản lí 15 cái source base của 1 start up nhé. Bạn muốn chia sẻ kinh nghiệm gì với tớ cứ chia sẻ lên đây thôi :D Việc merge source code của member trong team một ngày t phải làm không dưới 10 lần đâu
nghe nói là bạn làm php, php mà quản lý tốt như thế cũng đáng nể đấy :)
 
nghe nói là bạn làm php, php mà quản lý tốt như thế cũng đáng nể đấy :)
Làm start up thực ra mỗi thứ 1 tí. Devops,front end,backend thậm chí có cả bê máy chủ lên viettel idc để lắp đặt nữa cơ :D
Nói về php thì ông nào chê thì chê chứ t thấy vẫn ok, quan trọng là nó giải quyết đc bài toán thôi. Php hồi xưa thì lởm chứ version 7 có static type là scale ngon lành rồi
 
Em làm việc tại công ty X được 3 năm, ae toàn senior.
Tại 1 công ty Y em mới vào, tình hình là em và ae có một số ý kiến bất đồng trong việc phân tách các layers gồm Repository / Service và Controller/Serverless Func

Các bác lâu năm exp cho em hướng xử lý trong case này với.

Sơ sơ tình hình là với vấn đề trên, em sẽ chia ra các layer với reponsibility khác nhau.
1. Repo: sẽ làm việc với SQL và map vào entity. thực hiện các tác vụ với DB của 1 table nào đó
(ví dụ: UserRepo sẽ làm việc với UserEntity và thực hiện các thao tác thêm xóa sửa đối với bảng User)
2. Service: sẽ chỉ làm việc với Repo và 3rd nếu có để cung cấp n-method cho 1 service nào đó. 1 Service có thể inject n-dependencies bao gồm các repo.
(ví dụ: AuthUserService sẽ làm việc với UserRepo, UserPermissionRepo, CryptoXXX (3rd) để cung cấp các method như RegisterUser, LoginUser ... vvv)
3. Controller/Func: sẽ chỉ làm việc với Service để thực thi các phương thức
(ví dụ: AuthController sẽ có API Login => trong đó sẽ call 2 action là AuthService.login và AuthService.getBasicInfo ... vvv)

Theo quan điểm của em thì nó là basic và flexible.. theo pattern này thì có thể apply cho bất kỳ ngôn ngữ nào.
Em có research thì cũng thấy các ref pattern giống giống cách của em .
https://exceptionnotfound.net/the-r...n-with-dependency-injection-and-asp-net-core/

Vấn đề là như vậy, em cũng trình bày với ae trong cty nhưng 4-10 người role cao hơn em ko đồng ý (em ko bàn tới skill của họ nhưng nếu họ giải thích được lí do chính đáng thì em ko comment), còn lại mấy ae dưới ko ý kiến -> 9/10.
Họ cho rằng controller nên gọi thẳng repository, còn service chỉ dùng cho 3rd.
logic nên implement luôn trong controller -> em có phản biện rằng có 1 số case cần dùng lại logic này thì ntn? thì ko trả lời được

Và do ý chỉ 1/10 nên cuối cùng thì ý kiến của em bị reject. Khi review code cũng bi soi khá nặng nề, hiuhiu
Các bác đã gặp hay có hướng xử lý nào cho trường hợp giống em không ?
My 2 cents:
Nếu controller gọi thẳng đến repo thì sẽ bị tight coupling => khó cho việc thay đổi hoặc tách nhỏ trong tương lai khi business bị phình to hoặc thay đổi.
Ví dụ:
  • Nếu controller gọi thẳng repo thì các anh "hát mẹ cốt" là bắt buộc phải lấy data từ db lên rồi. Sau này (giả sử) db của anh không còn cái entity đấy vì tách ra thành micro-service khác rồi, thì anh lại phải sửa lại code (+test) cho cái controller đấy. Còn nếu thay đổi implementation của repo để gọi đến 3rd party API thay vì gọi đến db (để tránh sửa code và test ở controller) thì lại vi phạm convention đặt ra từ đầu (repo xử lý table) gây hoang mang cho người đến sau :D
  • Nếu controller gọi service thì ở tầng controller nó chỉ quan tâm là cái service đấy nó cung cấp cho tao cái API đấy (bỏ input vào là ra expected output) còn nó làm mẹ gì ở dưới kệ nó, nó có gọi đến repo để lấy data trực tiếp từ db hay gọi đến 3rd party API kệ nó => nếu đổi cách lấy data (chẳng hạn) thì anh chỉ cần thay mẹ cái implementation mới (+test mới) cho thằng service đấy thôi không phải thay đổi code (hay test) ở tầng controller.

Cái này nó còn tuỳ thuộc vào cái độ phức tạp của project mà anh đang làm nữa nhé. Nếu như nó đã quá bé và cảm thấy tương lai không có chuyện thay đổi gì nữa thì thôi, cũng không nên cứng nhắc quá làm gì :)
 
Sửa lần cuối:
Làm start up thực ra mỗi thứ 1 tí. Devops,front end,backend thậm chí có cả bê máy chủ lên viettel idc để lắp đặt nữa cơ :D
Nói về php thì ông nào chê thì chê chứ t thấy vẫn ok, quan trọng là nó giải quyết đc bài toán thôi. Php hồi xưa thì lởm chứ version 7 có static type là scale ngon lành rồi
kek làm startup thì ai chả làm wholestack. cơ mà php muốn làm ngon thì cần kỷ luật khá cao, tôi thấy nể thì vào khen thôi có gì đâu.

web làm php đứng top thiếu gì, facebook, pornhub concurrent user tính bằng triệu nó còn dùng php...

// cơ mà được chọn thì tôi vẫn không chọn, có đầy thứ hay ho hơn :"> ví dụ như vụ structure này tôi dùng elixir chưa bao giờ phải đau đầu quá lâu, vì cost cho refactoring thấp tè.
 
Thì 1 ông cầm master thôi mà. Conflict (nếu có) cũng đâu có khó xử lí đâu. Mà tôi thấy merge 1 file đỡ đau đầu so với merge một đống file chứ

Ông dùng pull/merge request bao giờ chưa. Ông master chỉ review rồi merge vào thôi mà có phải fix gì đâu. Ông mà phải fix conflict là ông dev fix bug kia ấy chứ

Hờ tớ 10 năm exp, hiện đang lead team 7 người và quản lí 15 cái source base của 1 start up nhé. Bạn muốn chia sẻ kinh nghiệm gì với tớ cứ chia sẻ lên đây thôi :D Việc merge source code của member trong team một ngày t phải làm không dưới 10 lần đâu
Tại vì anh không bắt chia nhỏ file ra nên dev mới phải suốt ngày đi resolve conflicts thì có :cautious:
Anh phải nghĩ là "không nên để xảy ra việc conflict" (risk0 gần bằng 0) thay vì "xử lý việc conflict không khó" (risk1 > risk0) chứ :D
 
Sửa lần cuối:
Ý kiến của mình là nên làm như chủ xị. Tức là Controller gọi service. Ko build logic trong controller.
Lý do: Để unit test. Để reusable. Để dependency injection.

Cái thứ 2 là controller có được phép gọi thẳng repository ko? Câu trả lời là có và không.

Nếu repo có hàm cung cấp đúng dữ liệu cần thì ko cần qua service vì như vậy sẽ xảy ra function proxy ( function wrapper). Đó là lý thuyết (có) Nhưng cái này trong thực tế khó có trường hợp vậy (không)

Lý do: Repo thường là trả về full entity mà controller nó chỉ cần một phần trong đó thôi nên cần có service để bỏ bớt hoặc format lại dữ liệu. Cho nên thưc tế controller gọi thẳng repo là cực hiếm.
repo trả về full entity thì code bác chưa tối ưu rồi, muốn lấy gì select cái đó thôi chứ
 
Tại vì anh không chia nhỏ file ra nên mới phải suốt ngày đi resolve conflicts thì có :cautious:
Anh phải nghĩ là "không nên để xảy ra việc conflict" (risk0 gần bằng 0) thay vì "xử lý việc conflict không khó" (risk1 > risk0) chứ :D
Anh phải phân biệt đc merge source code và resolve conflict chứ. Merge source thì ông lead nào chả phải làm hàng ngày ;))
Mà ông đừng hiểu nhầm tôi ko chia nhỏ file
Cái tôi lấy chỉ là ví dụ của cái dự án to đùng mà cấu trúc của nó vẫn đơn giản 1 featured/file thôi. Quản cái git thì muốn ko conflict thì ông phải biết cách chia feature cho team.
Việc conflict là có nhưng giỏi lắm 1 tuần bị đôi lần chứ mấy. Mà nếu có bị thì tôi cũng đâu phải là thằng đi resolve đâu mà ông dev phải resolve rồi update lại cái mergen request. Việc của tôi đơn giản là lên gitlab review code rồi ấn nút merge thôi
Ps: mà thôi buồn ngủ vãi rồi. Anh em nào quote để mai nhé. G9
 
repo trả về full entity thì code bác chưa tối ưu rồi, muốn lấy gì select cái đó thôi chứ
Giờ ví dụ như vầy. UserRepo. GetUserById.

  • Case 1: Tôi cần thông tin sau khi oauth chỉ gồm name và email.
  • Case 2: Tôi cần thông tin cho Report cần name và personal id.
  • Case 3: Tôi cần thông tin cho Salary bao gồm name, personal id và salary.
  • Case N:...

Thế là tôi phải viết N cái function để cần gì lấy đó thôi à? Thế anh tối ưu cho tôi trong trường hợp này tôi nên làm thế nào?
 
Anh phải phân biệt đc merge source code và resolve conflict chứ. Merge source thì ông lead nào chả phải làm hàng ngày ;))
Xin lỗi tôi nói thiếu.
Tại vì anh không bắt chia nhỏ file ra nên dev mới phải suốt ngày đi resolve conflicts thì có
:cautious:

Anh phải nghĩ là "không nên để xảy ra việc conflict" (risk0 gần bằng 0) thay vì "xử lý việc conflict không khó" (risk1 > risk0) chứ
:D

Mà ông đừng hiểu nhầm tôi ko chia nhỏ file
Cái tôi lấy chỉ là ví dụ của cái dự án to đùng mà cấu trúc của nó vẫn đơn giản 1 featured/file thôi. Quản cái git thì muốn ko conflict thì ông phải biết cách chia feature cho team.
Anh không vứt toàn bộ feature vào 1file là tôi mừng cho dev của anh :D

Còn tôi phân tích dựa trên cái ví dụ của anh nhé. Anh cứ tưởng tượng là có N ông dev cùng làm 1 feature/1 file. Nếu dev1 có commit1 thêm func1 vào cuối file, dev2 commit2 func2 cũng cuối file,... devN commitN funcN cũng cuối file. Thế có phải là sẽ có N-1 lần resolve conflicts không?
:cautious:

Đấy chỉ là mới nói chuyện bị conflict có 1 chỗ đấy nhé. Còn nếu có tầm X chỗ conflicts (càng nhiều người làm cùng 1 file + commit sửa nhiều chỗ trong file thì X càng dễ lớn) thì ông dev nào non có mà nhoè mẹ mắt
:D
=> lại gọi lead hoặc tham khảo với team để resolve => tốn thời gian + risk
Nếu code scripting language mà không phải kiểu typesafe thì conflict lại càng đáng sợ
:(


Mà nếu có bị thì tôi cũng đâu phải là thằng đi resolve đâu mà ông dev phải resolve rồi update lại cái mergen request.
Resolve conflicts là việc của dev, nhưng take risk lại là việc của anh :D

=> tốt nhất là "không nên để xảy ra việc conflict" hoặc để X thật nhỏ bằng cách chia nhỏ file ra :D
 

Thống kê chủ đề

Ngày tạo
soledad86,
Người trả lời cuối
freedom.9,
Trả lời
217
Lượt xem
33.246
Quay lại
Lên đầu trang