Stop Circular Dependencies With SDP

Циклічні залежності — це «тихі вбивці». Вони не викликають помилок під час збірки. Вони не спричиняють винятків під час виконання (runtime exceptions) під час імпорту. Натомість вони призводять до ледь помітних значень undefined, які з'являються у продакшені через кілька тижнів.

Цикл виникає, коли Модуль A імпортує щось із B, а B імпортує щось назад із A.

JavaScript розв'язує ці імпорти мовчки. Якщо Модуль A все ще завантажується в той момент, коли Модуль B запитує його, JavaScript повертає порожній об'єкт. Ваш код виходить з ладу пізніше, а стек викликів (stack trace) вказує не на те місце.

Ви можете виправити це за допомогою dependency-cruiser. Цей інструмент сканує ваші файли та будує граф залежностей. Він працює з TypeScript та монорепозиторіями.

Як налаштувати:

  • Додайте його до ваших dev dependencies: yarn add -D dependency-cruiser
  • Додайте скрипт до вашого package.json: "depcruise": "depcruise packages --config .dependency-cruiser.js"
  • Створіть файл .dependency-cruiser.js, щоб відловлювати цикли.

Але знайти цикл — це лише половина справи. Ви повинні не дати їм виникнути.

Використовуйте принцип стабільних залежностей (Stable Dependencies Principle, SDP). Це правило стверджує, що ви повинні будувати залежності в напрямку стабільності.

Стабільність — це структурна властивість. Модуль є стабільним, коли від нього залежить багато інших модулів. Якщо ви зміните стабільний модуль, це вплине на багатьох розробників. Саме ця ціна робить його стабільним.

Використовуйте формулу нестабільності: I = Fan-Out / (Fan-In + Fan-Out)

• I = 0 означає, що модуль є максимально стабільним. Від нього залежить усе, а сам він не залежить ні від чого. • I = 1 означає, що модуль є максимально нестабільним. Він залежить від багатьох речей, а від нього не залежить ніщо.

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

Ваші утиліти низького рівня (I ≈ 0) ніколи не повинні імпортувати щось із ваших сторінок високого рівня (I ≈ 1).

Ви можете перетворити цей принцип на автоматизоване правило за допомогою dependency-cruiser. Замість того, щоб просто перевіряти наявність циклів, перевіряйте напрямок:

  • Забороніть утилітам імпортувати щось із features.
  • Забороніть features імпортувати щось із pages.

Це усуває структурні умови, що створюють цикли. Ви перестаєте реагувати на баги і починаєте їх запобігати.

Source: https://dev.to/wojciech_kot_b82f5d7cbfc6/stop-circular-dependencies-before-they-stop-you-dependency-cruiser-the-stable-dependencies-34ho