Лучшие практики для больших решений в Visual Studio (2008)

У нас есть решение с более чем 100 проектами, большинство из которых C#. Естественно, что и на открытие, и на сборку уходит много времени, поэтому я ищу лучшие практики для таких зверей. Вдоль строк вопросов, на которые я надеюсь получить ответы:

  • как вы лучше всего справляетесь со ссылками между проектами
    • должен ли "копировать локальный" быть включен или выключен?
  • должен ли каждый проект собираться в свою собственную папку, или все они должны собираться в одной выходной папке (все они являются частью одного и того же приложения)

  • Являются ли папки с решениями хорошим способом организации вещей?

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

12 ответов

Возможно, вас заинтересуют эти две статьи MSBuild, которые я написал.

MSBuild: лучшие практики для создания надежных сборок, часть 1

MSBuild: лучшие практики для создания надежных сборок, часть 2

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

Чтобы кратко ответить на ваши вопросы здесь, хотя:

  • CopyLocal? Наверняка выключите это
  • Создать одну или несколько выходных папок? Построить в одну выходную папку
  • Папки решения? Это вопрос вкуса.

Сказал Ибрагим Хашими

Моя книга: Внутри Microsoft Build Engine: Использование MSBuild и Team Foundation Build

+1 за щадящее использование папок решений, чтобы помочь организовать вещи.

+1 за сборку проекта в свою папку. Первоначально мы попробовали общую папку вывода, и это может привести к тонкому и болезненному нахождению устаревших ссылок.

FWIW, мы используем ссылки на проекты для решений, и хотя nuget, вероятно, является лучшим выбором в наши дни, мы обнаружили, что svn:externals хорошо работает для внутренних сборок сторонних производителей и (каркасного типа). Просто привыкните использовать конкретный номер ревизии вместо HEAD при обращении к svn:externals (виновен как обвиненный:)

Выгрузите проекты, которые вы не используете часто, и купите SSD. SSD не улучшает время компиляции, но Visual Studio становится в два раза быстрее открывать / закрывать / собирать.

У нас похожая проблема, так как мы имеем дело с 109 отдельными проектами. Чтобы ответить на оригинальные вопросы, основанные на нашем опыте:

1. Как вы лучше всего справляетесь со ссылками между проектами

Мы используем опцию контекстного меню "Добавить ссылку". Если выбран "проект", то зависимость добавляется в наш единственный глобальный файл решения по умолчанию.

2. Должен ли быть включен или отключен режим "Копировать локально"?

По нашему опыту. Дополнительное копирование просто увеличивает время сборки.

3. Должен ли каждый проект создавать свою собственную папку или все они должны создавать одну и ту же выходную папку (все они являются частью одного приложения)

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

4. Являются ли папки с решениями хорошим способом организации вещей?

Нет в нашем опыте. Структура папок одного человека - кошмар другого. Глубоко вложенные папки просто увеличивают время, необходимое для поиска чего-либо. У нас совершенно плоская структура, но имена наших файлов проектов, сборок и пространств имен совпадают.


Наш способ структурирования проектов основан на одном файле решения. Строительство это занимает много времени, даже если сами проекты не изменились. Чтобы помочь с этим, мы обычно создаем другой файл решения "текущий рабочий набор". Любые проекты, над которыми мы работаем, добавляются к этому. Время сборки значительно улучшилось, хотя мы столкнулись с одной проблемой: Intellisense не работает для типов, определенных в проектах, которых нет в текущем наборе.

Частичный пример схемы нашего решения:

\bin

OurStuff.SLN

OurStuff.App.Administrator
OurStuff.App.Common
OurStuff.App.Installer.Database
OurStuff.App.MediaPlayer
OurStuff.App.Operator
OurStuff.App.Service.Gateway
OurStuff.App.Service.CollectionStation
OurStuff.App.ServiceLocalLauncher
OurStuff.App.StackTester
OurStuff.Auditing
OurStuff.Data
OurStuff.Database
OurStuff.Database.Constants
OurStuff.Database.ObjectModel
OurStuff.Device
OurStuff.Device.Messaging
OurStuff.Diagnostics
...
[etc]

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

Что касается открытия и построения времени, это будет трудно исправить, не разбиваясь на более мелкие решения. Вы можете изучить распараллеливание сборки (google "Parallel MS Build", чтобы узнать, как это сделать и интегрировать в пользовательский интерфейс), чтобы улучшить скорость. Кроме того, посмотрите на дизайн и посмотрите, может ли помочь рефакторинг некоторых ваших проектов, который приведет к меньшему общему количеству.

