thảo luận How to build a [good] Project/Code Structure (long post)

mấy ông Java / DotNet thấy cứ thích khổ dâm với đống architect / pattern / clean code nhỉ. Năm 2020 rồi, hãy dùng react/vue/angular để phía BE giản tiện lại. Giờ mà còn server-side rendering = JSP với Thymeleaf nữa

Vd như phía API quan tâm éo gì tới screen Login, screen Register, screen User List 1, screen User List 2.... BE cứ viết API "GET /api/users" rồi phía FE tự xử thôi.

Code duplicate là chuyện bình thường, thậm chí tui còn khuyến khích khi đang code 1 feature mới nữa. Để duplicated code đó, sau 1-2 sprint mới có đủ tầm nhìn mà refactor.
Cái này thím cũng đừng vội chụp mũ làm gì, việc server side rendering hay đẩy cho Client nó phụ thuộc vào yêu cầu ban đầu thôi.
Còn như ví dụ của bác là không đúng. 1 API get đó mà xử lý được cái đống màn hình của bác thì if nó phải tầm chục cái bác ạ :boss:
Tất nhiên giờ đơn giản nhất là cứ RESTful mà phang thôi, tiện cho FE cũng như mobile nữa, tuy nhiên OP đang thảo luận về việc kiến trúc project.
@OP.
Về phần kiến trúc project thì hiện tại của iem thì theo kiểu đơn thuần sau
Controller -> Service (Interface/Implementation) -> Repository (Sql/nosql package)
Những phần chung như AOP, Config, Exception Handling thì move ra package riêng
Trong các package lại chia theo domain riêng
Ví dụ
Controller -> user package -> User Controller, Profile Controller ...
Việc tách ntn cũng na ná với của thím vậy.
 
Thực ra cách cuối cùng của bác e đang thấy nó na ná như sử dụng định nghĩ team tự chủ trong quản lý bằng Agile, tức là bổ dọc để 1 team có đủ skill để done được mọi thứ trong dự án mà không cần phụ thuộc bố con thằng nào cả.
Em có một thắc mắc là: Em biết việc dùng OOP trong thiết kế khá ổn, tuy nhiên dùng nhiều thì những bạn mới hoặc những người kiến thức ko chắc có thể bị ngợp và khó tiếp cận. Vậy OOP như thế nào là đủ để vừa tối ưu vừa có thể dễ tiếp cận bác nhỉ
 
nếu project src code chia screen như bác, sẽ hợp lý với các bài toán đơn giản và những developer làm dự án từ đầu
Nếu gặp một bài toán phức tạp, dev ra dev vào thì tạm thời mình nghĩ sẽ gặp 2 vấn đề như sau:
1. Dev mới vào sẽ cần 1 thời gian đủ lâu để trải nghiệm code ở tất cả các screen mới có thể hiểu tổng quan về nghiệp vụ.
2. Chính vì các service bị duplicate lên thay vì dependence nên là 1 thay đổi là lại phải update ở các chỗ khác(cái này xảy ra thường xuyên, chắc bác có đối sách, hi vọng được chia sẻ)
 
nếu project src code chia screen như bác, sẽ hợp lý với các bài toán đơn giản và những developer làm dự án từ đầu
Nếu gặp một bài toán phức tạp, dev ra dev vào thì tạm thời mình nghĩ sẽ gặp 2 vấn đề như sau:
1. Dev mới vào sẽ cần 1 thời gian đủ lâu để trải nghiệm code ở tất cả các screen mới có thể hiểu tổng quan về nghiệp vụ.
2. Chính vì các service bị duplicate lên thay vì dependence nên là 1 thay đổi là lại phải update ở các chỗ khác(cái này xảy ra thường xuyên, chắc bác có đối sách, hi vọng được chia sẻ)

Mình xin trả lời từng ý một nhé.

1. Các project mà mình áp dụng mô hình [level 2] của mình cũng không bé lắm đâu, business logic cũng khá phức tạp đấy(bên mình làm Agile/Scrum, dev cho ra sản phẩm mất 6 tháng, maintain/update các thứ trong vòng 18 tháng tiếp theo, nếu nói team size bé thì đúng). Và việc người ra người vào trong vòng ngót 2 năm ấy cũng có(mất 1 anh Team Lead và 1 bạn Junior), nhưng project vẫn run ok.

