Ứng dụng thiết kế Clean Architecture trong ứng dụng Frontend.
Image for post
Minh họa quy tắc phụ thuộc cho ứng dụng FE

1. Mở đầu:

Trong bài viết trước, Mình có nói tới những phức tạp khác nhau có thể xảy ra nếu chúng ta không cẩn thận trong việc tách logic nghiệp vụ của ứng dụng khỏi giao diện người dùng. Nhưng cũng chỉ mới dừng lại ở lý thuyết. Và lần này, mình muốn đi xa hơn một bước đó là viết một serial bài về việc ứng dụng vào thực tiễn.
Như tiêu đề của bài viết, chúng ta sẽ tập trung vào Vue để triển khai kiến trúc vào thực tiễn. Mình hi vọng sẽ có thêm thời gian và viết một bài hướng dẫn cho React. Nhưng vì Vue và React sử dụng những ý tưởng cốt lõi giống nhau, nên mình mong các nhà phát triển đi theo React đọc bài này sẽ thấy hữu ích.

2. Thoả thuận:

Image for post
Photo by Cytonn Photography on Unsplash
Phát triển giao diện người dùng, giống như bất kỳ hoạt động thực hành nào khác của con người, có nhiều cách tiếp cận theo hướng kỹ thuật, thậm trí theo sở thích chủ quan. Trước khi chúng ta bắt đầu, mình muốn cung cấp một vài chú giải rõ ràng về các phương pháp và kỹ thuật mình chọn để ứng dụng trong bài viết này. Bạn có quyền không đồng ý và thích cách khác hơn, nhưng mình sẽ dành một vài đoạn để giải thích lý do của mình.

Xây dựng một ứng dụng theo chuẩn Enterprise:

Các ý tưởng và cách tiếp cận kiến trúc mà mình sắp thảo luận hầu hết đều có thể áp dụng cho các ứng dụng cấp Enterprise. Những điều đó được thể hiện theo những ý sau:
A. Những sự phức tạp trong ứng dụng.
B. Được xây dựng và hỗ trợ bởi một nhóm các nhà phát triển.
C. Ứng dụng xây dựng và phát triển trong thời gian một vài năm, tính độc lập và thích nghi trước những thay đổi của thế giới frontend cũng như dễ dàng bảo trì mã nguồn.
D. Ứng dụng web: không phải là một trang web đơn thuần, nơi gần như toàn bộ logic nghiệp vụ tồn tại ở phía Backend. Nó cũng không phải là một thư viện giao diện, được cho là không bao hàm bất kì business logic nào. Mình tin rằng đối với những trường hợp này, sử dụng một cách tiếp cận khác sẽ tốt hơn.

TDD - Test Driven Development:

Mình tin chắc rằng TDD cung cấp rất nhiều giá trị cho việc cải thiện chất lượng mã nguồn. Thật không may, hầu hết các hướng dẫn mình xem đều không ứng dụng nó (trừ khi những hướng dẫn này tập trung vào TDD). Trong bài viết này, mình sẽ sử dụng cách tiếp cận theo hướng thử nghiệm: trước tiên chúng ta sẽ nghĩ về các thử nghiệm của chức năng cụ thể và sau đó sẽ áp dụng vào việc viết mã hiện thực nó.

3. Điều kiện:

Image for post
Photo by Sharon McCutcheon on Unsplash
Trước khi bắt đầu, hãy đảm bảo rằng bạn quen thuộc với các công cụ sau đây:
Hiểu rõ về kiến trúc component nói chung và ứng dụng cụ thể nó trong Vue:
1. Component là gì và ứng dụng nó trong UI
2. Cú pháp cơ bản của Vue
3. Hiểu về "state"
4. Hiểu vể "render" và "lifecircle" của ứng dụng
Hiểu về VueX:
1. Đã quen với flux pattern
2.  Hiểu về "actions" - "mutations" và "Store"
3. Hiểu và ứng dụng VueX vào Vue
OOP - Lập trình hướng đối tượng:
Là một điều kiện quan trọng để đi đường dài đó chính là OOP và các nguyên tắc cơ bản trong thiết kế phần mềm như SOLID, design pattern, phân tách các mối quan tâm...Nếu bạn tin rằng JS chỉ hỗ trợ lập trình hàm - FP hoặc "OOP chỉ dành cho những nhà phát triển Java" thì bài viết này sẽ khiến bạn thất vọng :))

4. Công cụ:

 
Image for post
Photo by Jo Szczepanska on Unsplash
Ngoài Vue/VueX có một số mục trọng công cụ mà mình sẽ ứng dụng trong bài viết này:
1. TypeScript: Chúng ta sắp bắt đầu một ứng dụng chuẩn Enterprise. Nhiều nhà phát triển sẽ hỗ trợ hoặc thay thế các dự án cũ đang chạy JS sang TS trong vài năm tới đây. Việc kiểm tra kiểu nghiêm ngặt chính là điểm mạnh và giúp cho chi phí bảo trì mã nguồn giảm xuống đáng kể về lâu dài. Mình sẽ không cố gắng thuyết phục ai sử dụng nó nhưng may thay đã có hàng trăm bài viết về chủ đề này.
2. JSX: Cú pháp trong Vue đương nhiên sẽ tự nhiên và gần với HTML hơn nhưng có một lợi ích đáng ngặc nhiên là JSX hỗ trợ việc check kiểu nghiêm ngặt. Gần đây có một bài mình viết về lý do tại sao điều này lại quan trọng và cách bạn có thể sử dụng nó.
3. Jest: Chúng ta sẽ sử dụng Jest để viết kiểm thử đơn vị kết hợp với thư viện Vue-test-utils.
4. Vuetify: thư viện UI cho Vue.