С точки зрения облегчения боли при сборке, вы можете использовать опцию "Диспетчер конфигурации..." для сборок, чтобы включить или отключить сборку определенных проектов. У вас может быть "Project [n] Build", который может исключать определенные проекты и использовать его при нацеливании на конкретные проекты.

Что касается более 100 проектов, я знаю, что вы не хотите, чтобы вам задавали этот вопрос о преимуществах сокращения размера вашего решения, но я думаю, что у вас нет другого выбора, когда речь идет об ускорении времени загрузки (и использование памяти) devenv.

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

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

Заметка

Вышеуказанное работает для моих решений, которые обычно являются веб-приложениями, и у меня не было проблем со ссылками, но это возможно!

У нас похожая проблема. Мы решаем это, используя меньшие решения. У нас есть мастер решение, которое открывает все. Но перф. на это плохо. Итак, мы сегментируем небольшие решения по типу разработчика. Таким образом, разработчики БД имеют решение, которое загружает проекты, о которых они заботятся, и разработчики сервисов, и разработчики пользовательского интерфейса - это одно и то же. Редко, когда кто-то должен открыть все решение, чтобы получить то, что ему нужно делать изо дня в день. Это не панацея - у нее есть свои плюсы и минусы. См. "Модель с несколькими решениями" в этой статье (игнорируйте часть об использовании VSS:)

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

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

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

Я считаю, что это лучшая практика, потому что нет предела тому, насколько сложными могут быть общие усилия, когда вы разбиваете их физически таким образом. Объединение всех проектов в одно решение в конечном итоге достигнет верхнего предела.

Надеюсь, эта информация поможет.

У нас более 60 проектов, и мы не используем файлы решений. У нас есть смесь проектов C# и VB.Net. Производительность всегда была проблемой. Мы не работаем над всеми проектами одновременно. Каждый разработчик создает свои собственные файлы решений на основе проектов, над которыми они работают. Файлы решения не проверяются в нашей системе контроля версий.

Все проекты библиотеки классов будут создаваться в папку CommonBin в корне исходного каталога. Исполняемые файлы / веб-проекты создаются в отдельной папке.

Мы не используем ссылки на проекты, а используем ссылки на файлы из папки CommonBin. Я написал специальную задачу MSBuild, которая будет проверять проекты и определять порядок сборки.

Мы использовали это в течение нескольких лет и не имеем никаких жалоб.

Все это связано с вашим определением и мнением о том, что такое решение и проект. На мой взгляд, решение - это просто логическая группировка проектов, которые отвечают очень специфическим требованиям. Мы разрабатываем большое интранет-приложение. Каждое приложение в этой интрасети имеет свое собственное решение, которое также может содержать проекты для exes или windows-сервисов. И затем у нас есть централизованная структура с такими вещами, как базовые классы и помощники и httphandlers / httpmodules. Базовая структура довольно велика и используется всеми приложениями. Разделив таким образом множество решений, вы уменьшите количество проектов, необходимых для решения, так как большинство из них не имеют никакого отношения друг к другу.

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

Мой совет заключается в том, чтобы сделать это и разработать централизованную среду (если хотите, собственную реализацию Enterprise Library). Вы можете или GAC поделиться им, или вы можете напрямую ссылаться на местоположение файла, чтобы у вас было центральное хранилище. Вы можете использовать ту же тактику и для централизованных бизнес-объектов.

Если вы хотите напрямую ссылаться на библиотеку DLL, вы должны ссылаться на нее в своем проекте с помощью копии local false (где-то вроде c:\mycompany\bin\mycompany.dll). Во время выполнения вам нужно будет добавить некоторые настройки в ваш app.config или web.config, чтобы он ссылался на файл, отсутствующий в GAC или в корзине времени выполнения. В действительности, не имеет значения, является ли это копией локального или нет, или если dll попадает в корзину или даже находится в GAC, потому что конфигурация переопределит оба из них. Я думаю, что это плохая практика - копировать локально и иметь грязную систему. Скорее всего, вам придется временно скопировать local, если вам нужно отладить одну из этих сборок.

Вы можете прочитать мою статью о том, как использовать DLL в глобальном масштабе без GAC. Мне действительно не нравится GAC, потому что он предотвращает развертывание xcopy и не запускает автозапуск приложений.

http://nbaked.wordpress.com/2010/03/28/gac-alternative/

Установка CopyLocal=false сократит время сборки, но может вызвать различные проблемы во время развертывания.

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

Мой опыт установки CopyLocal=false не был успешным. См. За и против в моем сообщении в блоге "НЕ меняйте" Копировать локальные "ссылки на проект на false, если не понимаете подпоследовательности".

Другие вопросы по тегам