Программирование на основе интерфейсов: пишете ли вы интерфейсы для всех классов вашего домена? - PullRequest
23 голосов
/ 30 сентября 2008

Я согласен, что программирование на основе интерфейсов является хорошей практикой. В большинстве случаев в Java «интерфейс» в этом смысле означает интерфейс языковой конструкции, так что вы пишете интерфейс и класс реализации и большую часть времени используете интерфейс вместо класса реализации.

Интересно, будет ли это хорошей практикой и для написания моделей предметной области? Так, например, если у вас есть клиент класса домена и у каждого клиента может быть список заказов, вы бы обычно также писали интерфейсы ICustomer и IOrder. А также у Клиента будет список IOrders вместо Orders? Или вы бы использовали интерфейсы в доменной модели, только если она действительно управляется доменом, например у вас есть как минимум два разных типа заказов? Другими словами, будете ли вы использовать интерфейсы только из-за технических потребностей в модели предметной области или только в тех случаях, когда это действительно уместно в отношении фактической предметной области?

Ответы [ 15 ]

26 голосов
/ 30 сентября 2008

Написание интерфейсов «просто потому, что» кажется мне пустой тратой времени и энергии, не говоря уже о нарушении принципа KISS.

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

12 голосов
/ 30 сентября 2008

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

8 голосов
/ 30 сентября 2008

Интерфейсы - отличный способ изолировать компоненты для модульного тестирования и общего управления зависимостями. Сказав это, я часто предпочитаю абстрактные классы, поэтому, по крайней мере, часть общего поведения выгружается туда, а не заставляет некоторые дубликаты, которые приносят интерфейсы. Современные IDE позволяют быстро и легко создавать интерфейсы, поэтому они не , которые много работают: -)

5 голосов
/ 30 сентября 2008

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

Это, конечно, не означает, что нужно избегать использования интерфейсов в доменных объектах. Используйте там, где это необходимо. Например, в последнее время я работал над веб-приложением, в котором разные типы доменных объектов соответствуют страницам с постоянными ссылками, в которых пользователи могут оставлять комментарии. Итак, каждый из этих доменных объектов теперь реализует интерфейс «Commentable». Весь код, основанный на комментариях, затем программируется в интерфейсе Commentable, а не в доменных объектах.

4 голосов
/ 29 июня 2009

На самом деле, этот вопрос является примером распространенного заблуждения о «программировании на интерфейсах».

Видите ли, этот является очень хорошим принципом, но он действительно не означает, что многие думают, что это означает!

«Программа для интерфейса, а не для реализации» (из книги GoF) означает только то, что вы не должны стараться изо всех сил создавать отдельных интерфейсов для всего. Если у вас есть объект ArrayList, тогда объявите тип переменной / поля / параметра / возвращаемого типа List. В этом случае код клиента будет работать только с типом интерфейса.

В книге «Эффективная Ява» Джошуа Блоха этот принцип более четко выражен в «Пункте 52: Обращайтесь к объектам по их интерфейсам». Там даже написано жирным шрифтом:

Вполне уместно ссылаться на объект классом, а не интерфейс, если соответствующий интерфейс не существует.

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

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

4 голосов
/ 30 сентября 2008

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

Довольно просто в IDEA / eclipse превращать конкретный класс в интерфейс, когда вы решите, что он вам нужен.

Затем используйте внедрение зависимостей с Spring или Guice , если у вас есть много реализаций интерфейса для внедрения в места в вашем коде, которые вы используете 'new'

2 голосов
/ 30 сентября 2008

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

Кроме того, написание интерфейса вручную - пустая трата времени. Вы можете использовать рефакторинг Resharper «Pull Members», чтобы позволить ему создать новый интерфейс из определенного класса в считанные секунды. Другие инструменты рефакторинга, которые интегрируются с IDE, также должны иметь аналогичную функциональность.

1 голос
/ 18 декабря 2008

* Я делаю это, потому что мне это нужно для создания прокси моих доменных объектов.

1 голос
/ 30 сентября 2008

Мы извлекаем интерфейсы из всего лишь потому, что это помогает в тестировании (насмешках) и для таких вещей, как AOP. Eclipse может сделать это автоматически: Refactor-> Extract Interface.

И если вам нужно изменить класс позже, вы можете использовать Refactor-> Pull Up ..., чтобы вывести необходимые методы на интерфейс.

1 голос
/ 30 сентября 2008

Я думаю, что основной причиной программирования на интерфейсах является тестируемость. Следовательно, для объектов домена - просто придерживайтесь POJO или POC # Os :) и т. Д., Т. Е. Просто не допускайте, чтобы ваши классы добавляли какую-либо конкретную инфраструктуру, чтобы они не зависели от зависимостей сборки и времени выполнения, и все. Создание интерфейсов для DAO - хорошая идея.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...