> Что такое принцип разделения интерфейса (Interface Segregation Principle) (iOS, Swift)

Уровень: junior · Роль: mobile · Категория: Технические вопросы

Компании: MTS

Стек: iOS, Swift

> Пример ответа

Короткий ответ

Принцип разделения интерфейса (ISP) гласит: клиенты не должны зависеть от методов, которые они не используют. Вместо одного "толстого" интерфейса лучше создавать несколько узких, специализированных. В iOS это особенно важно при работе с протоколами - они должны быть минимальными и описывать только ту функциональность, которая реально нужна конкретному потребителю.

Подробное объяснение

ISP - один из пяти принципов SOLID. Его суть: интерфейс (в Swift - протокол) должен быть настолько маленьким, насколько это возможно, но достаточным для выполнения своей задачи. Если класс или структура вынуждены реализовывать методы, которые им не нужны, это нарушает принцип.

Проблема "толстых" протоколов проявляется так:

  • реализация содержит лишний код, который не используется;
  • изменение одного метода в протоколе ломает все типы, которые его реализуют;
  • появляется скрытая связность между несвязанными обязанностями.

Решение - декомпозиция: разбить большой протокол на несколько маленьких. Каждый клиент зависит только от того протокола, который ему действительно нужен. В Swift это особенно удобно, потому что протоколы можно комбинировать через композицию (например, typealias или наследование протоколов).

Важно не путать ISP с принципом единственной ответственности (SRP). SRP касается классов и их причин для изменения, а ISP - интерфейсов и их потребителей. Один класс может иметь несколько узких протоколов, описывающих разные аспекты его поведения.

На практике

В iOS-разработке ISP применяется повсеместно:

  • делегаты и data source разбиты на отдельные протоколы (UITableViewDataSource и UITableViewDelegate - классический пример);
  • в архитектуре VIPER протоколы View, Interactor, Presenter разделены, чтобы каждый модуль зависел только от нужного;
  • при работе с сетью лучше иметь отдельные протоколы для загрузки данных и для их обработки, а не один универсальный.

Нарушение ISP часто встречается, когда разработчик создаёт один протокол для всего экрана: и загрузка данных, и отображение, и навигация. В результате ViewController реализует десятки методов, половина из которых пустые.

Пример кода

Плохо - один "толстый" протокол:

SWIFT
protocol UserService {
func fetchUser() -> User
func updateUser(_ user: User)
func deleteUser(_ user: User)
func fetchFriends() -> [User]
func sendMessage(to user: User, text: String)
}

Класс, которому нужны только друзья, вынужден реализовывать всё:

SWIFT
class FriendsListViewModel: UserService {
func fetchUser() -> User { fatalError("not needed") }
func updateUser(_ user: User) { fatalError("not needed") }
func deleteUser(_ user: User) { fatalError("not needed") }
func fetchFriends() -> [User] { /* real logic */ }
func sendMessage(to user: User, text: String) { fatalError("not needed") }
}

Хорошо - разделённые протоколы:

SWIFT
protocol UserFetching {
func fetchUser() -> User
}
protocol UserUpdating {
func updateUser(_ user: User)
func deleteUser(_ user: User)
}
protocol FriendsFetching {
func fetchFriends() -> [User]
}
protocol Messaging {
func sendMessage(to user: User, text: String)
}

Теперь каждый класс реализует только то, что использует:

SWIFT
class FriendsListViewModel: FriendsFetching {
func fetchFriends() -> [User] { /* real logic */ }
}

Как отвечать на собеседовании

Начни с определения: "ISP - это принцип, согласно которому клиенты не должны зависеть от методов, которые не используют". Затем приведи пример из iOS: разделение UITableViewDataSource и UITableViewDelegate. Объясни, зачем это нужно: меньше связанность, проще тестировать, легче поддерживать. Если спросят про связь с SOLID - скажи, что ISP дополняет SRP, но работает на уровне интерфейсов.

Для junior достаточно показать понимание идеи и уметь привести простой пример. Если спросят про композицию протоколов - упомяни, что в Swift можно комбинировать узкие протоколы через typealias или наследование, но не углубляйся, если не уверен.

Что проверяет интервьюер

Интервьюер оценивает:

  • понимание базовой идеи - почему плохо иметь "толстые" протоколы;
  • умение применять принцип в контексте iOS (делегаты, data source, VIPER);
  • способность увидеть нарушение ISP в коде и предложить рефакторинг;
  • знание смежных тем: SOLID, композиция протоколов, dependency inversion.

Для junior достаточно, чтобы ты уверенно объяснил принцип и привёл корректный пример. Глубокое обсуждение trade-off и edge cases обычно ожидается от middle и senior.

Типичные ошибки

  • Путать ISP с SRP - это разные принципы, хотя и связанные.
  • Считать, что ISP запрещает наследование протоколов - на самом деле наследование протоколов допустимо, главное - чтобы каждый клиент зависел от минимального набора методов.
  • Приводить пример, где разделение протоколов приводит к дублированию кода - это не нарушение ISP, а нормальная цена за слабую связанность.
  • Говорить, что "протокол должен быть маленьким" без объяснения, почему это важно для конкретного клиента.
  • Забывать, что ISP касается не только протоколов, но и любых интерфейсов - например, публичных API классов или структур.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью