Bất cứ khi nào tôi có thể, tôi cố gắng hạn chế giao tiếp giữa các đối tượng theo mô hình yêu cầu và trả lời. Có một thứ tự ngụ ý một phần trên các đối tượng trong chương trình của tôi sao cho giữa hai đối tượng A và B bất kỳ, có thể có cách để A gọi trực tiếp hoặc gián tiếp một phương thức của B hoặc để B gọi trực tiếp hoặc gián tiếp một phương thức của A , nhưng A và B không bao giờ có thể gọi phương thức của nhau. Đôi khi, tất nhiên, bạn muốn có giao tiếp ngược với người gọi phương thức. Có một vài cách tôi thích để làm điều này, và cả hai đều không phải là cuộc gọi lại.
Một cách là bao gồm nhiều thông tin hơn trong giá trị trả về của lệnh gọi phương thức, có nghĩa là mã máy khách sẽ quyết định phải làm gì với nó sau khi thủ tục trả lại quyền điều khiển cho nó.
Một cách khác là gọi một đối tượng con chung. Nghĩa là, nếu A gọi một phương thức trên B và B cần truyền đạt một số thông tin cho A, B gọi một phương thức trên C, trong đó A và B đều có thể gọi C, nhưng C không thể gọi A hoặc B. Đối tượng A sẽ là chịu trách nhiệm nhận thông tin từ C sau khi B trả lại quyền kiểm soát cho A. Lưu ý rằng điều này thực sự không khác biệt cơ bản so với cách đầu tiên tôi đề xuất. Đối tượng A vẫn chỉ có thể truy xuất thông tin từ giá trị trả về; không có phương thức nào của đối tượng A được gọi bởi B hoặc C. Một biến thể của thủ thuật này là truyền C làm tham số cho phương thức, nhưng các hạn chế về mối quan hệ của C với A và B vẫn được áp dụng.
Bây giờ, câu hỏi quan trọng là tại sao tôi khăng khăng làm mọi thứ theo cách này. Có ba lý do chính:
- Nó giữ cho các đối tượng của tôi liên kết lỏng lẻo hơn. Các đối tượng của tôi có thể gói gọn các đối tượng khác, nhưng chúng sẽ không bao giờ phụ thuộc vào ngữ cảnh của người gọi và bối cảnh sẽ không bao giờ phụ thuộc vào các đối tượng được đóng gói.
- Nó giữ cho dòng điều khiển của tôi dễ dàng lý do về. Thật tuyệt khi có thể giả định rằng mã duy nhất có thể thay đổi trạng thái bên
self
trong trong khi một phương thức thực thi là một phương thức và không có phương thức nào khác. Đây là cùng một loại lý luận có thể khiến người ta đặt các trường hợp đột biến lên các đối tượng đồng thời.
- Nó bảo vệ bất biến trên dữ liệu được đóng gói của các đối tượng của tôi. Các phương thức công khai được phép phụ thuộc vào các bất biến và các bất biến đó có thể bị vi phạm nếu một phương thức có thể được gọi bên ngoài trong khi phương thức khác đang thực thi.
Tôi không chống lại tất cả các sử dụng của cuộc gọi lại. Để tuân thủ chính sách của tôi về việc không bao giờ "gọi người gọi", nếu một đối tượng A gọi một phương thức trên B và chuyển một cuộc gọi lại cho nó, cuộc gọi lại có thể không thay đổi trạng thái bên trong của A và bao gồm các đối tượng được bao bọc bởi A và các đối tượng trong bối cảnh của A. Nói cách khác, cuộc gọi lại chỉ có thể gọi các phương thức trên các đối tượng được cung cấp cho nó bởi B. Cuộc gọi lại, thực tế, nằm trong cùng các hạn chế mà B là.
Một kết thúc lỏng lẻo cuối cùng để gắn kết là tôi sẽ cho phép gọi bất kỳ chức năng thuần túy nào, bất kể thứ tự từng phần này mà tôi đã nói đến. Các hàm thuần túy khác một chút so với các phương thức ở chỗ chúng không thể thay đổi hoặc phụ thuộc vào trạng thái có thể thay đổi hoặc tác dụng phụ, do đó không phải lo lắng về các vấn đề khó hiểu.