Решения Visual Studio: есть ли в этих решениях слишком много проектов?

В компании, в которой я сейчас работаю, мы поддерживаем 4 приложения Windows, которые несколько связаны. Для каждого приложения у нас есть решение, каждое из которых составляет от 50 до 100 проектов. Есть, вероятно, 40 или 50 проектов, которые разделяются между одним или несколькими решениями.

Просто для того, чтобы дать вам представление, более крупное решение имеет почти 90 проектов, 20 из которых являются проектами пользовательского интерфейса (основное приложение, проекты пользовательских элементов управления, вспомогательные проекты UI), еще 20 - это проекты бизнес-уровня, возможно, 30 или 40 данных Проекты уровня доступа, а остальные - проекты Windows и специализированные проекты

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

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

  • Большое время компиляции.
  • Классы, которые обычно должны быть Private, должны быть общедоступными, чтобы быть доступными другими проектами на одном уровне.
  • Недавно я начал использовать профилировщик Eqateq. Пробная версия позволяет профилировать до 10 DLL. Моя ситуация явно затрудняет использование этого приложения.
  • Отслеживание ссылок между проектами довольно сложно. Я уверен, что существует много неиспользуемых ссылок между проектами.

Напротив, я не нашел преимущества этой ситуации.

Итак, мои вопросы:

  • Когда вы решили создать новый проект, а не просто создать папку в текущем проекте?
  • Есть ли какие-то преимущества, которые я пропускаю?

UPDATE:

Имейте в виду, что я не предлагаю ни одного проекта для всего. На минимальном уровне должен быть один проект для DAL, один для BL и один для каждого приложения пользовательского интерфейса. И я понимаю, что это нереально для большинства приложений. Я пытаюсь понять, каковы наилучшие методы определения уровня "единой ответственности" за сборку? Я имею в виду, что это очень субъективный вопрос, который, если его принять до крайности, приведет к созданию одной сборки для каждого класса.

ОБНОВЛЕНИЕ 2:

Все три ответа предоставили ценную информацию, но поскольку я могу выбрать только один, я выбираю Doc для его комментария о том, как определить количество проектов DAL. Я также связываюсь с другими вопросами, которые я только что нашел, которые имеют следующую информацию: здесь и здесь. Я также рекомендую читать эту статью.

Ответ 1

Мы говорим в основном о проектах .NET, не так ли? Если ваше приложение разделено на разные проекты/сборки, вы вынуждены избегать циклических зависимостей между этими проектами, поскольку компиляторы С# и VB.NET запрещают это. Если вы ставите все в один большой проект, каждый класс может ссылаться на каждый другой класс в этом проекте, позволяя создать реальный кошмар зависимости. Если вы собираетесь использовать модульные тесты и разработки в команде, это в основном легче, если члены команды могут работать в разных изолированных библиотеках DLL и тестировать их отдельно.

"Отслеживание ссылок" часть вашего вопроса: если вы поместили все в одну большую DLL, у вас есть те же ссылки между вашими классами, как если бы у вас были отдельные библиотеки DLL, но вы больше не можете их контролировать. То же самое касается классов "private" (вы подразумеваете "внутренний", я думаю?)

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

EDIT: пока я прочитал несколько статей (как этот) о сокращении времени компиляции путем определения границ компонентов по пространствам имен и поместив несколько компонентов в одну физическую сборку/один проект VS. Чтобы сделать этот подход осуществимым, нужно, вероятно, использовать такой инструмент, как NDepend или что-то подобное, чтобы убедиться, что между компонентами нет циклических зависимостей. Для больших проектов это, вероятно, лучший вариант.

Ответ 2

Наличие многих проектов не обязательно плохо.

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

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

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

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

Для классов, которые принадлежат ТОЛЬКО для проекта, я обычно добавляю "внутреннее" (или "подробное" ) слово в пространство имен этих "внутренних" классов, которые должны быть объявлены общедоступными. Например: вы узнаете, что никакие классы из MyApplication.Model.Publisher не должны обращаться к любым классам из: MyApplication.Model.Vendors.Internal. Это метод, который я видел в API Eclipse.

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

Другие подходы с действительно огромным программным обеспечением идут по плагинам, поэтому время сборки будет намного короче. Он всегда идет с ценой ты. Вы можете проверить OSGI для этого.

Ответ 3

Если количество проектов в данном решении вызывает ежедневное раздражение (например, из-за нагрузки на решение и времени компиляции), у вас действительно есть слишком много проектов в решении. Тем не менее, альтернативы могут быть немного раздражающими, поэтому вам нужно выяснить, где лежит ваша "счастливая среда".

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

В то время как циклическое уклонение от зависимости определенно желательно, я видел сборку сегрегации, взятую в некоторые довольно нелепые крайности. Существуют инструменты (например, NDepend, FxCop), которые могут помочь выявить неадекватные зависимости, и я, как правило, предпочитаю использовать их для сегрегации сборки, когда единственная причина для сегрегации - это единственная причина для сегрегации.

Ответ 4

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

Мое личное мнение - начать с одного проекта на один слой (как вы упомянули), например, для графического интерфейса пользователя, один для бизнес-уровня, один для DAL и т.д. Дополнительные проекты для вашего решения должны создаваться только тогда, когда возникает определенная потребность, а не преждевременно. На этом этапе вы можете реорганизовать свое решение, чтобы переместить проект "Папка" в отдельный проект.

Это обеспечит: - время сборки быстрее - У вас есть точный объем проектов, которые требуется вашему проекту. - У вас есть документированные аргументы в пользу того, почему вы создали конкретный проект (что ему нужно)

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