У нас есть решение с более чем 100 проектами, большинство из которых на C #. Естественно, что и открытие, и сборка занимают много времени, поэтому я ищу лучшие практики для таких зверей. Я надеюсь получить ответы на следующие вопросы:
- как вы лучше всего обрабатываете ссылки между проектами
- должно быть включено или выключено "копировать локально"?
должен ли каждый проект строиться в своей собственной папке или все они должны строиться в одной выходной папке (все они являются частью одного приложения)
Папки решений - хороший способ систематизировать вещи?
Я знаю, что разделение решения на несколько меньших решений - это вариант, но он сопровождается собственным набором проблем рефакторинга и построения, поэтому, возможно, мы можем сохранить это для отдельного потока :-)
Ответы:
Возможно, вас заинтересуют эти две написанные мной статьи о MSBuild.
MSBuild: Рекомендации по созданию надежных сборок, часть 1
MSBuild: Рекомендации по созданию надежных сборок, часть 2
В частности, в Части 2 есть раздел Создание больших деревьев исходных текстов, на который вы, возможно, захотите взглянуть.
Чтобы кратко ответить на ваши вопросы здесь:
Сайед Ибрагим Хашими
Моя книга: Внутри 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]
источник
Здесь мы работаем над аналогичным крупным проектом. Папки решений зарекомендовали себя как хороший способ организации вещей, и мы склонны просто оставлять для параметра copy local значение true. Каждый проект собирается в свою собственную папку, и тогда мы знаем, что для каждого развертываемого проекта в ней у нас есть правильное подмножество двоичных файлов.
Что касается открытия времени и построения времени, это будет трудно исправить, не разбиваясь на более мелкие решения. Вы можете изучить распараллеливание сборки (Google "Parallel MS Build", чтобы узнать, как это сделать и интегрировать в пользовательский интерфейс), чтобы повысить скорость здесь. Кроме того, посмотрите на дизайн и посмотрите, может ли помочь рефакторинг некоторых ваших проектов, который приведет к меньшему количеству в целом.
источник
Что касается облегчения сборки, вы можете использовать параметр «Configuration Manager ...» для сборок, чтобы включить или отключить сборку определенных проектов. У вас может быть «Project [n] Build», который может исключать определенные проекты и использовать его, когда вы ориентируетесь на определенные проекты.
Что касается более 100 проектов, я знаю, что вы не хотите задаваться вопросом о преимуществах сокращения размера вашего решения, но я думаю, что у вас нет другого варианта, когда дело доходит до ускорения времени загрузки (и использование памяти) devenv.
источник
То, что я обычно делаю с этим, немного зависит от того, как на самом деле происходит процесс «отладки». Хотя обычно я НЕ устанавливаю значение copy local как истинное. Я настраиваю каталог сборки для каждого проекта, чтобы выводить все в желаемую конечную точку.
Поэтому после каждой сборки у меня есть заполненная папка со всеми DLL и любыми окнами / веб-приложениями, и все элементы находятся в нужном месте. Копировать локально не понадобилось, так как в конце концов DLL окажется в нужном месте.
Заметка
Вышеупомянутое работает для моих решений, которые обычно представляют собой веб-приложения, и у меня не было проблем со ссылками, но это возможно!
источник
У нас похожая проблема. Мы решаем это, используя меньшие решения. У нас есть универсальное решение, открывающее все. Но перф. на этом плохо. Итак, мы сегментируем более мелкие решения по типу разработчика. Итак, у разработчиков БД есть решение, которое загружает интересующие их проекты, а разработчики сервисов и разработчики пользовательского интерфейса - то же самое. Редко, когда кому-то приходится открывать все решение, чтобы делать то, что им нужно, на повседневной основе. Это не панацея - у нее есть свои плюсы и минусы. См. «Модель с несколькими решениями» в этой статье (не обращайте внимания на часть об использовании VSS :)
источник
Я думаю, что с такими большими решениями лучше всего их разбивать. Вы можете думать о «решении» как о месте, где можно собрать вместе необходимые проекты и, возможно, другие части для работы над решением проблемы. Разбив более 100 проектов на несколько решений, специализирующихся на разработке решений только для части общей проблемы, вы можете справиться с меньшими затратами в определенный момент времени, ускорив взаимодействие с необходимыми проектами и упростив проблемную область.
Каждое решение будет производить результат, за который оно отвечает. Этот вывод должен содержать информацию о версии, которая может быть установлена в автоматическом процессе. Когда результат будет стабильным, вы можете обновить ссылки в зависимых проектах и решениях с помощью последней версии внутреннего дистрибутива. Если вы все еще хотите войти в код и получить доступ к источнику, вы действительно можете сделать это с помощью сервера символов Microsoft, который Visual Studio может использовать, чтобы вы могли перейти к ссылочным сборкам и даже получить исходный код.
Одновременная разработка может быть осуществлена путем предварительного указания интерфейсов и имитации разрабатываемых сборок, пока вы ждете незавершенных зависимостей, которые вы хотите развить.
Я считаю, что это лучшая практика, потому что нет предела тому, насколько сложным может быть общее усилие, когда вы разбиваете его физически таким образом. Объединение всех проектов в одно решение в конечном итоге достигнет верхнего предела.
Надеюсь, эта информация поможет.
источник
У нас около 60+ проектов, и мы не используем файлы решений. У нас есть смесь проектов C # и VB.Net. Производительность всегда была проблемой. Мы не работаем над всеми проектами одновременно. Каждый разработчик создает свои собственные файлы решений на основе проектов, над которыми они работают. Файлы решения не попадают в систему управления версиями.
Все проекты библиотеки классов будут собираться в папку CommonBin в корне исходного каталога. Исполняемые / веб-проекты создаются в отдельной папке.
Мы не используем ссылки на проекты, вместо них ссылки на файлы из папки CommonBin. Я написал специальную задачу MSBuild, которая проверяет проекты и определяет порядок сборки.
Мы пользуемся этим уже несколько лет и нареканий не имеем.
источник
Все это связано с вашим определением и представлением о том, что такое решение и проект. На мой взгляд, решение - это просто логическая группировка проектов, которые решают очень конкретное требование. Мы разрабатываем большое интранет-приложение. Каждое приложение в этой интрасети имеет собственное решение, которое также может содержать проекты для бывших сотрудников или служб 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/
источник
Установка CopyLocal = false сократит время сборки, но может вызвать различные проблемы во время развертывания.
Есть много сценариев, когда вам нужно, чтобы Copy Local оставалось равным True, например, проекты верхнего уровня, зависимости второго уровня, библиотеки DLL, вызываемые отражением.
Мой опыт установки CopyLocal = false не увенчался успехом. См. Сводку «за» и «против» в моем сообщении в блоге «НЕ меняйте ссылки проекта« Копировать локальные »на ложные, если не понимаете подпоследовательности».
источник