Ответ 1
Да, это плохая практика именно по той причине, о которой вы заявили, - вы не можете перестроить из источника.
Во-первых, я опишу пример того, как это может произойти с использованием С# в Visual Studio, поскольку VS, как правило, информирует вас, если у вас есть циклическая ссылка и не рекомендуется.
Сначала создается класс Утилиты, основанный только на коде, предоставленном вам Visual Studio и .Net. Затем создается класс E-mail, который зависит от Утилиты. Вместо того, чтобы добавлять оба проекта в одно решение, создается новое решение и добавляется ссылка на Utilities.dll. Затем, спустя некоторое время, кто-то решает, что они хотят, чтобы класс Утилиты отправил электронное письмо и добавил ссылку на Mail.dll. Visual Studio с удовольствием позволит вам это сделать, но теперь источник не будет компилироваться как есть без одного из двоичных файлов.
В моем рабочем месте это стандартная процедура для копирования и вставки двоичных файлов при разработке, а затем только для создания проектов, над которыми вы работаете. Это привело к по крайней мере одной циркулярной ссылке в кодовой базе, которая осталась незамеченной более 3 лет.
Это кажется очень плохой практикой для меня, потому что нет возможности построить проект из источника, не имея вначале DLL. Этот аргумент мало подходит для "практических" людей, с которыми я работаю, поскольку маловероятно, что мы потеряем все копии наших двоичных файлов одновременно. Бинарные файлы не сохраняются в контроле версий в любой момент, что только меня больше беспокоит.
Это похоже на ситуацию, которой следует избегать, но не такую ситуацию, которая представляет какую-либо значительную угрозу. Являются ли круговые ссылки между проектами действительно большими, или я не выдуваю их из пропорции?
Да, это плохая практика именно по той причине, о которой вы заявили, - вы не можете перестроить из источника.
Это один из симптомов чрезмерной модуляции.
Я работал в компании один раз с около двадцати разработчиков и более шестидесяти различных активных проектов в репозитории SVN. Каждый проект имел свою собственную конструкцию script и создал JAR файл, который был зависимым от по меньшей мере полудюжины или около того других проектов. Управление всеми этими зависимостями было настолько сложным, что мы потратили много времени на попытки (неудачно, я мог бы добавить), чтобы настроить проекты maven для автоматического получения всех правильных библиотек (и правильных версий) для всех этих небольших микропроектов.
Самое смешное (для меня) было то, что это был действительно только один проект, и это было не то, что мы раздавали внешнему миру. Это было размещенное приложение с веб-интерфейсом, работающее на одном кластере серверов.
Sheesh.
Другим побочным эффектом архитектуры было то, что одни и те же функции дублировались снова и снова (не всегда с теми же алгоритмами или результатами, если на то пошло) в нескольких разных проектах. Я думаю, что причина в том, что люди не хотели вводить новую зависимость от всего подпроекта, чтобы получить доступ к некоторым из его классов. Но я думаю, что еще одна причина заключалась в том, что люди просто не знали, какой код существует там, и вместо того, чтобы искать код, который они хотели бы использовать, они просто переписывали бы его в своем собственном проекте.
Конечно, модульность вообще хорошая вещь.
Но, как и все хорошие вещи, его можно воспринимать до смешных крайностей.
Мой совет состоит в том, чтобы найти эти циклические зависимости и объединить проекты в более крупные куски, поскольку текущий прорыв проекта, вероятно, представляет собой ложную модульность. Лучше разделить свой большой проект на несколько хорошо разделенных модулей, чем иметь миллион псевдомодулей, создающих искусственные границы между логически связанными классами.
Помимо проблем с построением, циклические ссылки всегда указывают на недостаток дизайна. В .NET круговая связь делает две сборки эффективно одной сборкой. Если ни один из них не может жить сам по себе без другого, его создание отдельно - это просто упражнение - это не меняет того факта, что вместе они представляют собой монолитную сборку.
Я заметил это много с сборками утилиты. Должен быть анти-шаблон.
Вопрос, который я бы поставил перед вашими коллегами:
Хорошо, очень маловероятно, что мы потеряем все наши двоичные файлы одновременно. Но, скажите, какая польза от этого подхода?
Если они приходят с чем-то другим, чем "Мы всегда делали это так", я бы хотел это услышать. И, как всем известно, "мы всегда так делали это", это НЕ хорошая причина, и они не должны защищать его.
круговые зависимости плохие, потому что:
это потенциально бесконечный цикл в процессе сборки
Если у вас возникли проблемы с убеждением ваших "прагматичных" коллег в том, что это плохая практика, предложите прагматичное решение: удалите эти циклические ссылки и время сборки снизится, так как избежать ненужных перестроек не удастся.
Hm, я думаю, что в терминах вопроса OP, о проектах Building с нуля, это плохая практика, из-за:
Да, это очень важно, потому что это приводит к неуправляемым составным композициям и, скорее всего, некоторым формам ошибок сборки и, скорее всего, некоторым ошибкам развертывания, в какой-то момент жизненного цикла проекта.
Visual Studio 2008 явно запрещает циклические ссылки между проектами (а не бинарниками) в решениях. Как вы уже сказали, это не относится к двоичным файлам. Я считаю, что это связано с тем, что VS2008 ожидает, что бинарные ссылки управляются независимо и ожидает, что вы создадите эти проекты самостоятельно. Вообще говоря, это означает, что все бинарные ссылки следует рассматривать как сторонние компоненты, которые представляют собой отдельные отношения в одностороннем порядке (между вашим кодом и двоичным кодом).
Кроме того, MSBuild позволяет использовать файл SLN для создания всего, если все ваши проекты используют VB или С#. Это позволяет создать файл uber-solution, который идеально подходит для процесса автоматической сборки. Уловка заключается в том, что для того, чтобы такой файл главного решения работал, все проекты в SLN должны использовать ссылки на проекты. Поэтому, чтобы воспользоваться этим, по определению, Microsoft ожидает, что вы не используете круговые ссылки, поскольку они явно запрещены средой Visual Studio IDE (для ссылок на проекты).
Скотт Хансельман ссылается на файл uber-solution в следующем сообщении:
Hack: параллельные MSBuild из среды Visual Studio IDE
http://www.hanselman.com/blog/CategoryView.aspx?category=MSBuild