Buổi design bắt đầu bằng một hình chữ nhật nhỏ trên whiteboard. Bên trong đó, một người vẽ ranh giới giữa hai phần của hệ thống. Code phía sau boundary đó vẫn còn rối. Database table có thể sẽ đổi. Tên product cũng chưa chắc đã giữ nguyên. Nhưng cả team cứ quay lại một câu hỏi: phần này nên hứa điều gì với phần còn lại của codebase?
Đó là giá trị thầm lặng của một interface tốt. Nó cho codebase một câu nói ổn định trong khi implementation bên dưới vẫn học thêm. Storage chuyển từ table này sang table khác. Provider bị thay thế. Một shortcut performance được gỡ bỏ. Một nhánh tạm trở thành workflow đúng nghĩa. Nếu mọi caller đều phụ thuộc vào hình dạng bên trong, mỗi lần đổi sẽ thành cuộc thương lượng với cả hệ thống. Nếu caller phụ thuộc vào một lời hứa rõ, phần bên trong có thể cải thiện mà không kéo mọi hàng xóm vào.
Điều này không có nghĩa interface nên được nghĩ ra trong phòng kín. Những boundary hữu ích nhất thường đến từ việc quan sát thay đổi thật. Behavior nào cứ xuất hiện trong planning? Rule nào mọi người phải giải thích lại nhiều lần? Detail nào cứ rò rỉ sang screen, job, và test vốn không nên quan tâm? Những chỗ rò đó thường là chất liệu design tốt hơn một sơ đồ architecture trắng tinh.
Một interface bền cũng không nhất thiết phải lớn. Đôi khi contract tốt nhất rất nhỏ vì nó gọi tên một việc rõ ràng. Đôi khi nó cần mang thêm context một chút, vì giấu context đó sẽ làm caller phải đoán. Câu hỏi không phải interface có minimal theo nghĩa trừu tượng hay không. Câu hỏi là nó có bảo vệ caller khỏi những detail dễ thay đổi, đồng thời vẫn làm behavior quan trọng visible hay không.
Test giúp team giữ lời hứa này trung thực. Test quanh interface không chỉ chứng minh implementation hiện tại chạy được. Nó nên mô tả behavior mà implementation tương lai phải giữ. Khi test nói bằng ngôn ngữ product thay vì ngôn ngữ storage, team có một guardrail nhỏ để tránh vô tình rewrite ý nghĩa.
Ở đây cũng có phần con người. Một interface ổn định giảm lượng lịch sử mà teammate phải nhớ trước khi sửa an toàn. Họ không cần biết mọi lý do implementation đầu tiên trông như vậy. Họ cần biết boundary hứa gì, không hứa gì, và example nào cho thấy edge case. Loại clarity đó là món quà cho người tham gia sau.
Phần khó là chấp nhận interface là trách nhiệm, không phải trang trí. Một khi các phần khác tin nó, đổi nó cẩu thả sẽ tạo cost cho nhiều người. Vì vậy versioning, deprecation, migration note, và example nhàm chán đều quan trọng. Chúng cho hệ thống di chuyển mà không giả vờ mọi chuyển động đều miễn phí.
Khi implementation thay đổi nhưng interface vẫn bình tĩnh, team đã tạo được một mảnh architecture sống qua tăng trưởng. Code bên trong có thể bị thay nhiều lần. Lời hứa vẫn readable. Nếu bạn từng thấy một boundary làm những thay đổi sau này bớt căng, mình rất muốn nghe điều gì đã làm lời hứa đó rõ ràng.