2013-10-11 4 views
2

При реализации шаблона репозитория в сочетании с инфраструктурой сущности, почему я вижу много примеров с использованием интерфейса для своего класса репозитория? Конкретным примером ссылки является here.Почему интерфейс используется при реализации шаблона репозитория с инфраструктурой сущностей?

В чем смысл интерфейса? Почему не просто класс? Будет ли действительно необходимо, чтобы более одного класса подписались на этот очень специфический интерфейс, например, для «Рабочих»?

ответ

5

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

public class EmployeeService 
{ 
    private readonly IEmployeeRepository employeeRepository; 

    public EmployeeService(IEmployeeRepository employeeRepository) 
    { 
     this.employeeRepository=employeeRepository; 
    } 

    public IEnumerable<Employee> GetAllEmployees() 
    { 
     IEnumerable<Employee> employeeList=this.employeeRepository.GetAll(); 
     //Optionally do some processing here 
     return employeeList; 
    } 
} 

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

  • Если вы хотите, чтобы написать тест автоматизированного блока для этого класса, вы можете дать ему поддельный реализацию IEmployeeRepository, который не пошел бы в реальную базу данных, но вместо этого возвращающего жёстко чтобы вы могли протестировать свой метод, не беспокоясь о БД на данный момент. Это называется «Mock» и часто является основной причиной размещения этого интерфейса. Есть также несколько библиотек, которые автоматизируют этот процесс, все полагаются на то, что они генерируют поддельный класс, реализующий интерфейс. Безусловно, это самая распространенная причина для создания такого интерфейса.
  • В какой-то момент вы можете решить, что хотите заменить инфраструктуру сущности чем-то другим или, скажем, захотеть реализовать репозиторий для чего-то другого, кроме реляционной БД. В этом случае вы должны написать другой репозиторий, реализующий тот же интерфейс, но делая что-то совершенно другое. Учитывая, что службы, использующие его , полагаются только на интерфейс, что код будет работать полностью немодифицирован, если соблюдается тот же контракт (конечно, код, который фактически создает репо и передает его службе, должен измениться, но это еще одна история). Таким образом, одна и та же служба работает одинаково независимо от того, где она считывает/сохраняет данные.
+1

Мой разум был достаточно раздутым на ночь. Спасибо. – Ryan

+0

Итак, что вы будете делать, когда вам нужны определенные методы, например, для репозитория учетной записи, который вы, возможно, захотите получить по имени? Используете ли вы предикаты в приложении «Где» или я специально добавляю для этого дополнительные функции без интерфейса? Я чувствую, что предоставление предикатов менее проверяемо. – Ryan

+1

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

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