5. Tổng quan dự án:

Image for post
Photo by Craig Cameron on Unsplash
Dự án này sẽ là một phiên bản thu nhỏ, một bản mock cho một ứng dụng Enterprise điển hình. Việc sử dụng Blog như một dự án demo khá là phổ biến và chúng ta sẽ tiếp nối truyền thống này =))
Blog của chúng ta đương nhiên sẽ có tính năng hiển thị các bài post và cho người dùng để lại comment trong bài viết. Vì nó là phiên bản demo nên sẽ chỉ có 2 trang là Home và Artical, trang Home hiển thị ra các bài viết còn trang Artical sẽ là đại diện cho một bài post hoàn chỉnh và kèm phần comment cho user.
Bản demo được triển khai trên dịch vụ Heroku.

6. Mã Nguồn:

Talk are cheap, show me the code - Linus Torvalds

Đồng ý hai tay hai chân, nếu bạn không muốn dành thời gian để đọc hết bài viết thì có thể đọc mã nguồn tại đây.

7. Hướng dẫn sử dụng mã nguồn:

Repo gồm một vài branch, mỗi branch chứa một phần mã nguồn trong mỗi chương của serial bài hướng dẫn. Bạn có thể switch từ các branch khác nhau để xem cách mà mã nguồn tăng lên từ từ theo thời gian phát triển tính năng. Qua mỗi phần hướng dẫn, mình sẽ hỗ trợ bạn liên kết với các branch trong mỗi section để có thể follow được theo từng bước nhỏ.
Chúng ta sẽ phân tích các yêu cầu mà chúng ta phải đáp ứng trong chương này. Sau đó, chúng ta sẽ viết một vài thử nghiệm follow theo yêu cầu và tạo mã nguồn thực thi thực tế. Và cuối cùng, chúng ta sẽ kết thúc với nhiều phần thử nghiệm hơn hoặc sẽ sửa lại các thử nghiệm trước nểu cảm thấy cần thiết và việc sử dụng TDD sẽ giúp chúng ta đảm bảo chất lượng - kết quả của mã nguồn không thay đổi.
Đầu tiên, lấy code từ repo nếu bạn chưa có nó. Sau đó switch sang branch có tên "init". Nó sẽ đặt repo vào trạng thái ban đầu, với cấu trúc project trống. Đầu tiên chúng ta hãy xem cách cấu trúc directory trước.
* "entities", "services" và "store" sẽ giữ các thành phần tương ứng của ứng dụng; nhưng hiện tại chúng được để rỗng chưa chứa bất kì file nào.
* "ui" directory bao gồm những thứ thường được đẩy trực tiếp vào src directory: Vue components, router pages ( hoặc views), và Vue plugins. Chúng ta biết rằng giao diện người dùng không quá quan trọng, vì vậy bản cảm thấy đúng khi đặt chúng trong một thư mục con chuyên dụng.
Base của project được xây từ vue-cli. Nếu kiểm tra file package.json chúng ta sẽ thấy câu lệnh quen thuộc "vue-cli-service serve".
Để chạy dev server, đơn giản chỉ cần gọi lệnh "npm run serve" hoặc "yarn serve". Để chạy lệnh kiểm thử "npm t" nếu kèm theo chế độ watch ta gọi lệnh "npm run test:watch".
Xin lưu ý rằng mình sử dụng các quy tắc ESLint khá chặt cho TS. Mìnhthực thi kiểu trả về hàm rõ ràng (ngoại trừ các biểu thức và Hàm có thứ tự cao hơn), tiền tố “I” cho các interface.  Mìnhcũng cấm các biến không được sử dụng và các hàm tạo vô dụng, dấu chấm phẩy và dấu ngoặc kép.  Đó là khuyến nghị cá nhân (một phần chủ quan) của mình. Nên bạn có thể cấu hình khác đi theo ý bạn hoặc sử dụng nó.
Chúc may mắn!

8. Kiến trúc:

Image for post
Trong bài viết trước, mình đã dành thời gian khá nhiều để nói về Clean Architecture trong fronend app. Bob Martin, trong bài viết của ông đã đưa ra một minh hoạ tuyệt vời. Mình đã minh hoạ lại chúng và áp dụng hình vẽ trên vào project này.
Bức hình trên đại diện cho luật "Dependency": các vòng trong không biết gì về các vòng bên ngoài.
Như chúng ta có thể thấy, ở trung tâm của hình vẽ của ứng dụng chính là "Entities". Đó là các quy tắc cốt lõi của Business. Chúng chứa logic quý giá nhất và quan trọng nhất đói với ứng dụng - các đối tượng thuần tuý không có phụ thuộc.
Vòng tròn tiếp theo đại diện cho "Services". Bạn có thể coi chúng như các trường hợp sử dụng cho một thực thể cụ thể. Đó là nơi mà chúng ta tìm nạp và thao tác với chúng. Các service tuân theo quy tắc "dependency" và chỉ phụ thuộc vào các Entity.
Và cuối cùng, một loạt các chi tiết: không quan trọng, những thứ bổ sung như UI, DB (hoặc store), frameworks, etc. Chúng phụ thuộc vào Services và Entities cũng như nhau (ví dụ: components, instance, thành phần phụ thuộc vào store).

Các phần khác của serial:

Part 4: VueX
Part 5: UI - Pages và Components