Несколько комментариев.
Я бы избегал сборки 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
сборок, которые содержат ваши фабричные методы.
Еще одним преимуществом такой структуры является то, что модульное тестирование намного проще и может основываться на контрактах, а не на реализации, что помогает вам писать чистый, тестируемый код.
Это может показаться большим количеством сборок, но преимущества, которые вы получаете, не давая своему коду создавать неприятные зависимости, значительно снизят вероятность того, что ваш проект станет слишком сложным, и помогут добиться хорошего качества в процессе работы. Небольшая боль теперь устранит такую боль позже.