2. Về việc dev có cảm thấy lạ lẫm với mô hình của mình? Chắc chắn rồi. Ban đầu, khi mình đưa ra mô hình của mình, PO bên kia còn cảm thấy không phù hợp, Team Lead và các devs cũng không đồng tình lắm với cách chia của mình. Mình đã conduct một buổi brainstorm meeting để trao đổi cụ thể về vấn đề này --> Cuối cùng mọi người đều chấp nhận run thử một thời gian.
Kết quả là Team Lead cực sướng vụ review,merge,resolve code các kiểu (gần như không có conflict), đội dev cũng sướng vì không phải đụng chạm lẫn nhau, chỉ có hỏi nhau mỗi cái path trong controller là ntn mà thôi. Devs bên mình cũng bình thường, không cao siêu lắm đâu nên mình nghĩ ai cũng có thể làm được, không cứ gì là dev xịn hay lởm.
Còn vụ nắm business logic cho từng màn hình thì tại sao phải trải nghiệm nhiều/hết các màn hình mới nắm tổng quan về nghiệp vụ được? Có 2/n người sẽ phải nắm điều ấy. Đầu tiên là thằng BA bên kia, tiếp theo là thằng PM như mình (mặc dù trong Agile/Scrum méo có role PM, nhưng thôi, vì nửa mùa nên chấp nhận), Team Lead cũng phải nắm được tương đối, cuối cùng mới tới thằng dev. Các dev đơn giản chỉ cần biết nghiệp vụ của màn hình là được, quan tâm gì tới của thằng khác? (Project của mình tương đối lớn, nếu bảo dev phải nắm nghiệp vụ gần hết thì hơi khó) Cách phân chia thì mình chia mỗi dev các màn hình "hơi hơi" liên quan đến nhau nên cũng khá tiện.

3. Cái vụ duplicate thì mình phải thừa nhận điều bạn nói là đúng. Business logic hôm nay thế này, mai thế khác, mỗi lần như thế là người design, tracking, review như mình tương đối khổ (Còn chơi quả Find/Replace All thì risk quá). Nhưng vì tính độc lập giữa các module nên mình chấp nhận điều đó (cái gì cũng có mặt không tốt của nó mà).
 
Thực ra cách cuối cùng của bác e đang thấy nó na ná như sử dụng định nghĩ team tự chủ trong quản lý bằng Agile, tức là bổ dọc để 1 team có đủ skill để done được mọi thứ trong dự án mà không cần phụ thuộc bố con thằng nào cả.
Em có một thắc mắc là: Em biết việc dùng OOP trong thiết kế khá ổn, tuy nhiên dùng nhiều thì những bạn mới hoặc những người kiến thức ko chắc có thể bị ngợp và khó tiếp cận. Vậy OOP như thế nào là đủ để vừa tối ưu vừa có thể dễ tiếp cận bác nhỉ
Cách chia bổ dọc tương đối phổ biến, không cứ phải Agile đâu. Thời mình làm ở FSOFT, làm theo mô hình waterfall hay prototype development cũng đều phân chia theo kiểu bổ dọc. Cách bổ dọc hay bổ ngang cũng là câu chuyện giữa đa dạng hoá và chuyên môn hoá. Một đằng thì phải biết hết, làm hết, còn một đằng thì chỉ cần làm đúng thứ mình giỏi là được.

Mình là PM, cái ưu tiên của mình bao giờ cũng phải là chất lượng dự án được đặt lên hàng đầu, tiếp theo là giá cả. Bài toán đặt ra là, bạn thuê 1 thằng giỏi back-end, 1 thằng giỏi front-end rồi kết hợp 2 thằng với nhau (lưỡng long nhất thể), hay là thuê 2 thằng full-stack hơn? Về mặt giá cả, dĩ nhiên phương án 1 tốn ít chi phí hơn chứ :D . Về mặt chất lượng, thì đúng là 1 nghề cho chín còn hơn chín nghề đấy (Bài học "của người khác" hơi bị đắt giá về cái này).

