Các giao diện Tách riêng Nguyên tắc nói:
Không có khách hàng nào bị buộc phải phụ thuộc vào các phương thức mà nó không sử dụng. ISP chia các giao diện rất lớn thành các giao diện nhỏ hơn và cụ thể hơn để khách hàng sẽ chỉ phải biết về các phương thức mà họ quan tâm.
Có một vài câu hỏi chưa được trả lời ở đây. Một là:
Nhỏ như thế nào?
Bạn nói:
Hiện tại tôi xử lý vấn đề này bằng cách chia không gian tên của mô-đun tùy thuộc vào yêu cầu của khách hàng.
Tôi gọi hướng dẫn này là gõ vịt . Bạn xây dựng các giao diện chỉ hiển thị những gì khách hàng cần. Nguyên tắc phân tách giao diện không chỉ đơn giản là gõ vịt thủ công.
Nhưng ISP cũng không chỉ đơn giản là một lời kêu gọi cho các giao diện vai trò "mạch lạc" có thể được sử dụng lại. Không có thiết kế giao diện vai trò "mạch lạc" nào có thể bảo vệ hoàn hảo chống lại việc bổ sung một khách hàng mới với nhu cầu vai trò của chính nó.
ISP là một cách để cách ly khách hàng khỏi tác động của những thay đổi đối với dịch vụ. Nó được dự định để làm cho việc xây dựng diễn ra nhanh hơn khi bạn thực hiện các thay đổi. Chắc chắn nó có lợi ích khác, như không phá vỡ khách hàng, nhưng đó là điểm chính. Nếu tôi thay đổi count()
chữ ký chức năng dịch vụ , thật tuyệt nếu khách hàng không sử dụng count()
không cần chỉnh sửa và biên dịch lại.
Đây là lý do tại sao tôi quan tâm đến Nguyên tắc phân chia giao diện. Đó không phải là điều tôi coi niềm tin là quan trọng. Nó giải quyết một vấn đề thực sự.
Vì vậy, cách nó nên được áp dụng sẽ giải quyết một vấn đề cho bạn. Không có cách thức vơ vơ nào để áp dụng ISP mà không thể bị đánh bại chỉ bằng ví dụ đúng về một thay đổi cần thiết. Bạn có nhiệm vụ xem xét cách hệ thống thay đổi và đưa ra lựa chọn sẽ khiến mọi thứ im lặng. Hãy khám phá các tùy chọn.
Trước tiên hãy tự hỏi: việc thực hiện thay đổi giao diện dịch vụ có khó không? Nếu không, hãy ra ngoài và chơi cho đến khi bạn bình tĩnh lại. Đây không phải là một bài tập trí tuệ. Hãy chắc chắn rằng phương pháp chữa trị không tệ hơn căn bệnh này.
Nếu nhiều khách hàng sử dụng cùng một tập hợp con các hàm, điều đó lập luận cho các giao diện tái sử dụng "mạch lạc". Tập hợp con có khả năng tập trung xung quanh một ý tưởng mà chúng ta có thể nghĩ về vai trò của dịch vụ đang cung cấp cho khách hàng. Thật tuyệt khi nó hoạt động. Điều này không phải lúc nào cũng hoạt động.
Nếu nhiều khách hàng sử dụng các tập hợp con khác nhau của chức năng thì có thể khách hàng thực sự đang sử dụng dịch vụ thông qua nhiều vai trò. Điều đó ổn nhưng nó làm cho các vai trò khó thấy. Tìm họ và cố gắng trêu chọc họ. Điều đó có thể đưa chúng tôi trở lại trong trường hợp 1. Khách hàng chỉ cần sử dụng dịch vụ thông qua nhiều giao diện. Vui lòng không bắt đầu truyền dịch vụ. Nếu bất cứ điều gì có nghĩa là chuyển dịch vụ vào máy khách nhiều lần. Điều đó hoạt động nhưng nó khiến tôi đặt câu hỏi nếu dịch vụ không phải là một quả bóng bùn lớn cần phải phá vỡ.
Nếu nhiều khách hàng sử dụng các tập hợp con khác nhau nhưng bạn không thấy các vai trò thậm chí cho phép các khách hàng có thể sử dụng nhiều hơn một thì bạn không có gì tốt hơn là gõ vịt để thiết kế giao diện của bạn xung quanh. Cách thiết kế giao diện này đảm bảo rằng máy khách không tiếp xúc với ngay cả một chức năng mà nó không sử dụng nhưng nó gần như đảm bảo rằng việc thêm một máy khách mới sẽ luôn liên quan đến việc thêm một giao diện mới mà trong khi thực hiện dịch vụ không cần biết về nó giao diện tổng hợp các giao diện vai trò sẽ. Chúng tôi chỉ đơn giản là đánh đổi một nỗi đau cho người khác.
Nếu nhiều khách hàng sử dụng các tập hợp con khác nhau, chồng chéo, các khách hàng mới dự kiến sẽ thêm vào đó sẽ cần các tập hợp con không thể đoán trước và bạn không muốn chia tay dịch vụ sau đó xem xét một giải pháp chức năng hơn. Vì hai tùy chọn đầu tiên không hoạt động và bạn thực sự ở một nơi tồi tệ, nơi không có gì theo một mô hình và sẽ có nhiều thay đổi hơn, sau đó xem xét việc cung cấp cho mỗi chức năng đó là giao diện riêng. Kết thúc ở đây không có nghĩa là ISP đã thất bại. Nếu bất cứ điều gì thất bại, đó là mô hình hướng đối tượng. Giao diện phương thức duy nhất theo ISP trong cực đoan. Đó là một chút gõ bàn phím nhưng bạn có thể thấy điều này đột nhiên làm cho các giao diện có thể sử dụng lại. Một lần nữa, hãy chắc chắn rằng không có
Vì vậy, hóa ra họ có thể nhận được rất nhỏ thực sự.
Tôi đã đặt câu hỏi này như một thách thức để áp dụng ISP trong những trường hợp cực đoan nhất. Nhưng hãy nhớ rằng cực đoan là tốt nhất nên tránh. Trong một thiết kế được cân nhắc kỹ lưỡng áp dụng các nguyên tắc RẮN khác, các vấn đề này thường không xảy ra hoặc không quan trọng, gần như nhiều.
Một câu hỏi chưa được trả lời là:
Ai sở hữu các giao diện này?
Lâu dần tôi thấy các giao diện được thiết kế với tâm lý mà tôi gọi là "thư viện". Tất cả chúng ta đều có lỗi về mã hóa khỉ-khỉ-do bạn đang làm gì đó bởi vì đó là cách bạn đã thấy nó được thực hiện. Chúng tôi có tội với điều tương tự với giao diện.
Khi tôi nhìn vào một giao diện được thiết kế cho một lớp trong thư viện tôi từng nghĩ: ồ, những người này là ưu. Đây phải là cách đúng đắn để làm một giao diện. Điều tôi đã không hiểu là ranh giới thư viện có nhu cầu và vấn đề riêng. Đối với một điều, một thư viện hoàn toàn không biết gì về thiết kế của khách hàng. Không phải mọi ranh giới đều giống nhau. Và đôi khi ngay cả cùng một ranh giới có những cách khác nhau để vượt qua nó.
Dưới đây là hai cách đơn giản để xem thiết kế giao diện:
Giao diện sở hữu dịch vụ. Một số người thiết kế mọi giao diện để phơi bày mọi thứ mà một dịch vụ có thể làm. Bạn thậm chí có thể tìm thấy các tùy chọn tái cấu trúc trong IDE sẽ viết giao diện cho bạn bằng cách sử dụng bất kỳ lớp nào bạn cung cấp cho nó.
Giao diện khách hàng sở hữu. ISP dường như lập luận rằng điều này là đúng và sở hữu dịch vụ là sai. Bạn nên chia nhỏ mọi giao diện với nhu cầu của khách hàng. Vì khách hàng sở hữu giao diện nên nó xác định nó.
Vậy ai đúng?
Xem xét các plugin:
Ai sở hữu các giao diện ở đây? Các khách hàng? Các dịch vụ?
Hóa ra cả hai.
Màu sắc ở đây là các lớp. Lớp màu đỏ (phải) không cần biết gì về lớp màu xanh lá cây (bên trái). Lớp màu xanh lá cây có thể được thay đổi hoặc thay thế mà không cần chạm vào lớp màu đỏ. Bằng cách đó, bất kỳ lớp màu xanh lá cây có thể được cắm vào lớp màu đỏ.
Tôi muốn biết những gì cần biết về những gì và những gì không nên biết. Đối với tôi, "những gì biết về cái gì?", Là câu hỏi kiến trúc quan trọng nhất.
Hãy làm cho một số từ vựng rõ ràng:
[Client] --> [Interface] <|-- [Service]
----- Flow ----- of ----- control ---->
Một khách hàng là một cái gì đó sử dụng.
Một dịch vụ là một cái gì đó được sử dụng.
Interactor
xảy ra là cả hai.
ISP cho biết chia tay giao diện cho khách hàng. Tốt thôi, hãy áp dụng điều đó ở đây:
Presenter
(một dịch vụ) không nên ra lệnh cho Output Port <I>
giao diện. Giao diện nên được thu hẹp theo những gì Interactor
(ở đây đóng vai trò là khách hàng) cần. Điều đó có nghĩa là giao diện BIẾT về Interactor
và, để theo ISP, phải thay đổi với nó. Và điều này là tốt.
Interactor
(ở đây hoạt động như một dịch vụ) không nên ra lệnh cho Input Port <I>
giao diện. Giao diện nên được thu hẹp theo những gì Controller
(một khách hàng) cần. Điều đó có nghĩa là giao diện BIẾT về Controller
và, để theo ISP, phải thay đổi với nó. Và điều này là không tốt.
Lớp thứ hai không ổn vì lớp màu đỏ không được biết về lớp màu xanh lá cây. Vậy ISP có sai không? Vâng tốt bụng. Không có nguyên tắc là tuyệt đối. Đây là một trường hợp mà những kẻ ngốc thích giao diện hiển thị mọi thứ mà dịch vụ có thể làm được là đúng.
Ít nhất, họ đúng nếu Interactor
không làm gì khác ngoài trường hợp sử dụng này cần. Nếu việc Interactor
này xảy ra đối với các trường hợp sử dụng khác thì không có lý do gì Input Port <I>
để biết về chúng. Không chắc chắn tại sao Interactor
không thể chỉ tập trung vào một Ca sử dụng vì vậy đây không phải là vấn đề, nhưng mọi thứ xảy ra.
Nhưng input port <I>
giao diện đơn giản là không thể tự nô lệ cho Controller
máy khách và đây là một plugin thực sự. Đây là ranh giới của 'thư viện'. Một cửa hàng lập trình hoàn toàn khác có thể viết lớp màu xanh lá cây nhiều năm sau khi lớp màu đỏ được xuất bản.
Nếu bạn đang vượt qua ranh giới 'thư viện' và bạn cảm thấy cần phải áp dụng ISP mặc dù bạn không sở hữu giao diện ở phía bên kia, bạn sẽ phải tìm cách thu hẹp giao diện mà không thay đổi giao diện.
Một cách để kéo nó ra là một bộ chuyển đổi. Đặt nó giữa khách hàng thích Controler
và Input Port <I>
giao diện. Bộ điều hợp chấp nhận Interactor
như một Input Port <I>
và ủy thác nó hoạt động với nó. Tuy nhiên, nó chỉ hiển thị những gì khách hàng Controller
cần thông qua giao diện vai trò hoặc giao diện thuộc sở hữu của lớp màu xanh lá cây. Bộ điều hợp không tự đi theo ISP nhưng cho phép lớp phức tạp hơn thích Controller
thưởng thức ISP. Điều này hữu ích nếu có ít bộ điều hợp hơn so với các máy khách như Controller
vậy sử dụng chúng và khi bạn ở trong tình huống bất thường khi bạn vượt qua ranh giới thư viện và mặc dù được xuất bản, thư viện sẽ không ngừng thay đổi. Nhìn vào bạn Firefox. Bây giờ những thay đổi đó chỉ phá vỡ bộ điều hợp của bạn.
Vì vậy, điều này có nghĩa là gì? Điều đó có nghĩa là bạn không cung cấp đủ thông tin để tôi nói cho bạn biết bạn nên làm gì. Tôi không biết nếu không theo dõi ISP sẽ gây ra sự cố cho bạn. Tôi không biết nếu làm theo nó sẽ không gây ra cho bạn nhiều vấn đề hơn.
Tôi biết bạn đang tìm kiếm một nguyên tắc hướng dẫn đơn giản. ISP cố gắng để được điều đó. Nhưng nó để lại rất nhiều không trả lời. Tôi tin vào nó. Có, vui lòng không ép buộc khách hàng phụ thuộc vào các phương pháp mà họ không sử dụng mà không có lý do chính đáng!
Nếu bạn có lý do chính đáng, chẳng hạn như thiết kế của bạn để chấp nhận plugin, thì hãy lưu ý đến các vấn đề không tuân theo nguyên nhân của ISP (khó thay đổi mà không phá vỡ máy khách) và cách để giảm thiểu chúng (giữ Interactor
hoặc ít nhất là Input Port <I>
tập trung vào một ổn định trường hợp sử dụng).