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

На python2.6

Я предполагаю, что вы ожидаете, что блок finally будет связан с блоком «try», где вы вызываете исключение «B». Блок finally присоединяется к первому блоку try.

Если вы добавили блок исключений во внутренний блок try, то блок finally вызовет исключение B.

try:
  raise Exception("a")
except:
  try:
    raise Exception("b")
  except:
    pass
  finally:
    raise

Вывод:

Traceback (most recent call last):
  File "test.py", line 5, in <module>
    raise Exception("b")
Exception: b

Еще один вариант, объясняющий, что здесь происходит

try:
  raise Exception("a")
except:
  try:
    raise Exception("b")
  except:
    raise

Вывод:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    raise Exception("b")
Exception: b

Если вы видите здесь, заменив Блок finally с исключением вызывает исключение B.

22
задан Dan Rayson 27 November 2018 в 16:33
поделиться

24 ответа

Если бы я знал, что когда-либо будет только одна реализация, я бы не создавал интерфейс. Это подпадает под ЯГНИ, ИМО.

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

28
ответ дан 29 November 2019 в 03:23
поделиться

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

-2
ответ дан 29 November 2019 в 03:23
поделиться

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

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

0
ответ дан 29 November 2019 в 03:23
поделиться

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

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

0
ответ дан 29 November 2019 в 03:23
поделиться

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

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

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

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

0
ответ дан 29 November 2019 в 03:23
поделиться

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

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

0
ответ дан 29 November 2019 в 03:23
поделиться

Я предпочитаю не определять интерфейс, если он мне действительно не нужен. ИМО, интерфейс - один из наиболее часто используемых шаблонов проектирования. Я думаю, что случай, о котором вы говорите, связан с вопросом «А что, если ... понадобится в будущем?». Поскольку разработчик еще не гадалка ... Я бы придерживался "недоиспользования" интерфейса.

0
ответ дан 29 November 2019 в 03:23
поделиться

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

ДОПОЛНЕНИЕ Прочитав некоторые комментарии: Имитация объекта: это будет означать, что у вас БУДЕТ иметь более одной реализации вашего интерфейса, yoru mock - это другая реализация.

0
ответ дан 29 November 2019 в 03:23
поделиться

Да, особенно с помощью Delphi.

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

1
ответ дан 29 November 2019 в 03:23
поделиться

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

0
ответ дан 29 November 2019 в 03:23
поделиться

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

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

1
ответ дан 29 November 2019 в 03:23
поделиться

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

Это не всегда может быть достигнуто с общедоступным / защищенным / частным.

1
ответ дан 29 November 2019 в 03:23
поделиться

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


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

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, я просто передаю реализация напрямую вместо этого.


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

2
ответ дан 29 November 2019 в 03:23
поделиться

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

Так что да, ЯГНИ - не усложняй себе жизнь, пока это не понадобится.

3
ответ дан 29 November 2019 в 03:23
поделиться

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

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

2
ответ дан 29 November 2019 в 03:23
поделиться

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

3
ответ дан 29 November 2019 в 03:23
поделиться

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

3
ответ дан 29 November 2019 в 03:23
поделиться

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

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

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

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

4
ответ дан 29 November 2019 в 03:23
поделиться

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

Тем не менее, широкое применение может быть следующим:

  1. Заполнитель для будущих расширений / улучшений

  2. Простота реализации Инверсия управления / внедрения зависимостей

  3. Простота реализации имитаций для модульного тестирования.

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

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

4
ответ дан 29 November 2019 в 03:23
поделиться

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

8
ответ дан 29 November 2019 в 03:23
поделиться

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

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

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

10
ответ дан 29 November 2019 в 03:23
поделиться

When I work with someone else on a project, for instance if I do the front end (Web application for instance) and the other person does all the database work, we start by writing an API. The side that faces me is all about the problem domain: classes for User, Administrator, Employee, SKU or whatever. Then we can work independently; she implements all the interfaces and I write the code that uses them.

1
ответ дан 29 November 2019 в 03:23
поделиться

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

22
ответ дан 29 November 2019 в 03:23
поделиться

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

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

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

0
ответ дан 29 November 2019 в 03:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: