Управление и структура растущего .NET проекта - PullRequest
9 голосов
/ 21 июня 2011

Мы создаем программную платформу .NET для автоматизации тестирования в нашей компании.

Приложение состоит из компонента GUI (WinForms) и различных «действий», которые динамически загружаются в него для выполнения.

Уже идет примерно 100 проектов действий, и это число увеличивается. Некоторые из этих проектов взаимозависимы с другими проектами и т. Д.

Все загруженные действия должны ссылаться на нашу dll «SDK» для различных действий (результаты для основного приложения, ведение журнала и т. Д.).

С этим относительно простым дизайном мы сталкиваемся с некоторыми управленческими решениями, которые мы хотели бы решить наилучшим образом:

  1. Должны ли действия ("плагины") ссылаться на выходные данные нашего проекта SDK или какую-либо известную стабильную версию? Например, при разработке большого приложения (например, MS Office) не все команды, естественно, работают с исходным кодом для всех компонентов.

Какое лучшее решение для чего-то подобного? а почему?

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

Каковы общие практики в сценариях, где управление множеством проектов, которые связаны между собой? Есть ли какие-либо советы для этого?

Ответы [ 2 ]

2 голосов
/ 21 июня 2011

Это проблема, которая не имеет четкого ответа, но ...

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

Для сильно связанной системы я могу предложить два каталога для двоичных файлов: сторонний каталог и каталог, в котором находятся библиотеки DLL, которые ваша компания создает, на которые могут ссылаться другие разработчики.Сторонние библиотеки DLL (за пределами вашей компании) должны находиться в системе контроля версий, чтобы все разработчики ссылались на одни и те же версии сторонних библиотек DLL из одного и того же местоположения, что позволяет избежать несоответствий машины разработчика и проблем с установкой стороннего программного обеспечения на каждую машину.На внутренние библиотеки DLL нельзя ссылаться в системе контроля версий, и они должны быть собраны на каждом компьютере разработчика с помощью автоматизированного пакетного файла сборки или подобного.На шаге пост сборки вы можете скопировать их все в один и тот же каталог, и пока разработчики получают последние версии системы управления версиями и сборки, у всех есть одинаковые DLL из вашей компании.

Например, получить последнюю версию, сборку(используя пакетный файл для сборки всех необходимых проектов), а затем в качестве шага после сборки скопируйте вывод в общий.Теперь все ваши другие проекты могут ссылаться на обычные DLL-библиотеки Compnay и сторонние DLL-библиотеки из одного и того же местоположения, и все они согласованы.

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

В слабосвязанной системе используется такая структура, как MEF (Managed Extensibility Framework), и ваши компоненты ссылаются на "Contract DLL", которая определяет интерфейсы для ваших компонентов.Проект ссылается на интерфейсные или контрактные библиотеки DLL и на самом деле не заботится о реализации, а затем MEF управляет плагином для вас.

В этом случае вы ссылаетесь на интерфейсную библиотеку DLL, а не на реальную библиотеку DLL, которая ее реализует.

Например, скажем, у меня есть интерфейс ILog с методом LogMessage.

private ILog _logger;
_logger.LogMessage();

Итак, в сильно связанном случае: Action.DLL напрямую ссылается на Logger.DLL.

В слабосвязанном случае Action.DLL ссылается на ILog.DLL (только интерфейс).Logger.DLL реализует ILog.DLL.Но Action.DLL не имеет прямой ссылки на Logger.DLL.

Теперь я могу иметь любое количество библиотек DLL, которые влияют на интерфейс ILog, но Action.DLL не ссылается на них напрямую.Это довольно круто, и одна из самых захватывающих функций MEF и слабой связи в целом - способность не иметь зависимостей.

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

У меня не было бы одной крупной контрактной DLL, я бы попытался разбить интерфейсы на логические группировки.Например, ведение журнала выглядит как интерфейс служебной программы Utility, поэтому я хотел бы создать DLL-библиотеку контрактов Utility с интерфейсом ILog.Как это разделить, зависит от того, что вы пытаетесь сделать.Или каждый интерфейс может быть контрактной DLL, но, возможно, это немного экстремально.

1 голос
/ 21 июня 2011

Это довольно сложная тема, особенно в области .NET.Я не знаю о «лучшем» решении, но я объясню, как нам это удается;возможно, вам это пригодится.

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

Первое: физическая структура (мы используем SVN).

  • Для каждого проекта существует корень управления исходным кодом
  • У каждого проекта есть свои собственные ствол, ветви и теги
  • Папка стволов имеет версионные папки \ src и \ build и неверсионную папку \ lib Папка \ lib содержит двоичные файлы для ссылки.Этими двоичными файлами могут быть сторонние библиотеки или другие проекты, на которые вам нужно связать (например, ваш SDK).Все двоичные файлы в каталоге \ lib поступают из корпоративного хранилища плюща (см. http://ant.apache.org/ivy/).. В эти дни в среде .NET наблюдается большое движение относительно NuGet , так что вы также можете проверить это.

Ваша папка versioned \ build содержит сценарии сборки, например, для получения бинарных файлов из ivy, публикации вашего проекта в ivy или компиляции каждого проекта. Они также пригодятся, если вы хотите указать сервер Continuous Integrationв каждом из ваших проектов.

Второе: чтобы определить, откуда берутся зависимости

Ответ: Они приходят из вашего репозитория ivy (это может быть так же просто, как сетевой файловой системой с общим доступом).создал свой репозиторий, так что вы можете контролировать его содержимое. Будьте очень осторожны с бинарными файлами сторонних производителей, которые устанавливаются в GAC. Visual Studio - трудная задача в ^^, чтобы справиться с этим.

В частности:

Как правильно проверить, что все необходимые зависимости (например, сторонние библиотеки) действительно взяты изrrect location?

Ivy дает вам большую гибкость с зависимостями, а также разрешает транзитивные зависимости;Например, вы можете зависеть от SDK rev = "1. +" status = "latest.release", который будет означать "последний стабильный релиз SDK 1.x, или от SDK rev =" 2. + "status =" latest.«Интеграция», что будет означать последний доступный двоичный файл 2.x SDK (вероятно, созданный в результате непрерывной интеграции).

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

Это также означает, что объем кода в ваших проектах останется настолько малым, насколько вам понадобится работоспособная Visual StudioЭто также означает, что инструменты рефакторинга, такие как ReSharper, будут намного менее полезными. Также будет определенная сложность в отношении ваших сценариев сборки и стратегии ветвления. Это во многом зависит от логики ваших компонентов.

Это краткий обзор, если вы думаете, что вы хотите именно этого, я могу расширить ответ. Хорошоудачи;экосистема .NET, и в частности Visual Studio, на самом деле не работают так.

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