Я новичок в команде, работающей над довольно большим проектом с множеством компонентов и зависимостей. Для каждого компонента есть interfaces
пакет, в котором размещаются открытые интерфейсы для этого компонента. Это хорошая практика?
Моя обычная практика всегда заключалась в том, что интерфейсы и реализации были в одном пакете.
Ответы:
Размещение и интерфейса, и реализации - обычное дело и не кажется проблемой.
Возьмем, к примеру, Java API - у большинства классов оба интерфейса и их реализации включены в один пакет.
Возьмем, к примеру,
java.util
пакет:Он содержит интерфейсы , такие как
Set
,Map
,List
, в то же время имея реализаций , таких какHashSet
,HashMap
иArrayList
.Кроме того, документация Javadocs разработана для хорошей работы в этих условиях, поскольку при отображении содержимого пакета документация разделяется на представления интерфейсов и классов .
Наличие пакетов только для интерфейсов может быть немного излишним, если только интерфейсов не огромное количество. Но разделение интерфейсов на их собственные пакеты только ради этого звучит как плохая практика.
Если необходимо отличать имя интерфейса от имени реализации, можно использовать соглашение об именах, чтобы упростить идентификацию интерфейсов:
Добавьте к имени интерфейса префикс
I
. Этот подход используется с интерфейсами в .NET framework. Было бы довольно легко сказать, чтоIList
это интерфейс для списка.Используйте
able
суффикс - . Такой подход часто рассматривается в API Java, напримерComparable
,Iterable
иSerializable
некоторые из них.источник
Для любого языка их можно собрать в одном пакете. Важно то, что открыто для внешнего мира и как это выглядит снаружи. Никто не узнает и не заботится о том, находится ли реализация в том же самом пакете или нет.
Давайте посмотрим на этот конкретный экземпляр.
Если у вас есть все общедоступные объекты в одном пакете и личные объекты в другом пакете, который не является общедоступным, клиент библиотеки видит один пакет. Если вы переместите частные вещи в пакет с общедоступными вещами, но не открываете их изнутри пакета, клиент увидит то же самое.
Таким образом, это пахнет правилом без веской причины: оно принимает решение на основании чего-то, что является общедоступным, но это решение не оказывает никакого влияния на то, что является общедоступным.
Тем не менее, если в каком-то конкретном случае кажется хорошей идеей разделить интерфейс и реализацию на отдельные пакеты, продолжайте и сделайте это. На ум приходят причины для этого: пакет огромен или у вас есть альтернативная реализация, которую вы, возможно, захотите добавить вместо стандартной.
источник
friend
(C ++) илиinternal
(C #).Во многих фреймворках, таких как OSGi, это почти обязательно. Я думаю, что это способствует более слабому сцеплению на уровне упаковки, а не на уровне банки.
источник
Одним из аргументов в пользу размещения интерфейсов в разных пакетах является то, что проще создавать jar-файлы api, которые можно распространять среди потребителей вашего продукта или услуги. Это вполне возможно сделать вместе с интерфейсами и реализациями, но проще создать сценарий, если они находятся в разных пакетах.
источник
В книге « Практическая разработка программного обеспечения: подход к изучению конкретного случая» предлагается размещать интерфейсы в отдельных проектах / пакетах.
Архитектура PCMEF +, о которой говорится в книге, имеет следующие принципы:
Описание принципов №3 и №7 объясняет, почему это хорошая идея:
См. Эту ссылку: http://comp.mq.edu.au/books/pse/about_book/Ch9.pdf
источник
Да, это очень хорошая практика, потому что она позволяет публиковать интерфейс без публикации конкретной реализации. Тем не менее, если вам не нужно публиковать внешние интерфейсы, нет проблем с помещением определений интерфейсов в тот же пакет, что и реализация.
источник
Мы делаем это там, где работаю (то есть: помещаем интерфейс в один пакет, а реализацию в другой), и главное преимущество, которое мы получаем от этого, заключается в том, что мы можем легко переключаться между реализациями.
источник
У меня мало опыта работы с Java, но мне нравится делать это как хорошую практику в C # /. NET, потому что это допускает расширение в будущем, когда сборки с конкретными классами, реализующими интерфейсы, могут не распределяться полностью до клиент, потому что они передаются фабрикой посредников или по сети в сценарии веб-службы.
источник
Обычно я добавляю интерфейсы к реализации, однако я могу понять, почему вы можете захотеть сохранить их отдельно. Скажем, например, кто-то хотел переопределить классы на основе ваших интерфейсов, им понадобится jar / lib / etc с вашей реализацией, а не только интерфейсы. Если их разделить, вы можете просто сказать «Вот моя реализация этого интерфейса» и покончить с этим. Как я уже сказал, не то, что я делаю, но я понимаю, почему некоторые могут этого захотеть.
источник
Я делаю это в проекте, и у меня это хорошо работает по следующим причинам:
Отдельно упакованные интерфейсы и реализации предназначены для другого варианта использования, чем для различных типов Map или Set. Нет смысла иметь пакет только для деревьев (java.util.tree.Map, java.util.tree.Set). Это просто стандартная структура данных, поэтому соберите ее вместе с другими структурами данных. Однако, если вы имеете дело с игрой-головоломкой, которая имеет действительно простой интерфейс отладки и красивый производственный интерфейс, в качестве части интерфейса у вас могут быть com.your.app.skin.debug и com.your.app. . кожа. симпатичная. Я бы не стал помещать их в один и тот же пакет, потому что они делают разные вещи, и я знаю, что прибегну к некоторому SmurfNamingConvention (DebugAttackSurface, DebugDefenceSurface, PrettyAttackSurface и т. Д.), Чтобы создать неформальное пространство имен для двух, если бы они были в одном пакете.
Мое решение проблемы поиска связанных интерфейсов и реализаций, находящихся в отдельных пакетах, состоит в том, чтобы принять конфигурацию именования для моих пакетов. Например, я могу разместить все свои интерфейсы в com.your.app.skin.framework и знать, что другие пакеты на том же уровне дерева пакетов являются реализациями. Недостаток в том, что это нетрадиционное соглашение. Честно говоря, через 6 месяцев я посмотрю, насколько хороша эта конвенция :)
Я не использую эту технику религиозно. Есть интерфейсы, которые имеют смысл только в конкретной реализации. Я не вставляю их в пакет framework. Есть некоторые пакеты, в которых не похоже, что я собираюсь создать 40 различных классов реализации, поэтому я не беспокоюсь.
Мое приложение использует guice и имеет очень много интерфейсов.
Вопросы разработки программ обычно связаны с преимуществами и недостатками, и универсального ответа не существует. Зачем вообще использовать эту технику в крошечной программе из 200 строк? Для меня это имеет смысл, учитывая мои другие архитектурные решения, для моей конкретной проблемы. :)
источник
Я предпочитаю их в одной упаковке. Нет смысла создавать пакет специально для интерфейсов. Это особенно важно для команд, которым просто нравятся свои префиксы и суффиксы интерфейса (например, «I» и «Impl» для Java).
Если есть необходимость опубликовать набор интерфейсов в качестве общедоступного API, имеет смысл сохранить их в совершенно отдельном проекте и вместо этого создать зависимости проекта. Но все упирается в предпочтение и удобство ситуации, я полагаю.
источник
Поместите их в пакеты, которые отражают ваши проекты. Соединять интерфейсы и реализации вместе, если они являются частью одного проекта, - это нормально, но если вы пишете API, то кто-то другой, вероятно, выберет имя пакета, соответствующее их проекту.
В общем, если это для одного и того же проекта, я не вижу никакой пользы в хранении интерфейсов в отдельном пакете от их имплицитных. Если он становится загроможденным, могут возникнуть другие проблемы с именованием пакетов, независимо от устройства интерфейса.
источник
Я думаю, важно отметить, что для платформы OSGi лучше, если они находятся в разных пакетах, так что вы можете легко экспортировать весь пакет, скрывая пакеты реализации.
источник
Есть много веских причин для помещения интерфейсов в отдельный пакет от реализации. Например, вы можете использовать контейнер, поддерживающий внедрение зависимостей, для подключения необходимой реализации (-ов) во время выполнения, и в этом случае во время сборки должен присутствовать только интерфейс, а реализация может быть предоставлена во время выполнения. В качестве альтернативы вы можете захотеть предоставить несколько реализаций (например, используя фиктивные реализации для тестирования) или несколько версий конкретной реализации во время выполнения (например, для A / B-тестирования и т. Д.). Для таких случаев удобнее упаковать интерфейс и реализацию отдельно.
источник