Получение правильного уровня детализации интерфейса

В настоящее время я выполняю некоторые работы по разработке API, включая спецификацию ряда интерфейсов как абстракции, которые позже будут реализованы различными конкретными классами.

Как это бывает, я использую Java, но я думаю, что этот вопрос имеет отношение к любому языку, поддерживающему аналогичную концепцию интерфейса.

Я заметил, что часто существует опция между:

  • Создание большого интерфейса с полным набором методов
  • Создание нескольких интерфейсов, каждый из которых содержит подмножество полного диапазона методов (одному конкретному классу, вероятно, придется реализовать несколько или все эти интерфейсы).

Каковы плюсы и минусы каждого подхода?

Ответ 1

Про разделение интерфейса - это то, что вы можете разделить методы на группы обязанностей, которые имеют смысл быть вместе. Кон - ваш интерфейс теперь разделен на кучу меньших, которые может реализовать один класс.

Я бы порекомендовал разделить интерфейс, где он помогает читабельности, а не дальше. Если у вас есть один класс, который реализует 10 интерфейсов, либо эти интерфейсы необходимо объединить в один, либо, возможно, класс берет на себя большую ответственность, и на самом деле это должно быть два или более классов.

Ответ 2

В терминах анти-шаблонов я бы сказал, что слишком много интерфейсов может привести к так называемой Yo-yo-проблеме:

http://en.wikipedia.org/wiki/Yo-yo_problem

И помещение всего в один интерфейс может создать объект God:

http://en.wikipedia.org/wiki/God_object

Вы должны найти свое место где-то посередине:)

Удачи!

Ответ 3

Еще один вопрос: интерфейсы, которые помещают элементы в коллекцию, должны быть отделены от тех, которые берут элементы; комбинированный интерфейс должен наследовать от обоих. Таким образом разделяющие интерфейсы позволяют ковариацию и контравариантность. Например, ReadableBunch (Of ToyotaPrius) может быть безопасно передан обычной процедуре, ожидающей ReadableBunch (Of Car) [поскольку объект, который выдает экземпляры ToyotaPrius, при этом выдаст экземпляры Car], и WritableQueue (Of Car) ) могут быть безопасно переданы обычной процедуре, ожидающей WriteableQueue (из HondaCivic) [поскольку объект, который может принять автомобиль, по определению примет HondaCivic].

Я не знаю, означает ли этот тип ковариации и контравариантности что-либо в Java, но поскольку вопрос был помечен как язык-агностик, вопрос должен рассматриваться кем-либо, кодирующим платформы, которые поддерживают ковариацию и контравариантность (например .net)

Ответ 4

Я бы не стал выступать за интерфейс со слишком многими методами, поскольку я бы тоже не занимался классом. Программисту, который должен использовать такие интерфейсы или производные классы, будет сложно понять, как они связаны; кроме того, пытаясь вспомнить, что они есть и когда использовать, это похоже на то, что жонглирование слишком много мячей.

Для меня, в общем, более 1000 строк в модуле слишком много; более 100 строк в методе; более 15 методов или около того в классе или интерфейсе. Конечно, могут быть исключения, но я стараюсь их избегать.

Я бы определил, какие интерфейсы у вас есть, прежде чем думать, какие методы входят в них. Рассмотрим, что такое "атомарное поведение" для каждого абстрактного объекта в вашей системе и сделать каждый объект интерфейсом, составленным с наследованием, если это необходимо. Затем определите методы - после этого, вероятно, в каждом интерфейсе не будет много.

Ответ 5

Создание нескольких интерфейсов, каждый из которых содержит подмножество полного диапазона методов

Этот подход будет лучше работать с принципом дизайна "предпочитать композицию для наследования", поскольку отдельные классы могут реализовать один (или несколько) из интерфейсы.

Ответ 6

У меня нет хорошего ответа на ваш вопрос. Дизайн API - это немного искусства. Если вы находитесь в середине большого проекта, я рекомендую вам получить копию Практический дизайн API Ярослава Тулаха из славы NetBeans.

Я думаю, он рекомендовал бы против слишком многих методов, некоторые из которых могли бы быть просто вспомогательными методами. Вы должны предоставить минимум, необходимый для работы с API. Чем меньше слов, тем лучше.

Ответ 7

Количество методов в интерфейсе должно управляться только его известным (или ожидаемым) использованием. Если вызывающие абоненты обычно используют три разных (но перекрывающиеся) элемента интерфейса шесть членов, то шесть это!

Большое количество методов часто указывает на слабое сцепление, и хороший дизайн объекта должен поместить естественный предел на это число. Но вы никогда не должны разделить интерфейс, чтобы уменьшить количество методов, которые он содержит.