Còn vụ OOP thì thế này. Có 2 cái cần cân nhắc.
- Resource (cụ thể là chất lượng của dev):
Giả sử dự án toàn mấy bạn interns, có mỗi một/vài ông "cứng cứng" thì phải thiết kế + phân bố làm sao để mấy bạn ấy làm đúng, làm đủ là được (đúng nghĩa là làm như máy, không cần hiểu, chỉ cần làm đúng như design là tốt rồi). Thậm chí thiết kế theo kiểu tight-coupling, anti-pattern cũng không sao hết. Cần phải nhớ rằng deliver được product với đúng requirement của KH là ưu tiên số 1. Code đẹp, code hay để sau đi. (Chứ nguyên việc training cho mấy bạn interns hiểu cái này là cái gì, giải thích tại sao thì chắc dự án cháy luôn)
Còn nếu dev tầm tầm trung bình, có khả năng đọc hiểu được requirement, có thể "tự bay" được (thường thì mấy bạn interns sau tầm 2 dự án là đã ok rồi) thì cứ theo đúng OOP mà ốp thôi. Lúc này thì các bạn ấy sẽ phần nào hiểu thế nào là OOP, design pattern là gì,...Nếu không hiểu thì mình có thể giảng thêm. (Nhưng ngại nhất mấy bạn nửa vời, và cứng đầu. Biết mỗi thứ một tí, cuối cùng thành ra không biết gì)

- Tính chất của dự án:
Cái này thì hơi mông lung. Vì chẳng biết phải nói thế nào cho phù hợp. Ví dụ, mình làm 1 app C/C++ cho xe hơi --> Ốp OOP vào làm sao được? Hay làm UI = React/Angular mà không có TS thì design theo kiểu OOP thể nào cũng bị mấy ông dev cuồng FP chửi cho. Hoặc có những cái nó kiểu nửa vời thì ốp OOP vào nó cũng lỡ cỡ.

Mình biết gì thì chia sẻ nấy, có gì không đúng thì cứ cmt nhé! :)
 
Last edited:
Còn vụ nắm business logic cho từng màn hình thì tại sao phải trải nghiệm nhiều/hết các màn hình mới nắm tổng quan về nghiệp vụ được? Có 2/n người sẽ phải nắm điều ấy. Đầu tiên là thằng BA bên kia, tiếp theo là thằng PM như mình (mặc dù trong Agile/Scrum méo có role PM, nhưng thôi, vì nửa mùa nên chấp nhận), Team Lead cũng phải nắm được tương đối, cuối cùng mới tới thằng dev. Các dev đơn giản chỉ cần biết nghiệp vụ của màn hình là được, quan tâm gì tới của thằng khác? (Project của mình tương đối lớn, nếu bảo dev phải nắm nghiệp vụ gần hết thì hơi khó) Cách phân chia thì mình chia mỗi dev các màn hình "hơi hơi" liên quan đến nhau nên cũng khá tiện.
nghiệp vụ đc hiểu là nghiệp vụ ở cả code nữa. vd: khi nhận 1 feature mới, giả sử có tài liệu rõ ràng như làm outsource đi, thì cũng phải hiểu đc sẽ phải làm gì, như bác chia theo screen và dupplicate thì:
1. Dev sẽ phải tìm trong đống code của screen khác để reuse code (dupplicate code) (quan tâm đến màn hình của thằng khác).
2. Các feature đc reuse code thực chất có thể đã đc reuse khá nhiều lần (do điều 1), có nhiều version (do có thể mỗi lần dupplicate lại thêm thắt 1 ít 1 ít) nên tìm kiếm khó, và confuse
3. Có thể teamlead sẽ chỉ cho dev chỗ cần tìm để reuse nhưng như thế mất thêm effort, team mà lớn thì chắc teamlead sẽ chỉ có role là training mất.
=> Mình chắc chắn nều feature đơn giản, dev sẽ tự code, chứ k dupplicate code. feature phức tạp thì sẽ mất tg hơn nhiều lần.
Kết quả là Team Lead cực sướng vụ review,merge,resolve code các kiểu (gần như không có conflict), đội dev cũng sướng vì không phải đụng chạm lẫn nhau.
Mình nghĩ ntn, nếu đã chạy theo từng sprint + team size nhỏ, thì merge code, resolve code gần như ko phải vấn đề.
Nhưng vì tính độc lập giữa các module nên mình chấp nhận điều đó (cái gì cũng có mặt không tốt của nó mà)
Mình e rằng ở đây là low conhesion
 
