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

87

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

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

  • Папки решений - хороший способ систематизировать вещи?

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

Эйвинд
источник
2
Могу я спросить, зачем для одного решения более 100 проектов? Создают ли каждый свою собственную сборку?
Нил Н,
1
Да, они есть, и каждый из них представляет собой логически отдельную функциональность.
Эйвинд,
2
@Eyvind - Разве не для этого нужны классы и пространства имен? Какая польза от отдельных сборок? Я могу думать о некоторых, таких как потенциально небольшие обновления и использование памяти (если некоторые из них не загружены), но, безусловно, наличие 100+ сборок для компиляции и управления.
si618
1
@ Марк, я чувствую твою боль. У нас здесь до 94 проектов. Сейчас ничего не поделаешь, так как нам пришлось бы остановить разработку нескольких команд для реструктуризации. У нас есть 3 EXE-проекта, которые ссылаются на другой 91. Я экспериментирую с одной общей выходной папкой, пока результаты очень впечатляющие.
Кевин
2
Мужчина, 100+? Это ничего не значит для того, что у нас есть ... сейчас здесь почти 600 ...
Си Джонсон

Ответы:

41

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

MSBuild: Рекомендации по созданию надежных сборок, часть 1

MSBuild: Рекомендации по созданию надежных сборок, часть 2

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

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

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

Сайед Ибрагим Хашими

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

Сайед Ибрагим Хашими
источник
Спасибо, чувак, я обязательно их посмотрю!
Эйвинд,
1
Я скажу, что у меня есть эта книга, и она потрясающая. Это очень помогло мне автоматизировать мои сборки TFS и сборки для локальных разработчиков. Сейчас я работаю над инкрементными сборками, и книга очень глубоко затрагивает эту тему. Того стоит. Спасибо сказал. Продолжайте в том же духе.
irperez 08
Спасибо irperez за комментарии
Саид Ибрагим Хашими
2
-1 за НЕОБЫЧНУЮ рекомендацию отключить CopyLocal. Установка CopyLocal = false может вызвать различные проблемы во время развертывания. См. Мое сообщение в блоге «НЕ меняйте« Копировать локальные »ссылки проекта на ложные, если не понимаете подпоследовательности.» ( Geekswithblogs.net/mnf/archive/2012/12/09/… )
Майкл Фрейдгейм
Может ли "сборка в одну выходную папку" вызвать проблемы при компиляции с несколькими потоками?
BrunoLM
9

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

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

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

si618
источник
2
+1 У меня тоже проблемы с решением для общей выходной папки. Я не понял, что означает «ссылки на проекты для решений», объясните, пожалуйста, еще немного ...
Маурисио Шеффер,
Как и в случае, мы используем VS-> Добавить ссылку-> Проекты вместо VS-> Добавить ссылку-> Обзор. Мелочь, я знаю, но некоторые люди делают это по-другому (и я думаю, что это вызывает больше головной боли). Если вы посмотрите на текст MSBuild csproj, вы увидите свойство ProjectReference вместо Reference.
si618
Интересный ответ! Думаю, мы продвинулись туда же, куда и вы. У нас вообще нет папок решений, и мы полагаемся на именование проектов (проекты называются так же, как и пространство имен). Все наши выходные данные помещаются в единую папку, что делает настройку разработчика намного ближе к настройке развертывания. Если зависимости установлены правильно, то у нас нет устаревших ссылок.
Томас Братт
да, общий выходной каталог вызывает много проблем, особенно при использовании resharper. Действительно устаревшие ссылки.
Флориан Дойон,
1
@Kevin, прошло несколько лет, но по памяти один пример - это два проекта, ссылающихся на одну и ту же сборку, скажем, внешнюю библиотеку, на которую нет ссылки на проект. Все в порядке, если они используют одну и ту же версию, но затем выходит новый выпуск этой библиотеки, но только один проект обновляет их ссылку, какая версия используется в общей выходной папке?
si618
8

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

Николя Дорье
источник
3
Стоит отметить, что выгрузка проекта является индивидуальной настройкой для каждого пользователя, поэтому разработчики в вашей команде могут загружать только те проекты, которые им интересны. Это действительно помогло нашей команде.
Страница
Вы можете использовать расширение Solution Load Manager visualstudiogallery.msdn.microsoft.com/…, чтобы определить, что не загружать по умолчанию
Майкл Фрейдгейм,
6

У нас похожая проблема, ведь нам нужно заниматься 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]
Томас Братт
источник
Может ли "сборка в одну выходную папку" вызвать проблемы при компиляции с несколькими потоками?
BrunoLM
4

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

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

Дэвид М
источник
3

Что касается облегчения сборки, вы можете использовать параметр «Configuration Manager ...» для сборок, чтобы включить или отключить сборку определенных проектов. У вас может быть «Project [n] Build», который может исключать определенные проекты и использовать его, когда вы ориентируетесь на определенные проекты.

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

Майкл Медоуз
источник
Хм, это было отвергнуто за ошибку или просто за несогласие? Я могу жить с первым, если вы скажете мне, почему.
Майкл Медоуз,
Согласен, мне не нравится голосование против без комментариев, так что Майкл, ты получаешь мой +1, чтобы сбалансировать уравнение ;-)
si618
2
Кстати, мне лично не нравится возиться с управлением конфигурациями для подобных вещей. Зачем? потому что, если вы случайно зафиксируете измененную конфигурацию, это затронет ваш сервер сборки или других разработчиков.
si618
Согласовано. Собственно, та же проблема возникает и с решениями со слишком большим количеством проектов. :)
Майкл Медоуз
3

То, что я обычно делаю с этим, немного зависит от того, как на самом деле происходит процесс «отладки». Хотя обычно я НЕ устанавливаю значение copy local как истинное. Я настраиваю каталог сборки для каждого проекта, чтобы выводить все в желаемую конечную точку.

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

Заметка

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

Митчел Селлерс
источник
3

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

JP Alioto
источник
2

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

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

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

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

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

Блейк Тейлор
источник
2

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

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

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

Мы пользуемся этим уже несколько лет и нареканий не имеем.

Васу Балакришнан
источник
3
Не могли бы вы поделиться своей настраиваемой задачей msbuild?
andreapier
0

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

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

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

Если вы хотите напрямую ссылаться на DLL, вам нужно будет ссылаться на нее в своем проекте с помощью copy 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/

user306031
источник
0

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

Есть много сценариев, когда вам нужно, чтобы Copy Local оставалось равным True, например, проекты верхнего уровня, зависимости второго уровня, библиотеки DLL, вызываемые отражением.

Мой опыт установки CopyLocal = false не увенчался успехом. См. Сводку «за» и «против» в моем сообщении в блоге «НЕ меняйте ссылки проекта« Копировать локальные »на ложные, если не понимаете подпоследовательности».

Майкл Фрейджейм
источник