Насмешки носорога, введение зависимости и разделение проблем - PullRequest
3 голосов
/ 19 марта 2010

Я новичок в издевательстве и внедрении зависимостей, и мне нужно руководство.

Мое приложение использует типичную N-уровневую архитектуру, в которой BLL ссылается на DAL, а пользовательский интерфейс ссылается на BLL, но не на DAL. Довольно прямо вперед.

Допустим, например, у меня есть следующие классы:

class MyDataAccess : IMyDataAccess {}
class MyBusinessLogic {}

Каждый существует в отдельной сборке.

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

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

Одним из возможных решений, с которым я играю, является создание внутреннего конструктора для MyBusinessLogic с параметром IMyDataAccess. Затем я могу использовать Accessor из тестового проекта для вызова конструктора. Но все еще есть этот запах.

Какое общее решение здесь. Я просто должен делать что-то не так. Как я могу улучшить архитектуру?

Ответы [ 3 ]

4 голосов
/ 19 марта 2010

Вы можете определить свои классы так:

public class MainForm : Form
{
    private readonly businessLogic;

    public MainForm(IBusinessLogic businessLogic)
    {
        this.businessLogic = businessLogic;
    }
}

public class BusinessLogic : IBusinessLogic
{
    private IDataLayer dataLayer;

    public BusinessLogic(IDataLayer dataLayer)
    {
        this.dataLayer = dataLayer;
    }
}

public class DataLayer : IDataLayer
{
    public DataLayer(string connectionString)
    {
    }
}

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

public static void Main(string[] args)
{
   var dataLayer = new DataLayer("foo");
   var businessLogic = new BusinessLogic(dataLayer);
   var mainForm = new MainForm(businessLogic);

   Application.Run(mainForm);
}

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

Примеры структур внедрения зависимостей для .NET: AutoFac , Castle , Spring.NET , StructureMap , Ninject и Managed Extensibility Framework .

2 голосов
/ 19 марта 2010

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

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

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

Надеюсь, это поможет.

0 голосов
/ 19 марта 2010

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

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