Hãy xem xét các tùy chọn, nơi chúng ta có thể đặt mã xác thực:
- Bên trong các setters trong xây dựng.
- Bên trong
build()
phương pháp.
- Bên trong thực thể được xây dựng: nó sẽ được gọi trong
build()
phương thức khi thực thể được tạo.
Tùy chọn 1 cho phép chúng tôi phát hiện các vấn đề sớm hơn, nhưng có thể có các trường hợp phức tạp khi chúng tôi có thể xác thực đầu vào chỉ có bối cảnh đầy đủ, do đó, thực hiện ít nhất một phần xác thực trong build()
phương thức. Do đó, việc chọn tùy chọn 1 sẽ dẫn đến mã không nhất quán với một phần xác thực được thực hiện ở một nơi và một phần khác được thực hiện ở nơi khác.
Tùy chọn 2 không tệ hơn đáng kể so với tùy chọn 1, bởi vì, thông thường, setters trong trình xây dựng được gọi ngay trước khi build()
, đặc biệt, trong các giao diện trôi chảy. Vì vậy, vẫn có thể phát hiện sớm một vấn đề đủ sớm trong hầu hết các trường hợp. Tuy nhiên, nếu trình xây dựng không phải là cách duy nhất để tạo một đối tượng, nó sẽ dẫn đến sự trùng lặp mã xác thực, bởi vì bạn sẽ cần phải có nó ở mọi nơi mà bạn tạo một đối tượng. Giải pháp hợp lý nhất trong trường hợp này sẽ là đặt xác nhận càng gần đối tượng được tạo càng tốt, nghĩa là bên trong nó. Và đây là tùy chọn 3 .
Từ quan điểm RẮN, việc xác thực trong trình xây dựng cũng vi phạm SRP: lớp trình xây dựng đã có trách nhiệm tổng hợp dữ liệu để xây dựng một đối tượng. Xác nhận là thiết lập hợp đồng trên trạng thái nội bộ của chính nó, trách nhiệm mới là kiểm tra trạng thái của một đối tượng khác.
Do đó, theo quan điểm của tôi, không chỉ tốt hơn là thất bại muộn từ quan điểm thiết kế, mà còn tốt hơn là thất bại bên trong thực thể được xây dựng, thay vì trong chính người xây dựng.
CẬP NHẬT: nhận xét này nhắc nhở tôi về một khả năng nữa, khi xác nhận bên trong trình xây dựng (tùy chọn 1 hoặc 2) có ý nghĩa. Sẽ có ý nghĩa nếu người xây dựng có hợp đồng riêng của mình trên các đối tượng mà nó đang tạo. Ví dụ: giả sử rằng chúng ta có một trình xây dựng xây dựng một chuỗi với nội dung cụ thể, giả sử, danh sách các phạm vi số 1-2,3-4,5-6
. Trình xây dựng này có thể có một phương thức như thế nào addRange(int min, int max)
. Chuỗi kết quả không biết gì về những con số này, cũng không cần phải biết. Trình xây dựng tự xác định định dạng của chuỗi và các ràng buộc trên các số. Do đó, phương thức addRange(int,int)
phải xác thực các số đầu vào và đưa ra một ngoại lệ nếu max nhỏ hơn min.
Điều đó nói rằng, quy tắc chung sẽ chỉ xác nhận các hợp đồng được xác định bởi chính người xây dựng.