Приведите пример интерфейса, нарушающего принцип интерфейсной сегрегации
Что проверяют
Видите ли вы нарушение принципа в том коде, который пишете каждый день. На Android это не абстрактный вопрос: платформенные слушатели и раздутые контракты экрана дают примеры прямо из проекта, и интервьюер ждёт именно их.
Как отвечать
Назовите принцип одной строкой и переходите к платформе. Самый узнаваемый пример это слушатель изменения текста: три метода, из которых обычно нужен один.
editText.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, a: Int, b: Int, c: Int) {}
override fun onTextChanged(s: CharSequence?, a: Int, b: Int, c: Int) {}
override fun afterTextChanged(s: Editable?) { validate(s?.toString()) }
})Два пустых метода в каждом использовании это и есть цена толстого контракта. Не случайно рядом появились расширения вроде doAfterTextChanged, а у слушателя анимации есть адаптер с пустыми реализациями.
Второй пример ближе к архитектуре: интерфейс экрана в духе showLoading, hideLoading, showError, showEmpty, showItems, который презентер вызывает вразнобой, а фрагмент реализует целиком. Лечится это не дроблением на пять интерфейсов, а одним состоянием: запечатанная иерархия и единственный метод отрисовки. Для коротких контрактов в Kotlin удобен fun interface: он принимает лямбду и убирает пустые заглушки.
Где спотыкаются
Считают адаптер с пустыми методами решением. Он убирает шум в вызывающем коде, но сам контракт остаётся прежним, а в Kotlin такой адаптер ещё и занимает единственную позицию наследования класса.
Второе: дробят интерфейс экрана на множество мелких и получают ту же связность, только рассыпанную по файлам. Проблема была не в числе методов, а в том, что презентер командует интерфейсом по шагам вместо передачи цельного состояния.
Третье: путают принцип с сокрытием реализации. Узкий интерфейс нужен клиенту, а не автору класса, поэтому объявляют его на стороне вызывающего, а не рядом с реализацией, которую он якобы описывает.