1. Dev sẽ phải tìm trong đống code của screen khác để reuse code (dupplicate code) (quan tâm đến màn hình của thằng khác).
2. Các feature đc reuse code thực chất có thể đã đc reuse khá nhiều lần (do điều 1), có nhiều version (do có thể mỗi lần dupplicate lại thêm thắt 1 ít 1 ít) nên tìm kiếm khó, và confuse
3. Có thể teamlead sẽ chỉ cho dev chỗ cần tìm để reuse nhưng như thế mất thêm effort, team mà lớn thì chắc teamlead sẽ chỉ có role là training mất.
Cái này mình nhận xét là các giả định của bạn đang mang hơi nhiều tính cá nhân.

Kể cả từ thời mình còn làm dev (mô hình level 1 và 1+) thì việc code theo đúng design là điều bắt buộc. Việc tìm code của người khác để reuse là biểu hiện của sự lười biếng và thiếu suy nghĩ. Rất may trong team mình thì không có ai như vậy.

Hơn nữa, trong mô hình của mình (level 2 và 2+) thì đã phân chia rạch ròi từng screen, chỉ có liên quan đến nhau ở phần controller. Do vậy, nếu có thì mỗi màn hình đều dùng phần của nó (Service, Repo) thì đâu có liên quan gì tới việc khó tìm kiếm hay confuse?

Nếu tính một cách lý thuyết thì với mô hình của mình sẽ tốn thời gian hơn khi phát triển (Nguyên nhân do việc duplicate code. Nhưng trong thực tế thì ngược lại còn nhanh hơn so với cách thông thường đấy), nhưng lại lợi trong việc maintain (Việc update 1 screen sẽ đảm bảo được việc sẽ không ảnh hưởng tới các màn hình khác)
 
Việc tìm code của người khác để reuse là biểu hiện của sự lười biếng và thiếu suy nghĩ. Rất may trong team mình thì không có ai như vậy.
Thực sự em ko còn gì để nói khi nghe đc câu này.
rạch ròi từng screen, chỉ có liên quan đến nhau ở phần controller. Do vậy, nếu có thì mỗi màn hình đều dùng phần của nó (Service, Repo) thì đâu có liên quan gì tới việc khó tìm kiếm hay confuse
vậy thì mỗi screen của bác chắc khủng khiếp lắm. bao trùm 1 domain rồi.
Nếu tính một cách lý thuyết thì với mô hình của mình sẽ tốn thời gian hơn khi phát triển (Nguyên nhân do việc duplicate code. Nhưng trong thực tế thì ngược lại còn nhanh hơn so với cách thông thường đấy), nhưng lại lợi trong việc maintain
em nghĩ bác nên xem lại câu này, nó vừa tốn thời gian khi phát triển, và cũng tốn cả thời gian khi maintain (chẳng qua bác là người maintain nên thấy nó dễ, chứ bàn giao cho thằng khác nó lại chả kêu trời kêu đất)
 
mấy ông Java / DotNet thấy cứ thích khổ dâm với đống architect / pattern / clean code nhỉ. Năm 2020 rồi, hãy dùng react/vue/angular để phía BE giản tiện lại. Giờ mà còn server-side rendering = JSP với Thymeleaf nữa

Vd như phía API quan tâm éo gì tới screen Login, screen Register, screen User List 1, screen User List 2.... BE cứ viết API "GET /api/users" rồi phía FE tự xử thôi.

Code duplicate là chuyện bình thường, thậm chí tui còn khuyến khích khi đang code 1 feature mới nữa. Để duplicated code đó, sau 1-2 sprint mới có đủ tầm nhìn mà refactor.
SPA thì cũng vẫn phải tổ chức code structure thôi, nhất là thằng React, code đồng bùi nhùi nó vẫn chạy - có vẻ ngon lành :sneaky:
 
Thực sự em ko còn gì để nói khi nghe đc câu này.

vậy thì mỗi screen của bác chắc khủng khiếp lắm. bao trùm 1 domain rồi.

