Наскільки суворо дотримуєтесь правила "Без циклу залежності" (NDepend)


10

Трохи довідки: як керівник команди, я використовую NDepend приблизно раз на тиждень, щоб перевірити якість нашого коду. Особливо тест-покриття, рядки коду та метрики цикломатичної складності для мене безцінні. Але коли справа доходить до циклів вирівнювання та залежності, я трохи ... заклопотаний. У Патріка Смакіа є приємна публікація в блозі, в якій описана мета вирівнювання.

Щоб було зрозуміло: під "циклом залежності" я розумію кругові посилання між двома просторами імен.

В даний час я працюю над системою GUI на основі CE CE для вбудованих інструментів - просто подумайте про графічну платформу Android, але про інструменти дуже низького рівня. Рамка являє собою єдину збірку з близько 50 000 рядків коду (випробування виключені). Рамка розділена на такі простори імен:

  • Основна підсистема навігації та меню
  • Екранна підсистема (Презентатори / Перегляди / ...)
  • Елементи керування / шар віджетів

Сьогодні я провів половину дня, намагаючись привести код до належних рівнів [завдяки Resharper взагалі немає проблем], але у всіх випадках існують певні цикли залежності.

Отже, моє запитання: наскільки чітко ви дотримуєтесь правила "Без циклу залежності"? Чи справді важливо вирівнювання?


2
Якщо "відсутність циклу залежності" означає відсутність кругових посилань, то - ніяких виправдань. Це чисто зло.
Арніс Лапса

@ollifant: визначте, що саме ви маєте на увазі, коли ви пишете "Без циклу залежності". Між шарами або між класами всередині шару?
Док Браун

Відповіді:


9

Нещодавно я написав дві білі книги, опубліковані в Simple-Talk на тему архітектури .NET-коду (перша книга про збірки .NET, друга - про простори імен та вирівнювання):

Розбиття бази Вашого коду за допомогою .NET зборів та проектів Visual Studio

Визначення .NET компонентів з просторами імен

Чи справді важливо вирівнювання?

Так!

Цитата з 2-ї білої книги:

Якщо графік залежностей між компонентами містить цикл, компоненти, що беруть участь у циклі, не можуть бути розроблені та перевірені самостійно. Через це цикл компонентів являє собою суперкомпонент, з більшою ентропією, ніж сума ентропій його містяться компонентів.

(...)

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

  • У традиційній архітектурній будівлі сила гравітації тисне на артефакти низького рівня. Це робить їх більш стійкими: «стабільними» в тому сенсі, що їх важко рухати.
  • В архітектурі програмного забезпечення, дотримуючись ідеї ациклічної складової, тиснуть на компоненти низького рівня. Це робить їх більш стійкими, в тому сенсі, що болісно їх переробляти. Емпірично абстракції рідше піддаються рефакторингу, ніж реалізація. З цієї причини, гарна ідея, що компоненти низького рівня містять в основному абстракції (інтерфейси та перерахування), щоб уникнути болісного рефакторингу.

6

Я ніколи не допускаю кругової залежності між класами чи просторами імен. У C #, Java та C ++ ви завжди можете розірвати залежність кругового класу, ввівши інтерфейс.

Тест кодування спочатку ускладнює введення кругових залежностей.


4

Це завжди справа: ви повинні розуміти вартість залежностей, щоб зрозуміти, чому слід уникати залежностей. Таким же чином, якщо ви розумієте вартість залежності, можете краще вирішити, чи варто це у вашому конкретному випадку.

Наприклад, у консольних відеоіграх ми часто покладаємось на залежності, де потрібні тісні зв’язки інформації, переважно з міркувань продуктивності. Це добре, оскільки, наприклад, нам не потрібно бути таким гнучким, як інструмент видання.

Якщо ви розумієте обмеження, якими має працювати програмне забезпечення (це апаратне забезпечення, ОС або просто дизайн (на кшталт "простіший інтерфейс, який ми можемо")), то вибирати розуміння того, які залежності не повинні бути зроблені, і які з них є, слід легко. добре.

Але якщо у вас немає вагомих і зрозумілих причин, уникайте будь-якої залежності, яку можете. Залежний код - це пекло налагодження.


2

Щоразу, коли ця тема обговорюється, учасники, як правило, втрачають різницю між циклами побудови та час роботи. Перше - це те, що Джон Лакос назвав "фізичним дизайном", а останнє в основному не має значення для дискусії (не зациклюйтеся на циклах виконання, наприклад, створених зворотними дзвінками).

З цього приводу Джон Лакос дуже суворо ставився до усунення всіх циклів (час нарощування). Боб Мартін, однак, прийняв таке ставлення, що лише цикли між бінарними файлами (наприклад, DLL-файли, виконувані файли) є значущими і їх слід уникати; він вважав, що цикли між класами в двійковій формі не є надзвичайно важливими.

Я особисто дотримуюся погляду Боба Мартіна на це. Однак я все ж приділяю деяку увагу циклам між класами, оскільки відсутність таких циклів полегшує код читати та навчатись іншим.

Слід зазначити, однак, що будь-який код, який ви створюєте за допомогою Visual Studio, не здатний мати кругові залежності між бінарними файлами (будь то власний чи керований код). Таким чином, найбільша проблема циклів вирішена для вас. :)


0

Майже повністю, тому що цикли залежності типу побудови незручні в Haskell, неможливі в Agda та Coq, і це мови, якими я зазвичай користуюся.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.