2.1.1 Xác lập miền (domain)
Miền của một ứng dụng là lĩnh vực mà nó đề cập đến — các ý tưởng và khái niệm ảnh hưởng đến cách hiểu về ứng dụng. Trong ứng dụng Taco Cloud, miền bao gồm các đối tượng như thiết kế taco, các nguyên liệu cấu thành nên thiết kế đó, khách hàng, và các đơn đặt taco được khách hàng gửi. Hình 2.2 minh họa các thực thể này và mối quan hệ giữa chúng.

Hình 2.2 Miền của Taco Cloud
Để bắt đầu, chúng ta sẽ tập trung vào các nguyên liệu taco. Trong miền của bạn, nguyên liệu taco là những đối tượng khá đơn giản. Mỗi nguyên liệu có một tên và một loại để có thể phân loại trực quan (protein, phô mai, nước sốt, v.v.). Mỗi nguyên liệu cũng có một ID giúp định danh dễ dàng và rõ ràng. Lớp Ingredient sau đây định nghĩa đối tượng miền mà bạn cần.
Liệt kê 2.1 Định nghĩa nguyên liệu taco
package tacos;
import lombok.Data;
@Data
public class Ingredient {
private final String id;
private final String name;
private final Type type;
public enum Type {
WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
}
}Như bạn thấy, đây là một lớp miền Java tiêu chuẩn, định nghĩa ba thuộc tính cần thiết để mô tả một nguyên liệu. Có lẽ điều đáng chú ý nhất về lớp Ingredient trong liệt kê 2.1 là nó dường như thiếu các phương thức getter và setter thông thường, chưa kể các phương thức tiện ích như equals(), hashCode(), toString() và các phương thức khác.
Bạn không thấy chúng trong liệt kê phần nào là để tiết kiệm không gian, nhưng quan trọng hơn là vì bạn đang sử dụng một thư viện tuyệt vời có tên là Lombok để tự động sinh ra các phương thức đó trong thời gian biên dịch, để chúng có sẵn khi chạy. Thực tế, annotation @Data ở cấp lớp được cung cấp bởi Lombok và yêu cầu Lombok sinh ra tất cả các phương thức còn thiếu, cũng như constructor nhận tất cả thuộc tính final làm đối số. Việc sử dụng Lombok giúp bạn giữ cho mã của Ingredient ngắn gọn và rõ ràng.
Lombok không phải là một thư viện của Spring, nhưng nó cực kỳ hữu ích đến mức tôi cảm thấy khó mà lập trình thiếu nó. Hơn nữa, nó rất cần thiết khi tôi cần giữ cho các ví dụ mã trong sách ngắn gọn và dễ hiểu.
Để sử dụng Lombok, bạn cần thêm nó như một phụ thuộc (dependency) vào dự án của bạn. Nếu bạn đang dùng Spring Tool Suite, chỉ cần nhấp chuột phải vào tệp pom.xml và chọn Add Starters từ menu ngữ cảnh của Spring. Danh sách các phụ thuộc như trong chương 1 (hình 1.4) sẽ xuất hiện, cho phép bạn thêm hoặc thay đổi các phụ thuộc đã chọn. Tìm Lombok trong mục Developer Tools, đảm bảo đã chọn nó và nhấn OK; Spring Tool Suite sẽ tự động thêm nó vào tệp cấu hình build của bạn.
Ngoài ra, bạn cũng có thể thêm Lombok thủ công vào tệp pom.xml như sau:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>Nếu bạn quyết định thêm Lombok thủ công vào cấu hình build, bạn cũng nên loại bỏ nó khỏi plugin Spring Boot Maven trong phần <build> của pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>Phép thuật của Lombok được áp dụng trong thời gian biên dịch, nên không cần nó trong thời gian chạy. Việc loại bỏ như vậy giúp tránh đưa Lombok vào tệp JAR hoặc WAR cuối cùng.
Phụ thuộc Lombok cung cấp cho bạn các annotation Lombok (như @Data) trong thời gian phát triển, và tự động sinh phương thức trong thời gian biên dịch. Nhưng bạn cũng cần cài đặt Lombok như một phần mở rộng trong IDE, nếu không IDE sẽ báo lỗi vì thiếu phương thức và các thuộc tính final chưa được gán. Truy cập https://projectlombok.org/ để xem hướng dẫn cài đặt Lombok trong IDE bạn sử dụng.
Tại sao mã của tôi lại có quá nhiều lỗi?
Xin nhắc lại rằng khi sử dụng Lombok, bạn phải cài đặt plugin Lombok trong IDE. Nếu không, IDE sẽ không biết rằng Lombok đang cung cấp các phương thức getter, setter và các phương thức khác, và sẽ báo lỗi vì thiếu chúng.
Lombok được hỗ trợ trong nhiều IDE phổ biến, bao gồm Eclipse, Spring Tool Suite, IntelliJ IDEA và Visual Studio Code. Truy cập https://projectlombok.org/ để biết thêm thông tin về cách cài đặt plugin Lombok trong IDE của bạn.
Tôi nghĩ bạn sẽ thấy Lombok rất hữu ích, nhưng hãy nhớ rằng nó là tùy chọn. Bạn không bắt buộc phải dùng nó để phát triển ứng dụng Spring, nên nếu bạn không muốn sử dụng, cứ thoải mái viết tay các phương thức còn thiếu. Cứ làm đi … tôi sẽ chờ.
Nguyên liệu là các thành phần cốt lõi của một chiếc taco. Để mô tả cách các nguyên liệu được kết hợp lại, chúng ta sẽ định nghĩa lớp miền Taco như sau.
Liệt kê 2.2 Đối tượng miền định nghĩa thiết kế taco
package tacos;
import java.util.List;
import lombok.Data;
@Data
public class Taco {
private String name;
private List<Ingredient> ingredients;
}Như bạn thấy, Taco là một đối tượng miền Java đơn giản với vài thuộc tính. Giống như Ingredient, lớp Taco cũng được đánh dấu với annotation @Data để Lombok tự động sinh ra các phương thức JavaBean cần thiết trong thời gian biên dịch.
Giờ đây chúng ta đã định nghĩa xong Ingredient và Taco, chúng ta cần thêm một lớp miền nữa để mô tả cách khách hàng chọn các loại taco họ muốn đặt, cùng với thông tin thanh toán và giao hàng. Đó là nhiệm vụ của lớp TacoOrder, được trình bày bên dưới.
Liệt kê 2.3 Đối tượng miền cho các đơn đặt taco
package tacos;
import java.util.List;
import java.util.ArrayList;
import lombok.Data;
@Data
public class TacoOrder {
private String deliveryName;
private String deliveryStreet;
private String deliveryCity;
private String deliveryState;
private String deliveryZip;
private String ccNumber;
private String ccExpiration;
private String ccCVV;
private List<Taco> tacos = new ArrayList<>();
public void addTaco(Taco taco) {
this.tacos.add(taco);
}
}Ngoài việc có nhiều thuộc tính hơn Ingredient hay Taco, không có điều gì quá mới để thảo luận về TacoOrder. Đây là một lớp miền đơn giản với chín thuộc tính: năm thuộc tính cho thông tin giao hàng, ba thuộc tính cho thông tin thanh toán, và một thuộc tính là danh sách các đối tượng Taco tạo nên đơn hàng. Ngoài ra còn có phương thức addTaco() được thêm vào để thuận tiện khi thêm taco vào đơn hàng.
Giờ đây các kiểu miền đã được định nghĩa xong, chúng ta đã sẵn sàng để sử dụng chúng. Hãy thêm một vài controller để xử lý các yêu cầu web trong ứng dụng.
