Подтвердить что ты не робот

Бесполезные интерфейсы

Зачем вам когда-либо использовать интерфейс, у вас будет только одна его реализация?

4b9b3361

Ответ 1

Если бы я знал, что будет только одна реализация, я бы не создал интерфейс. Это относится к YAGNI, IMO.

(Конечно, редко я знаю что-то о будущем для факта...)

Ответ 2

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

Ответ 3

Очень хорошая практика - установить interface как спецификацию для кода class на.

Если вы определяете общедоступные методы/функциональные возможности, которые ваш interface будет иметь, вы можете заблокировать это на месте. Тогда становится легче кодировать class, когда у вас есть четкая функциональность.

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

Ответ 4

Потому что они пропускают файлы заголовков С++?

Ответ 5

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

Однако большое использование будет:

  • Заместитель будущего расширения/улучшений

  • Легко реализовать инверсию инъекции управления/зависимостей

  • Легко реализовать mocks для модульного тестирования.

* Редактирование:

Я заметил, что у вас есть Spring в ваших тегах. Если использовать Spring, то # 2 выше, вероятно, является biggie. Его проще разрабатывать классы, которые ожидают интерфейсы, и вы можете поменять фактические реализации интерфейса в конфигурации Spring (Injection Dependency).

Ответ 6

Если действительно существует одна реализация и только когда-либо будет одной реализацией, не кодируйте интерфейс. (YAGNI).

Тем не менее, в 99% случаев существует как минимум две реализации класса, один реальный, один, используемый в тестировании.

Легкость разделения и издевательств частей системы во время тестирования более чем стоит дополнительных усилий по созданию интерфейса для одного класса.

Как побочная заметка, и, возможно, это связано только с тем, что мне не хватает самоконтроля, кодирование против интерфейсов меня намного больше фокусирует, когда я работаю над определенным классом. Я нахожу, что больше думаю о себе, и этот интерфейс, который я вызываю, вернет/сделает это ", а не" и этот класс, я работаю так, он вызывает х, преобразует y, общается с z, ставит кофе, пушит подушки, интегрирует n по отношению к y, а затем возвращает экземпляр обезьяны... подождите, что я делал снова? "

Ответ 7

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

Ответ 8

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

Ответ 9

Если у вас будет только одна реализация, я бы этого не сделал. Приведенные здесь аргументы о том, что у вас могут быть несколько реализаций, действительно не выдерживают тщательного изучения. Если вы закончите с несколькими реализациями, для извлечения интерфейса требуется около 5 секунд, используя либо встроенные инструменты Visual Studio, либо Resharper.

Итак, да, YAGNI - не усложняйте свою жизнь, пока вам не придется.

Ответ 10

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

Если реализация изменится, а "контракт", определенный в интерфейсе, не будет, вы будете счастливы: ваш интерфейс все еще описывает, что делает класс, и никто не должен знать, как он это делает.

Ответ 11

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


Интерфейсы с одним методом для передачи фрагментов логики реализации:

public interface IComparable<T>
{
    int CompareTo(T first, T second);
}

public static class Array<T>
{
    public void Sort(T[] input)
    {
        if (T is IComparable) { /* sorting implementation */ }
        else { Throw new Exception("Doesn't implement IComparable"); }
    }
}

Можно заменить на:

public static class Array<T>
{
    public void Sort(T[] input, Func<T, T, int> compare)
    {
        /* sorting implementation */
    }
}

Я считаю функциональный стиль более читаемым и многоразовым.


Интерфейсы с одним методом для зависимостей-инъекций/издевательств:

public interface IFailureNotifier
{
    void HandleFailure(Exception ex);
}

public class TransactionProcessor
{
    public IFailureNotifier FailureNotifier { get; set; }

    public TransactionProcessor(IFailureNotifier failureNotifier)
    {
        this.FailureNotifier = failureNotifier;
    }

    public void ProcessItems(object[] items)
    {
        try
        {
            for(object item in items) { /* do stuff */ }
        }
        catch(Exception ex)
        {
            FailureNotifier.HandleFailure(ex);
        }
    }
}

Можно переписать как:

public class TransactionProcessor
{
    public Action<Exception> FailureNotifier { get; set; }

    public TransactionProcessor(Action<Exception> failureNotifier)
    {
        this.FailureNotifier = failureNotifier;
    }

    public void ProcessItems(object[] items)
    {
        try
        {
            for(object item in items) { /* do stuff */ }
        }
        catch(Exception ex)
        {
            FailureNotifier(ex);
        }
    }
}

Преимущество этого подхода - более простая библиотека классов: мне не нужен суп из крошечных объектов для реализации единственного метода IFailureNotifier, я просто передаю реализацию напрямую.


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

Ответ 12

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

Это не всегда может быть достигнуто с помощью public/protected/private.

Ответ 13

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

Ответ 14

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

Объекты Value должны редко становиться интерфейсами, объекты обслуживания должны часто становиться интерфейсами.

Ответ 15

Да, особенно с Delphi.

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

Ответ 16

потому что у вас может быть два или более в будущем

Сложение После прочтения некоторых комментариев: Объект mocking: это означало бы, что у вас будет более одной реализации вашего интерфейса, yoru mock - это еще одна реализация.

Ответ 17

Возможность дальнейшего расширения в будущем.

Ответ 18

Я предпочитаю не определять интерфейс, если мне это не нужно. Интерфейс IMO является одним из самых злоупотребляемых шаблонов проектирования. Я думаю, что дело, о котором вы говорите, связано с вопросом: "Что, если... понадобится в будущем?". Поскольку разработчик еще не гадалка... Я бы придерживался интерфейса "недоиспользования".

Ответ 19

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

Одним из примеров того, где эта практика особенно полезна, является Spring подход на основе прокси-сервера, где ваша единственная реализация находится в разные JVM.

Ответ 20

В ряде других ответов упоминается "работа с другими", и это, безусловно, вызывает озабоченность. Проект с 10 программистами должен будет приближаться к вещам иначе, чем проект с одним, и, к сожалению, излагать архитектуру программного обеспечения таким образом, чтобы несколько людей могли вносить свой вклад в это, что-то, что люди, кажется, всегда усваивают трудный путь.

Кто-нибудь может предложить хорошие книги или статьи?

Ответ 21

Я часто делаю это и по нескольким причинам:

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

2) Он также обрезает список, предоставляемый через intellisense, только функциям, поддерживаемым интерфейсом.

3) И, как указано выше, это полезно для модульного тестирования и издевательских фреймворков.

Ответ 22

Одна ситуация для интерфейса только для одной реализации: RMI. У вас есть объект в одном приложении и будет использовать его из другого приложения через RMI; вам нужен интерфейс. Таким образом, вам даже не нужно включать класс реализации в вызывающее приложение, которое может спасти вызывающее приложение от включения пута J2EE-материала или внешних библиотек, которые могут использовать реализация.

Другая причина: сегодня у вас есть только одна реализация, но завтра может быть что-то в JDK или внешняя библиотека, которая может привести к изменению этой реализации (возможно, создание новой). Ваша система может измениться, и вам нужно добавить новую реализацию, сохранив старую версию; некоторое обслуживание и т.д.

Ответ 23

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

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

Я понимаю, что аналогичные типы абстракций уже существуют в .NET framework, но я решил, что это был подходящий пример.

Ответ 24

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

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

Ответ 25

потому что интерфейс лучше всего подходит для окончательного указания типа