Interface Segregation
Тема дорожной карты · Software Architecture
Принцип разделения интерфейсов ('Клиенты не должны быть вынуждены зависеть от методов, которые они не используют') является ключевым для создания эффективных и гибких систем. Интерфейс, состоящий из 50 методов, заставляет каждого реализатора реализовать все 50 методов, большинство из которых будут просто заглушками, бросающими NotImplementedException. Это не только усложняет код, но и увеличивает вероятность ошибок. Вместо этого, следует использовать роль-ориентированные интерфейсы, где класс, который только читает, не нуждается в методах записи. Это особенно важно на границах плагинов и расширений, где каждый компонент должен быть независимым и модульным.
Как это работает
При проектировании интерфейса важно спрашивать, какие клиенты вызывают какие методы. Если разные клиенты вызывают непересекающиеся подмножества методов, интерфейс следует разделить по линиям клиентов. Примером этого является паттерн репозитория (Repository Pattern), где интерфейс IReadOnlyRepository (с методами Get и List) отделяется от интерфейса IRepository (с методами Add, Update и Delete). Такая структура позволяет read-only клиентам не зависеть от методов записи, которые они не используют. Это позволяет упростить и улучшить управляемость кодом.
Когда применять
Принцип разделения интерфейсов (ISP) следует строго применять на границах API или библиотек, где внешние потребители зависят от интерфейса. Внутри приложения, где вы контролируете всех вызывающих, можно применять ISP более лениво, делая разделение только тогда, когда реальный клиент потребует более узкого интерфейса. Это позволяет избежать излишней сложности и упрощает тестирование и поддержку кода.
Типичные ошибки
(1) Взрыв интерфейсов — это когда интерфейс разделяется до такой степени, что каждый метод становится отдельным интерфейсом. Это может сделать типовую систему сложной в навигации, что превышает сложность реализации. (2) Неправильная ось разделения — когда интерфейс разделяется исходя из количества методов (например, 5 методов — это хорошо, 10 методов — это слишком много), а не по паттерну использования клиентов. Это может привести к неправильному разделению и усложнению кода. (3) God-интерфейс как 'проще API' — объединение всего в один интерфейс 'для удобства' может привести к тому, что клиенту придется мокать всю поверхность для тестов, что усложняет процесс тестирования и поддержки кода.