em nghĩ bác nên xem lại câu này, nó vừa tốn thời gian khi phát triển, và cũng tốn cả thời gian khi maintain (chẳng qua bác là người maintain nên thấy nó dễ, chứ bàn giao cho thằng khác nó lại chả kêu trời kêu đất)
Bạn đang hơi lái vấn đề về việc cá nhân rồi.
Ở đây chúng ta đang tranh luận về việc phân chia như thế thì code/maintain 1 feature (screen) dễ hay khó.
Luận điểm của bạn:
- Code/Maintain sẽ phải refer/reuse lại các screen/feature design cũ --> Nguyên nhân chính gây ra khó khăn.
Luận điểm của mình:
- Code/Maintain sẽ làm theo design, không cần phải refer/reuse lại các screen/feature cũ làm gì.

Còn việc bàn giao thì mình cũng đã bàn giao rồi (nhảy việc thôi mà), mình cũng mất một chút time để giải thích cho người mới và hiện tại bên đấy vẫn run smoothly chứ đâu có cái gì khó khăn đâu?

Mình ko thích blame ai cả. Nhưng việc bạn cứ đem các giả định mang tính cá nhân ra rồi công nhận nó đúng thì không hợp lý. Trong khi mình là người làm thực tế, và những cái bạn giả định hoàn toàn không xảy ra. Dĩ nhiên bạn có thể phản bác là lên mạng thì nói cái méo gì chẳng được? Nhưng mình cũng đã giải thích ở trên rồi, khi áp dụng mô hình của mình thì vẫn có những khó khăn và cũng có những nhược điểm của nó cả. Có gì thì mình nói lấy, không thêm không bớt. Mong bạn hiểu cho.
 
SPA thì cũng vẫn phải tổ chức code structure thôi, nhất là thằng React, code đồng bùi nhùi nó vẫn chạy - có vẻ ngon lành :sneaky:
Làm front-end = Angular còn đỡ một chút vì nó có khung sườn (framework) cả rồi, code đỡ hổ lốn hơn. Chứ làm = React thì mới thấy đúng kiểu mỗi người một phách, loạn hết cả lên.
 
mấy ông Java / DotNet thấy cứ thích khổ dâm với đống architect / pattern / clean code nhỉ. Năm 2020 rồi, hãy dùng react/vue/angular để phía BE giản tiện lại. Giờ mà còn server-side rendering = JSP với Thymeleaf nữa

Vd như phía API quan tâm éo gì tới screen Login, screen Register, screen User List 1, screen User List 2.... BE cứ viết API "GET /api/users" rồi phía FE tự xử thôi.

Code duplicate là chuyện bình thường, thậm chí tui còn khuyến khích khi đang code 1 feature mới nữa. Để duplicated code đó, sau 1-2 sprint mới có đủ tầm nhìn mà refactor.
"Code duplicate là chuyện bình thường, thậm chí tui còn khuyến khích khi đang code 1 feature mới nữa. Để duplicated code đó, sau 1-2 sprint mới có đủ tầm nhìn mà refactor." câu này hay nè, thà duplicated code còn hơn wrong abstraction
 
Thực ra cách cuối cùng của bác e đang thấy nó na ná như sử dụng định nghĩ team tự chủ trong quản lý bằng Agile, tức là bổ dọc để 1 team có đủ skill để done được mọi thứ trong dự án mà không cần phụ thuộc bố con thằng nào cả.
Em có một thắc mắc là: Em biết việc dùng OOP trong thiết kế khá ổn, tuy nhiên dùng nhiều thì những bạn mới hoặc những người kiến thức ko chắc có thể bị ngợp và khó tiếp cận. Vậy OOP như thế nào là đủ để vừa tối ưu vừa có thể dễ tiếp cận bác nhỉ
OOP thì khá là tốn chi phí, ngay cả người kinh nghiệm lâu năm sành sỏi tool IDE thì việc đọc và kiểu cũng khá là khó chứ chưa nói người thiếu kinh nghiệm. Cho nên viêc ứng dụng OOP thì còn phải coi lại chi phí nguồn lực dự án có đáp ứng ko.
 
Vd như phía API quan tâm éo gì tới screen Login, screen Register, screen User List 1, screen User List 2.... BE cứ viết API "GET /api/users" rồi phía FE tự xử thôi.
Tùy vào đầu API nữa.
Giả sử bạn có đầu API về get lương cho employee. Biz logic dưới back-end sẽ vô cùng phức tạp, cần tác động tới vài chục dữ liệu thì không tống cho FE được nhé. Vẫn phải phân lớp, cấu trúc cho hợp lý thì mới áp được biz logic vào.


