Роберт Мартін запропонував метрики, що перетворюють розмови про «зв'язність модулів» на числа.
Аферентна зв'язність (Ca) - скільки інших модулів залежать від цього. Висока Ca - модуль важливий для багатьох; його зміна зачіпає багатьох.
Еферентна зв'язність (Ce) - від скількох модулів залежить цей. Висока Ce - модуль залежить від багатьох; зміни в будь-якому з них можуть його зламати.
Нестабільність:
I = Ce / (Ca + Ce) від 0 до 1
- I ≈ 0 - стабільний модуль: від нього багато залежать, він сам ні від кого. Змінювати його дорого (багато споживачів). Приклад: спільні value objects, базові інтерфейси, ядро предметної області;
- I ≈ 1 - нестабільний: ні від нього ніхто, а він від багатьох. Змінювати легко й безпечно. Приклад: контролери, консольні команди, UI.
Принцип стабільних залежностей: залежності мають іти в напрямку стабільності - нестабільні модулі залежать від стабільних, а не навпаки. Якщо стабільний модуль (від якого залежить половина системи) залежить від нестабільного, кожна зміна нестабільного «трусить» усю систему.
Абстрактність (A) - частка абстрактних класів та інтерфейсів у модулі. Принцип стабільних абстракцій: стабільні модулі мають бути абстрактними (щоб їх можна було розширювати без зміни), нестабільні - конкретними.
Головна послідовність: ідеально A + I ≈ 1. Відхилення показує проблемні зони:
- «зона болю» (стабільний і конкретний: I ≈ 0, A ≈ 0) - від модуля всі залежать, але його неможливо розширити без зміни. Типово для «утилітних» класів і перевантажених базових моделей;
- «зона марності» (нестабільний і абстрактний) - інтерфейси, які ніхто не використовує.
Як застосувати в PHP-проєкті:
- інструменти: PhpMetrics, Deptrac (ще й перевіряє дозволені залежності між шарами), pdepend;
- дивитися на тенденції між релізами, а не на абсолютні значення;
- для модульного моноліту - головні метрики на рівні модулів (
Billing,Catalog), а не окремих класів.
Застереження: метрики - сигнал для розмови, а не мета. Оптимізувати «I» заради числа - створити штучні інтерфейси. Корисне питання: «чому від цього модуля залежить усе?» - і чи має так бути.