Во-первых, я опишу пример того, как это может происходить при использовании C# в Visual Studio, поскольку VS обычно сообщает вам, есть ли у вас циклическая ссылка, и предотвращает ее.
Сначала создается класс Утилиты, полагающийся только на код, предоставленный вам Visual Studio и .Net. Затем создается класс Электронная почта, который зависит от Утилиты. Вместо добавления обоих проектов в одно решение создается новое решение и добавляется ссылка на Utilities.dll. Затем, спустя некоторое время, кто-то решает, что он хочет, чтобы класс Утилиты отправлял электронное письмо, и добавляет ссылку на Email.dll. Visual Studio с радостью позволит вам это сделать, но теперь исходный код не будет компилироваться как есть без одного из двоичных файлов.
На моем рабочем месте это стандартная процедура - копировать и вставлять двоичные файлы при разработке, а затем создавать только те проекты, над которыми вы работаете. Это привело как минимум к одной циклической ссылке в кодовой базе, которая оставалась незамеченной более 3 лет.
Мне это кажется очень плохой практикой, потому что нет способа собрать любой проект из исходного кода, не имея предварительно библиотеки DLL. Этот аргумент не подходит «практичным» людям, с которыми я работаю, поскольку маловероятно, что мы потеряем все копии наших двоичных файлов одновременно. Бинарные файлы никогда не хранятся в системе контроля версий, что только беспокоит меня.
Это похоже на ситуацию, которой следует избегать, но не на ситуацию, которая представляет какую-либо заметную угрозу. Действительно ли циркулярные ссылки между проектами имеют большое значение или я преувеличиваю?





Вопрос, который я хотел бы задать вашим коллегам, звучит так:
Хорошо, очень маловероятно, что мы потеряем все наши двоичные файлы одновременно. Но скажите мне, в чем польза такого подхода?
Если они придут с чем-то отличным от «Мы всегда так поступали», я бы хотел это услышать. И, как всем известно, «мы всегда так поступали» НЕ является хорошей причиной, и они не должны ее защищать.
«мы всегда так поступали» - это один шаг от «Изменение этого стоит денег компании»
Компании будет стоить больше денег не
Да, это плохая практика именно по той причине, которую вы указали - вы не можете перестроить из исходного кода.
Я бы добавил, что хороший способ избежать подобных проблем - автоматическая непрерывная интеграция.
Хм, я думаю, что с точки зрения вопроса OP, о проектах строительство с нуля, это плохая практика из-за:
Помимо проблем со сборкой, циклические ссылки всегда указывают на недостаток дизайна. В .NET круговая связь превращает две сборки в одну. Если ни один из них не может жить самостоятельно без другого, их сборка по отдельности - это просто упражнение - это не меняет того факта, что вместе они представляют собой монолитную сборку.
Я часто это замечал на сборках утилит. Должен быть антипаттерн.
Круговые зависимости плохи, потому что:
это потенциально бесконечный цикл в процессе сборки
Это один из симптомов сверхмодуляризации.
Однажды я работал в компании, в которой было около двадцати разработчиков и более шестидесяти различных активных проектов в репозитории SVN. Каждый проект имел свой собственный сценарий сборки и создавал файл JAR, который зависел как минимум от полдюжины или около того других проектов. Управление всеми этими зависимостями было настолько сложным, что мы потратили кучу времени, пытаясь (я мог бы добавить, безуспешно) настроить проекты maven на автоматическое получение всех правильных библиотек (и правильных версий) для всех этих небольших микропроектов.
Самое смешное (для меня) было то, что на самом деле это был всего лишь один проект, и это даже не было чем-то, что мы распространяли во внешний мир. Это было размещенное приложение с веб-интерфейсом, работающее на кластере с одним сервером.
Блин.
Еще одним побочным эффектом архитектуры было то, что одни и те же виды функциональности дублировались снова и снова (не всегда с одними и теми же алгоритмами или результатами, если на то пошло) в нескольких разных проектах. Я думаю, что отчасти причина заключалась в том, что люди не хотели вводить новую зависимость для всего подпроекта только для того, чтобы получить доступ к нескольким его классам. Но я думаю, что еще одна причина заключалась в том, что люди просто не знали, какой код и где существует, и вместо того, чтобы искать код, который они хотели использовать повторно, они просто переписали его в своем собственном проекте.
Конечно, модульность - это вообще хорошо.
Но, как и все хорошее, его можно довести до смехотворных крайностей.
Мой совет - найти эти циклические зависимости и объединить проекты в более крупные куски, поскольку текущая разбивка проекта, вероятно, представляет собой ложную модульность. Лучше разделить ваш большой проект на несколько хорошо разделенных модулей, чем иметь миллиард псевдомодулей, создающих искусственные границы между логически связанными классами.
Я слышал, что упаковка Nuget для компонентов проекта базового уровня, таких как объекты DAL и POCO, является хорошей идеей, потому что вы можете установить пакеты Nuget в нескольких решениях. Вы слышали то же самое? Если да, не могли бы вы объяснить, как я могу использовать упаковку Nuget в такой ситуации?
Да, это большое дело, потому что это приводит к неуправляемым составам компонентов и, скорее всего, к некоторым ошибкам сборки и, очень вероятно, к некоторым ошибкам развертывания на определенном этапе жизненного цикла проекта.
Visual Studio 2008 явно запрещает циклические ссылки между проектами (не двоичными файлами) в решениях. Как вы заявили, это не относится к двоичным файлам. Я считаю, что это потому, что VS2008 ожидает, что двоичные ссылки управляются независимо, и ожидает, что вы создаете эти проекты независимо. Вообще говоря, это означает, что все двоичные ссылки следует рассматривать как сторонние компоненты, которые представляют собой отдельные односторонние отношения (между вашим кодом и двоичным кодом).
Кроме того, MSBuild позволяет использовать файл SLN для сборки всего, если все ваши проекты используют VB или C#. Это позволяет создать файл uber-решения, который идеально подходит для автоматизированного процесса сборки. Загвоздка в том, что для того, чтобы такой главный файл решения работал, все проекты в SLN должны использовать ссылки на проекты. Следовательно, чтобы воспользоваться этим преимуществом, Microsoft по определению ожидает, что вы не используете циклические ссылки, поскольку они явно запрещены IDE Visual Studio (для ссылок на проекты).
Скотт Хансельман ссылается на файл uber-решения в следующем сообщении:
Взлом: параллельные сборки MSBuild из среды Visual Studio IDE
.
http://www.hanselman.com/blog/CategoryView.aspx?category=MSBuild
Если вам трудно убедить своих «прагматичных» коллег в том, что это плохая практика, предложите прагматичное решение: удалите эти циклические ссылки, и время сборки сократится, так как можно избежать множества ненужных перестроек.
Интересный факт: в некоторых языках, например в python. Циркулярная ссылка просто не работает. В python циклическая ссылка в двух классах вызывает исключение при попытке запустить программу.