Есть ли в Java прирост производительности при использовании интерфейсов для сложных моделей? - PullRequest
4 голосов
/ 14 апреля 2010

Название вряд ли понятно, но я не уверен, как обобщить это по-другому. Любые изменения для уточнения приветствуются.

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

«Хорошее применение», которое мне порекомендовали, - это создание интерфейса с его уникальной реализацией. Никакого другого класса, реализующего этот интерфейс, наверняка не будет. Мне сказали, что это лучше сделать, потому что он «выставляет меньше» (или что-то близко) другим классам, которые будут использовать методы из этого класса, так как эти объекты ссылаются на объект из его интерфейса (все публичные методы). от реализации, воспроизводимой в интерфейсе).

Это кажется мне довольно странным, так как мне кажется, что я использую C ++ (с заголовочными файлами). Там я вижу смысл, но на Яве?

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


Редактировать: Спасибо всем за ответы, это было действительно полезно и поучительно (большинство из них, а не только "принятый").

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

Ответы [ 10 ]

12 голосов
/ 14 апреля 2010

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

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

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

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

Все это говорит о том, что, если после проведенного выше анализа вы по-прежнему не используете интерфейс для своего класса модели, запишите об этом. Пересмотреть его, скажем, через полгода. Затем, , если вы все еще чувствуете, что он не окупился, просто сбросьте его . Интерфейсы - как и любой другой элемент вашей программы - всегда должны иметь четкую цель и причину существования (и лучше, чем "мой коллега сказал мне создать его"). Они не панацея. Если вы используете их умно, вы делаете свой код лучше. Если вы используете их глупо, вы делаете свой код еще хуже. Тот факт, что вы разместили этот вопрос здесь, означает, что вы хотите узнать, как правильно их использовать, и это хорошо: -)

4 голосов
/ 14 апреля 2010

Кратко -

  1. вы явно документируете API для этого модуля в объекте интерфейса. Это будет понятнее вашим пользователям и, возможно, заставит вас задуматься о том, что происходит в этом интерфейсе
  2. вы можете предоставить несколько интерфейсов для одного и того же объекта и ограничить потребителей в том, что они могут делать (например, только чтение и чтение-запись)
  3. фреймворки используют интерфейсы, а классы насмешек - очень мощный метод тестирования
4 голосов
/ 14 апреля 2010

Прежде всего, интерфейсы не имеют никакого выигрыша в производительности. Во всяком случае, использование полиморфного кода и динамической диспетчеризации (например, виртуальных функций C ++) сопряжено с издержками.

Думайте об интерфейсах не как о чем-то, что добавляет выразительную силу, а как о чем-то, что заставляет вас писать лучше. Интерфейсы важны, ИМХО, по трем причинам:

1) Они могут помочь вам написать код с лучшей инкапсуляцией, сокрытием данных, стабильностью и т. Д.

2) Они могут помочь вам разделить поведение и реализацию, думая о том, что вы пытаетесь представить, а не о том, как это реализовать. Неспособность добавить состояние делает многое для предотвращения случайного добавления.

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

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

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

Должны ли вы всегда писать интерфейсы? Конечно, нет. Всегда бойтесь правил «Всегда» :) Это всегда баланс между потраченной впустую работой и = бесполезной сложностью и выгодами. Со временем и опытом вы получаете инстинкт этого.

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

3 голосов
/ 14 апреля 2010

Фактически, использование интерфейсов вместо классов позволяет вам три вещи:

  1. Отстранение контракта от его реализации: контракт - это интерфейс (это то, что вы объявляете, вы будете делать), а класс - это, очевидно, реализация
  2. Обеспечить легко альтернативную реализацию. Типичные примеры этого подразумевают замену механизма хранения другим без изменения пользовательского кода (например, перераспределение MySQL, скажем, Project Voldemort)
  3. Как преимущество 2 (и на этот раз легко расширяемое для элементов модели), интерфейсы позволяют выполнять своего рода тестирование в виде белого ящика: с помощью фреймворковой инфраструктуры (JMock, EasyMock, ...) вы отмените Реализация интерфейса, поведение которого может быть подозрительным, так называемым «макетом», возвращающим именно то, что вы ожидаете от своего теста. Это позволит вашему тесту не только проверить один компонент, но и убедиться, что ошибка исходит от этого компонента, а не от его внутренних подрядчиков (интерфейса, который вы ему предоставляете).
2 голосов
/ 14 апреля 2010

Вот 2 ссылки, которые объясняют, почему вы хотите это сделать:

http://www.artima.com/lejava/articles/designprinciples.html http://pragmaticjava.blogspot.com/2008/08/program-to-interface-not-implementation.html

Он не имеет ничего общего с производительностью выполнения (в большей степени с производительностью программиста (вас)) в том смысле, что вы отделяете пользователей класса от его реализации - в том числе для облегчения тестируемости и обслуживания.

Никаких других классов, реализующих этот интерфейс, наверняка не будет.

Может быть, не в этом году, но в следующем году возможно.

2 голосов
/ 14 апреля 2010

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

Тем не менее, есть некоторые причины для использования интерфейсов, даже если в настоящее время существует одна реализация. Возможно, будет проще расширить позже или предоставить альтернативные реализации. (Хотя в любой приличной IDE существует рефакторинг экстракта интерфейса.) Тестирование может быть намного проще: если вы хотите протестировать класс, который использует другие классы только через интерфейсы, вы можете легко предоставить фиктивные объекты для других классов. *

1 голос
/ 14 апреля 2010

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

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

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

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

0 голосов
/ 15 апреля 2010

Еще один способ неправильно использовать интерфейсы?

Нет очевидного прироста производительности при использовании интерфейсов. И наоборот, может оказать негативное влияние на производительность из-за RTTI (на основе возможностей вашего компилятора)

0 голосов
/ 14 апреля 2010

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

Не обращайте внимания на такую ​​ерунду.

0 голосов
/ 14 апреля 2010

Этот вопрос нацелен на C # , но я думаю, что он также применим. Ответ с наибольшим количеством голосов говорит, что определение интерфейса для каждого класса - это просто кодовый шум .

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