Круговые ссылки когда-либо необходимы? - PullRequest
6 голосов
/ 27 августа 2010

Я унаследовал решение Visual Studio, которое содержит многочисленные циклические ссылки между проектами.

Была ли когда-нибудь ситуация, когда это приемлемо удаленно?

Просто пытаюсь подтвердить мое подозрение, что этоПриложение разработано ужасно.Заранее спасибо.

Ответы [ 4 ]

8 голосов
/ 27 августа 2010

Однажды я прочитал колонку, в которой сравнивали 3 вида моделей: модель Спагетти, модель Лазаньи и модель Равиоли.

В модели Спагетти весь код взаимосвязан, четкой структуры нет. Это ужасно, и мы, вероятно, все можем согласиться с этим.

В модели Лазанья код разделен на разные уровни, и только слой более высокого уровня может получить доступ к слою более низкого уровня, и никогда наоборот.

В модели Ravioli код сгруппирован в меньшие модули. Каждый модуль предоставляет только то, что нужно показать, но каждый модуль может получить доступ ко всем другим модулям.

Около 10 лет назад мне показалось, что модель Ravioli лучше, чем модель Lasagna. В конце концов, в Java также есть модули Java, которые могут легко вызывать друг друга (и у меня сложилось впечатление, что между всеми различными модулями Java нет реальной структуры). Мне модель Lasagna казалась результатом не-объектно-ориентированного старого кода, а модель Ravioli казалась более современной, более объектно-ориентированной.

В настоящее время я склоняюсь к модели Лазаньи, но со встроенной моделью Равиоли. Это:

  • Приложение построено с использованием разных слоев, как в модели Lasagna
  • Но внутри слоев код все еще разделен между различными модулями, которые могут обращаться друг к другу, как в модели Ravioli.

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

Обратите внимание, что циклическая ссылка в этом примере уже может привести к проблемам (класс FileWriter может вызывать класс Debug при написании строки, но класс Debug использует класс FileWriter для записи отладочной информации, результат: переполнение стека).

В этом случае проблему можно легко решить, если не использовать класс FileWriter в классе Debug, а использовать собственные iostreams (если вы разрабатываете на C ++). В других случаях проблему может быть гораздо сложнее решить.

2 голосов
/ 29 августа 2010

Конкретно я бы посоветовал использовать NDepend для обнаружения и избежания циклов зависимости .

alt text

Выдержка из статьи (я написал): Управляйте зависимостями компонентов для получения чистой архитектуры

Циклы зависимости между компонентами приводят к тому, что обычно называют спагетти-кодом или запутанным кодом.Если компонент A зависит от B, который зависит от C, который зависит от A, компонент A не может быть разработан и протестирован независимо от B и C. A, B и C образуют неделимую единицу, своего рода суперкомпонент.Этот суперкомпонент имеет более высокую стоимость, чем сумма затрат по сравнению с A, B и C, из-за явления экономии масштаба (хорошо задокументировано в статье «Оценка программного обеспечения: демистификация черного искусства» Стива Макконнелла).По сути, это говорит о том, что стоимость разработки неделимого фрагмента кода увеличивается в геометрической прогрессии.

Это говорит о том, что разработка и поддержка 1000 LOC (строк кода), вероятно, обойдется в три или четыре раза дороже, чем разработка и поддержка 500 LOC, если только он не может быть разделен на два независимых кусочка по 500 LOC каждый.Отсюда и сравнение со спагетти, описывающим запутанный код, который невозможно поддерживать.Для рационализации архитектуры необходимо убедиться, что между компонентами нет циклов зависимости, а также убедиться, что размер каждого компонента приемлем (от 500 до 1000 LOC).

2 голосов
/ 27 августа 2010

Хорошее программное обеспечение разработано в слоях с четко разграниченными границами между ними.То есть: если у вас есть слой, вы должны быть в состоянии четко сформулировать, что он делает, почему он есть и от чего он зависит.Круглость затрудняет достижение этого и, как правило, должна быть удалена.(Microsoft потратила немало усилий в Windows 7, чтобы улучшить многоуровневую структуру Windows, удалив цикличности.)

Просто пытаюсь подтвердить мое подозрение, что это приложение разработано ужасно.

Это определенно поддержит эту теорию, но ИМО, вам понадобится не просто несколько циклических ссылок, чтобы сделать такой вывод.

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

1 голос
/ 27 августа 2010

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

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

...