3. Cái vụ duplicate thì mình phải thừa nhận điều bạn nói là đúng. Business logic hôm nay thế này, mai thế khác, mỗi lần như thế là người design, tracking, review như mình tương đối khổ (Còn chơi quả Find/Replace All thì risk quá). Nhưng vì tính độc lập giữa các module nên mình chấp nhận điều đó (cái gì cũng có mặt không tốt của nó mà).
Cũng như việc em trả lời bác ở trên. Nếu cái biz logic nó quá phức tạp mà lại bị dup ở nhiều nơi thì thực sự là khủng khiếp khi phải maintenace. Em đã từng dính một vài vụ biz logic liên quan tới tiền, ông cả ông dev, ông reviewer, ông lead đều không biết rằng code đó bị dup ở nhiều chỗ khác nhau.
Khi lên report số liệu sai từ lưa hết. Track-back và fix data mất gần 1 tuần chỉ vì hơn chục rows dữ liệu bị lệch.
Tất nhiên không thể có silver bullet. Với business của bác thì việc này chấp nhận được. Em chỉ note rằng sẽ có những business khác không thể chấp nhận được chuyện này.

Mình là PM, cái ưu tiên của mình bao giờ cũng phải là chất lượng dự án được đặt lên hàng đầu, tiếp theo là giá cả.
Như bác có nói, bác đưa ra thread này dưới góc độ là một PM nên đặt nặng các vấn đề về thời gian, kết quả nhiều hơn kỹ thuật (agile).
Những anh em khác thì đang bàn nhiều tới kỹ thuật và hiểu cái Title của thread (GOOD) dưới góc độ kỹ thuật hơn.
Khi đó nếu gọi cái structure này của bác là good về mặt kỹ thuật thì chưa chính xác. Đơn giản như câu hỏi của bác ở #8. Em cũng chưa hiểu rõ được cách bác phân chia các screen ra sao để tránh conflict hoặc giảm (tối đa) việc dup code?
 
Không có architecture nào tốt nhất cho mọi vấn đề. Tùy vào req cụ thể có kiến trúc phù hợp. Chấm hết.
 
Code duplication là điều tối kị trong khi code rồi. Project to quá thì sau này không có ai biết hết các chỗ cần phải sửa
Vấn đề này cũng khá khó, mình cùng từng dev một dự án khi mà khách hàng cũng chỉ có ideal chưa có kinh nghiệm làm bao giờ nên không có solution rõ ràng nhưng muốn go live sản phẩm trong thời gian ngắn. Lúc đầu ae trong team cũng viết các function reuse nhưng khi mà requirement nó thay đổi liên tục nay xây mai đập. Từ chỗ dùng chung thành d liên quan j nhau nữa lại chạy theo deadline không có thời gian mà refactor code nên clone code là nhanh nhất để kịp deadline đợi một ngày sẽ refector lại. Nhưng thực tế là khi nó to quá sau này d có effort mà refactor :stick:

via theNEXTvoz for iPhone
 
Ban đầu mình tưởng là 1 topic chia sẻ tri thức :v, đọc xong 2 trang mới biết là 1 bài chia sẻ mẹo chạy dự án outsource.
 
Vấn đề này cũng khá khó, mình cùng từng dev một dự án khi mà khách hàng cũng chỉ có ideal chưa có kinh nghiệm làm bao giờ nên không có solution rõ ràng nhưng muốn go live sản phẩm trong thời gian ngắn. Lúc đầu ae trong team cũng viết các function reuse nhưng khi mà requirement nó thay đổi liên tục nay xây mai đập. Từ chỗ dùng chung thành d liên quan j nhau nữa lại chạy theo deadline không có thời gian mà refactor code nên clone code là nhanh nhất để kịp deadline đợi một ngày sẽ refector lại. Nhưng thực tế là khi nó to quá sau này d có effort mà refactor :stick:

via theNEXTvoz for iPhone
Tất cả các dự án bảo sẽ refactor lại thì éo bh refactor cả :))
 
Back
Top