Получение правильного уровня детализации интерфейса - PullRequest
10 голосов
/ 21 января 2011

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

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

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

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

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

Ответы [ 7 ]

4 голосов
/ 21 января 2011

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

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

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

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

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

Удачи!

4 голосов
/ 24 января 2011

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

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

4 голосов
/ 21 января 2011

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

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

2 голосов
/ 21 января 2011

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

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

2 голосов
/ 21 января 2011

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

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

2 голосов
/ 21 января 2011

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

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

2 голосов
/ 21 января 2011

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

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

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

...