Архитектура N-Tier - Структура с несколькими проектами в VB.NET

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

У меня будут Приложение Windows и веб-приложение (уровни представления), они оба получат доступ к общему бизнес-слою. Бизнес-слой посмотрит на конфигурационный файл для нахождения названия dll (слой данных), на который это создаст ссылку во времени выполнения (действительно ли это - лучший подход?).

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

Проекты:

MyCompany.Common.dll - Содержит интерфейсы, все другие проекты имеют ссылку на этого.
MyCompany.Windows.dll - Проект Windows Forms, ссылки MyCompany.Business.dll
MyCompany.Web.dll - Проект веб-сайта, ссылки MyCompany.Business.dll
MyCompany.Busniess.dll - Бизнес-Слой, ссылки MyCompany. Данные.* (во времени выполнения)
Уровень MyCompany.Data.AccountingSys1.dll - Data для системы учета 1 уровень MyCompany.Data.AccountingSys2.dll - Data для системы учета 2

MyCompany.Common.dll проекта содержал бы все интерфейсы, друг друга, проект будет иметь ссылку на этого.

Public Interface ICompany
    ReadOnly Property Id() as Integer
    Property Name() as String
    Sub Save()
End Interface

Public Interface ICompanyFactory
    Function CreateCompany() as ICompany
End Interface

MyCompany.Data.AccountingSys1.dll проекта и MyCompany.Data.AccountingSys2.dll содержали бы классы как следующее:

Public Class Company
    Implements ICompany

    Protected _id As Integer
    Protected _name As String

    Public ReadOnly Property Id As Integer Implements MyCompany.Common.ICompany.Id
        Get
            Return _id
        End Get
    End Property

    Public Property Name As String Implements MyCompany.Common.ICompany.Name
        Get
            Return _name
        End Get
        Set(ByVal value as String)
            _name = value
        End Set
    End Property

    Public Sub Save() Implements MyCompany.Common.ICompany.Save
        Throw New NotImplementedException()
    End Sub

End Class

Public Class CompanyFactory
    Implements ICompanyFactory

    Public Function CreateCompany() As ICompany Implements MyCompany.Common.ICompanyFactory.CreateCompany
        Return New Company()
    End Function

End Class

MyCompany.Business.dll проекта предоставил бы бизнес-правила и получил бы форму данных слой данных:

Public Class Companies

    Public Shared Function CreateCompany() As ICompany
        Dim factory as New MyCompany.Data.CompanyFactory
        Return factory.CreateCompany()
    End Function    

End Class

Любые мнения/предложения значительно ценились бы.

7
задан Craig F 18 March 2010 в 01:08
поделиться

3 ответа

Несколько комментариев.

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

Я бы назвал ваши сборки по имени приложения, а также по названию компании. MyCompany.MyApplication.Business.dll предпочтительнее MyCompany.Business.dll . Тогда проще разделить приложения на части и повторно использовать код из нескольких приложений.

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

MyCompany.MyApplication.Windows-Contract.dll
MyCompany.MyApplication.Windows.dll

MyCompany.MyApplication.Web-Contract.dll
MyCompany.MyApplication.Web.dll

MyCompany.MyApplication.Business-Contract.dll
MyCompany.MyApplication.Business.dll

MyCompany.MyApplication.Data-Contract.dll
MyCompany.MyApplication.Data.AccountingSys1.dll
MyCompany.MyApplication.Data.AccountingSys2.dll

Из вашего описания видно, что сборки AccountingSys1 и AccountingSys2 имеют общий контракт, следовательно, только одна сборка контракта для двух сборок реализации.

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

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

Data.AccountingSys1
    Data-Contract

Data.AccountingSys2
    Data-Contract

Business
    Business-Contract
    Data-Contract

Windows
    Windows-Contract
    Business-Contract
    Data-Contract (maybe)

Web
    Web-Contract
    Business-Contract
    Data-Contract (maybe)

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

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

Если вы можете следовать всему вышеперечисленному, вам нужно будет реализовать какой-то подход с внедрением зависимостей, чтобы иметь возможность создавать экземпляры объектов из интерфейсов в сборках контрактов. Вы можете использовать существующую структуру DI или создать третий набор сборок * - Factory.dll , содержащих ваши фабричные методы.

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

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

5
ответ дан 7 December 2019 в 07:43
поделиться

Ваш общий подход хорош :)

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

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

1
ответ дан 7 December 2019 в 07:43
поделиться

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

1
ответ дан 7 December 2019 в 07:43
поделиться
Другие вопросы по тегам:

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