Программирование с использованием интерфейсов:Вы пишете интерфейсы для всех классов вашей предметной области?

StackOverflow https://stackoverflow.com/questions/152077

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

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

Затем используйте внедрение зависимостей с помощью Весна или Гуис если у вас есть много реализаций интерфейса для внедрения в места вашего кода, вы используете «новый»

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

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

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

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

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

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

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

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

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

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

В основном мы пишем веб-приложения с помощью Wicket, Spring и Hibernate и используем интерфейсы для Spring Beans, например.Сервисы и DAO.Для этих классов интерфейсы имеют смысл.Но мы также используем интерфейсы для каждого предметного класса, и я думаю, что это просто излишество.

Даже если вы почти уверены, что будет только один конкретный тип объекта модели, использование интерфейсов несколько упрощает макетирование и тестирование (но в наши дни существуют платформы, которые могут помочь вам автоматически генерировать макетные классы, даже для конкретных классов Java). Mockito, JTestR, Spring, Groovy...)

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

Написание интерфейсов для доменных классов может иметь смысл, если вы используете их для модульного тестирования.Мы используем Mock-объекты при модульном тестировании.Итак, если у вас есть интерфейс для объекта домена и сам ваш объект домена НЕ готов, но ваш клиент может проверить использование интерфейса с помощью фиктивных объектов.

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

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

Мы извлекаем интерфейсы из всего только потому, что это помогает в тестировании (издевательстве) и для таких вещей, как АОП.Eclipse может сделать это автоматически:Рефакторинг->Извлечь интерфейс.

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

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

Это еще одна вещь, с которой я столкнулся, о которой следует помнить, особенно в случае сгенерированного домена и объектов DAO.Многие интерфейсы слишком специфичны.Скажем, у многих объектов домена есть идентификатор и поле статуса. Почему у них нет общего интерфейса?Это вызвало у меня разочарование: излишне плоская (с точки зрения наследования) модель домена.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top