1

я подслушал ниже и попросила подтвердить это заявление:SOLID/TDD поощряет один реализация для одного интерфейса

«SOLID/TDD поощряет один реализация для одного интерфейса, это не реальный мир, и идет вразрез с точкой интерфейсы не так ли? "

Я изначально согласился, что все онлайн-примеры TDD и DI следуют типичным примерам IRepository/MyRepository, где есть только одна реализация. После дальнейших размышлений я не согласился.

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

Я надеялся, что люди смогут мне помочь.

ОБНОВЛЕНИЕ: Хотя я понимаю концепции DI и модульного тестирования, то, что я пытаюсь показать, заключается в том, как мы можем иметь несколько классов в производстве, реализующих один интерфейс.

UPDATE2: Продумав простой пример, здесь возможно выполнение нескольких реализаций, однако оно по-прежнему не отвечает на то, что я хочу. Что делать, если у вас есть конструктор, который имел единую зависимость от ILogger или IDataProvider или ISomething:

public interface ILogger 
{ 
    void Write(string data); 
} 

public class FileLogger : ILogger 
{ 
    void Write(string data) 
    { 
    // 
    } 
} 

public class DBLogger : ILogger 
{ 
    void Write(string data) 
    { 
    // 
    } 
} 

public class EventViewerLogger : ILogger 
{ 
    void Write(string data) 
    { 
    // 
    } 
} 

public class Calculator 
{ 
    private IEnumberable<ILogger> loggers; 

    public Calculator(IEnumberable<ILogger> loggers) 
    { 
     this.loggers = loggers; 
    } 

    public int Add(int a, int b) 
    { 
     var result = a + b; 

     foreach(var logger in loggers) 
     { 
     logger.Write("Result was " + logger); 
     } 
    } 
} 
+0

по теме: http://stackoverflow.com/questions/5411648/how-to-deal-with-interface-overuse-in-tdd. При единичном тестировании в изоляции вы нередко оказываетесь в интерфейсе, который реализуется тестовым двойным и точно * одним * производственным классом. –

+0

для меня это совсем не вопрос, мы создаем интерфейсы, ожидая, что может быть несколько реализаций ... вот что делает ваше приложение более гибким ... Я действительно не понимаю, почему вы этого не докажете. ..bottom line даже если вы находитесь в TDD/SOLID ... Цель использования интерфейса - указать контракт и который может быть реализован несколькими классами ... вместо этого пытается доказать это ... спросите у человека, который спросил вы, чтобы доказать это, чтобы освежить его/ее навыки объектно-ориентированного программирования ... – NiK

ответ

4

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

+0

Согласен, сейчас я хотел бы, чтобы продемонстрировать, что авторам этого заявления – Jon

3

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

Хотя вы не писали насмешку, макет по-прежнему считается воплощением интерфейса для меня.


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

  • Вызывающий код не заботится сколько реализаций у вас есть -> он усиливает развязку
  • Вы единственная реализация сегодня, вы можете иметь еще один в будущем. (Я знаю, это слабый аргумент, учитывая YAGNI).
  • Тестирование имеют свою фиктивной реализацию
  • изменения реализация, как создание другого один. У вас многократная реализация, но не в одно и то же время. => улучшает ремонтопригодность.

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

+0

Истинного но не в производстве. Я хотел бы продемонстрировать несколько реализаций одного интерфейса в производстве с помощью DI – Jon

+0

Не раздувайте свой код с ненужными интерфейсами. См. Http://stackoverflow.com/questions/90851/is-creating-interfacesfor-almost-every-class-justified-or-are-interfaces-overus. В частности, из http://martinfowler.com/bliki/InterfaceImplementationPair.html Использование интерфейсов, когда вы не будете иметь несколько реализаций это дополнительные усилия, чтобы держать все в sync.Furthermore скрывает случаи, когда вы на самом деле обеспечивают многократный реализации. –

+0

@ Майкл: Я частично согласен. Написание большего количества кода, чем необходимо, всегда плохо. «Необходимый» всегда зависит от размера и сложности проекта. В крупном и быстро меняющемся проекте, над которым я работаю, мы сэкономили много времени из-за интерфейсов, которые не были очевидной выгодой, когда мы его написали. В последние годы я начал использовать интерфейсы еще больше. Интерфейсы не должны раздуваться. Они должны быть маленькими, делая вещи более ясными и развязывая части программного обеспечения друг от друга. –

0

Итак, вы ищете пример интерфейса, который имеет несколько реализаций и используется в производственной среде?

JDBC - Oracle, MySql, любая другая база данных имеет свою собственную реализацию интерфейсов JDBC

JPA - см JPA Implementations - Which one is the best to use? для списка реализаций интерфейса (ов)

или вы ищете что-то другое ?

+0

Просто простая демонстрация действительно. Возможно, ILogger с FileLogger, DBLogger, EventViewerLogger. Однако не знаю, как все 3 может быть использована в одном приложении – Jon

+0

@ Джон просто войти все в файл (работает даже тогда, когда DB не доступен), но войти серьезные ошибки в БД для облегчения анализа и регистрировать все ошибки в eventviewerlog так, что бы быть самым простым вариантом, чтобы иметь решение для мониторинга мониторинга системы ... – Yahia

2

SOLID не способствует отображению 1-1 между интерфейсами и классами.

Сегментация интерфейса наиболее близка к интерфейсам, которые мы получаем. Но в нем говорится, что вы должны создавать как можно более конкретные интерфейсы. A IUserRepository может быть отключен до IUserStorage (CRUD) и IUserQueries (поиск). UserRepository, вероятно, будут реализовываться как с начала, так и позже. Самое замечательное в том, что вы можете создать кэшированную реализацию (узор декоратора) с небольшим усилием или использовать разные источники данных для писем и чтений (CQRS).

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

Проблема в том, что все просто думают о типичной бизнес-логике при обсуждении SOLID. Но мы все запускаем код в разных рамках, что принесет огромную пользу, если бы SOLID был применен.

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

1

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

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

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

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

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

+0

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

+0

Прочтите еще раз. Я никогда не говорил, что Стефан ошибался. Позиция Стефана заключается в том, что интерфейсы не бесполезны, потому что они используются в тестах. Моя позиция очень похожа, тесты являются первыми потребителями вашего кода. На вершине позиции Стефана моя точка зрения - SOLID, поощряет абстракции (а не только интерфейсы C#), и абстракции хороши. – bryanbcook

+0

IMHO, позиция Стефана заключается в том, что интерфейсы должны использоваться ВСЕГДА, даже если было бы проще использовать виртуальные методы. –

0

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

Смежные вопросы