Giới thiệu về Clean Architecture – Phần 2

Trong bài viết trước, mình đã giới thiệu với các bạn những ý tưởng cơ bản của Clean Architecture. Trong bài viết này, mình sẽ đi vào chi tiết cách hiện thực Clean Architecture với một ứng dụng Java sẽ như thế nào, các bạn nhé!

Để các bạn dễ hiểu, mình sẽ lấy ví dụ ứng dụng quản lý sinh viên được đề cập trong phần 1 để viết theo Clean Architecture như sau:

Giới thiệu về Clean Architecture

Đây là Maven project với nhiều module các bạn nhé!


Module entities

Các bạn có thể thấy, chúng ta có module entities để định nghĩa thông tin sinh viên:

Giới thiệu về Clean Architecture

Để đơn giản, mình chỉ định nghĩa 2 thông tin cơ bản của sinh viên trong class Student như sau:

Và trong tập tin pom.xml của module này, mình không declare bất kỳ một library hay framework nào cả.



Module use-cases

Module use-cases thì để đơn giản, mình chỉ định nghĩa một use case duy nhất là tìm kiếm thông tin sinh viên bằng tên:

Giới thiệu về Clean Architecture

Ở đây, như các bạn thấy, mình có định nghĩa thêm một package là adapter. Trong idea của Clean Architecture thì lớp adapter sẽ nằm bên ngoài lớp use-cases nhưng ở đây, chúng ta có thể gộp lớp adapter này nằm trong module use-cases cũng được, không cần phải thêm một module adapter để định nghĩa các interface, không cần thiết lắm. Nhưng nếu các bạn muốn follow chặt chẽ idea của Clean Architecture thì có thể introduce thêm module adapter nữa cũng được.

StudentAdapter có nội dung như sau:

Nội dung của tập tin pom.xml trong module use-cases, mình cũng không có một library, framework nào cả, ngoài dependency của module entities:



Module db

Chúng ta sẽ hiện thực phần lấy thông tin sinh viên trong module db.

Giới thiệu về Clean Architecture

Ở đây, mình sẽ sử dụng spring-data-jpa để làm nhiệm vụ thao tác với database nha các bạn!

Như các bạn thấy, mình cũng khai báo thêm Hibernate dependency cho phần implementation của JPA và thư viện Lombok để việc định nghĩa các entity đơn giản hơn!

StudentModel có nội dung như sau:

StudentRepository có nội dung như sau:

Như các bạn thấy ở đây, mình định nghĩa một query method cho phép chúng ta có thể lấy thông tin sinh viên từ tên của sinh viên đó.

Và bây giờ chúng ta có thể implement StudentAdapter trong module db như sau:

Ở đây, như các bạn thấy, mình có thêm một class là StudentMapper để convert data từ database sang entity và sau đó, nếu entity này được sử dụng ở đâu đó, ví dụ như module rest, chúng ta sẽ có một class Mapper khác để convert từ entity sang dto của rest để trả về cho người dùng.

Việc sử dụng class Mapper này sẽ giúp chúng ta giảm sự phụ thuộc giữa các module với nhau, chúng ta có thể dễ dàng thêm mới hoặc loại bỏ bớt module mà chúng ta sẽ dùng cho ứng dụng, với ít sự thay đổi code nhất.


Module rest

Sau khi đã lấy được data từ database, bây giờ là lúc chúng ta hiện thực module rest, đảm nhận vai trò expose API cho người dùng sử dụng.

Giới thiệu về Clean Architecture

Tập tin pom.xml của module rest có nội dung như sau:

Mình sử dụng spring-web dependency để định nghĩa các RESTful API, use-cases dependency để gọi tới các use cases của ứng dung và thư viện lombok chỉ để đơn giản cho việc định nghĩa các dto.

StudentDto có nội dung như sau:

StudentMapper có nội dung như sau:

Và class StudentController expose API lấy thông tin sinh viên bằng tên có nội dung như sau:

Ở đây, mình đang autowired FindStudentByNameUseCase là do mình đang tận dụng benifit của ứng dụng này với Spring framework, chúng ta sẽ định nghĩa các use cases trong Spring container. Nếu ứng dụng của các bạn sử dụng những framework khác thì việc sử dụng use cases sẽ phụ thuộc vào các framework đó.


Module configuration

Như mình nói, để ứng dụng có thể chạy được, chúng ta cần có module configuration.

Giới thiệu về Clean Architecture

Mình đang sử dụng Spring Boot để chạy ứng dụng:

và định nghĩa use case FindStudentByNameUseCase trong class UseCaseConfiguration:

Nội dung tập tin pom.xml của module configuration sẽ như sau:

Nếu các bạn để ý, mình đã định nghĩa các module rest và db generic nhất có thể, và việc cấu hình ứng dụng trong module configuration sẽ quyết định ứng dụng của chúng ta chạy như thế nào! Ví dụ ở đây, mình đang sử dụng MySQL để chạy ứng dụng, sau này nếu mình muốn chuyển sang một database system khác như PostgreSQL chẳng hạn, việc mình cần làm là chỉ cần thay đổi ở module configuration này mà thôi, …

Tập tin pom.xml của parent project có nội dung như sau:

Đến đây thì chúng ta đã hoàn thành ứng dụng ví dụ của mình.

Giả sử mình có table student và data được tạo trong database server MySQL như sau:

thì khi chạy ứng dụng và request tới http://localhost:9090/student/find?name=Khanh, các bạn sẽ thấy kết quả như sau:
Giới thiệu về Clean Architecture

Add Comment