Не має значення, наскільки міцно пов'язане одне з іншим, якщо та інша річ ніколи не змінюється. Звичайно, я вважав, що протягом багатьох років більш продуктивним є фокусування на пошуку меншої кількості причин, щоб змінитись, шукати стабільності, ніж полегшити їх зміни, намагаючись досягти найбіднішої форми з’єднання.
Роз'єднання я вважаю дуже корисною до того, що іноді я віддаю перевагу скромному дублюванню коду для роз'єднання пакетів. Як основний приклад, я мав вибір використовувати свою математичну бібліотеку для реалізації бібліотеки зображень. Я не робив і просто копіював деякі основні математичні функції, які були тривіальними для копіювання.
Тепер моя бібліотека зображень повністю незалежна від математичної бібліотеки таким чином, що незалежно від того, які зміни я вносимо до своєї математичної області, це не вплине на бібліотеку зображень. Це ставить стабільність насамперед. Зараз бібліотека зображень є більш стабільною, як і в тому, що різко менше причин для зміни, оскільки вона відокремлена від будь-якої іншої бібліотеки, яка могла б змінитися (окрім стандартної бібліотеки С, яка, сподіваємось, ніколи не повинна змінюватися). Як бонус, його також легко розгорнути, коли це просто окрема бібліотека, яка не потребує втягування купу інших ліб, щоб створити її та використовувати.
Стабільність мені дуже допомагає. Мені подобається створювати колекцію добре перевіреного коду, який має все менше і менше причин коли-небудь змінитись у майбутньому. Це не трубна мрія; У мене є код C, який я використовую і використовую знову з кінця 80-х, який з тих пір взагалі не змінився. Це, мабуть, низький рівень матеріалів, наприклад, орієнтований на пікселі та пов'язаний з геометрією код, в той час як багато моїх матеріалів вищого рівня застаріли, але це все-таки багато що допомагає. Це майже завжди означає бібліотеку, яка покладається на все менше і менше речей, якщо взагалі нічого зовнішнього. Надійність зростає і збільшується, якщо ваше програмне забезпечення все більше залежить від стабільних основ, які знаходять мало причин для зміни. Менше рухомих деталей справді приємно, навіть якщо на практиці рухомих деталей за кількістю набагато більше, ніж стійких деталей.
Вільна муфта знаходиться в одному ключі, але я часто виявляю, що сипуча муфта настільки менш стабільна, ніж жодна муфта. Якщо ви не працюєте в команді з набагато кращими дизайнерами інтерфейсів і клієнтами, які не змінюють свою думку, ніж я коли-небудь працював, навіть чисті інтерфейси часто знаходять причини змінюватися способами, які все ще спричиняють каскадні поломки коду. Ця думка про те, що стабільність може бути досягнута шляхом спрямування залежностей до абстрактного, а не конкретного, корисна лише в тому випадку, якщо дизайн інтерфейсу легше отримати в перший раз, ніж реалізація. Мені часто здається, що розробник, можливо, створив би дуже гарну, якщо не чудову, реалізацію, враховуючи вимоги до дизайну, які, на їх думку, повинні виконати, лише щоб у майбутньому змінити вимоги до дизайну повністю.
Тому мені подобається підтримувати стабільність і повну розв'язку, щоб я міг принаймні впевнено сказати: "Ця маленька ізольована бібліотека, яка використовується роками та захищена ретельним тестуванням, майже не має ймовірності вимагати змін незалежно від того, що відбувається в хаотичному зовнішньому світі . " Це дає мені невеликий шматочок розуму, незалежно від того, які дизайнерські зміни вимагаються зовні.
З'єднання та стабільність, приклад ECS
Я також люблю системи, що складаються з компонентів, і вони впроваджують багато жорстких зв'язків, оскільки система для компонентних залежностей забезпечує доступ до всіх даних та маніпулює ними, безпосередньо так:

Всі залежності тут досить жорсткі, оскільки компоненти просто викривають необроблені дані. Залежності не тягнуться до абстракцій, вони спрямовуються до необроблених даних, що означає, що в кожній системі є максимально можливий обсяг знань про кожен тип компонентів, до яких вони вимагають доступу. Компоненти не мають функціональних можливостей для всіх систем, що мають доступ до та непрацюючих із необробленими даними. Однак міркувати про таку систему, як дуже просто, дуже просто. Якщо текстура виходить гнучкою, то ви з цією системою відразу розумієте, що лише система візуалізації та фарбування має доступ до компонентів текстури, і ви, ймовірно, можете швидко виключити систему візуалізації, оскільки вона читає лише з текстур концептуально.
Тим часом нечітко поєднаною альтернативою може бути така:

... з усіма залежностями, що спрямовані на абстрактні функції, а не на дані, і кожна окрема річ на цій діаграмі розкриває власний публічний інтерфейс та функціональність. Тут усі залежності можуть бути дуже вільними. Об'єкти можуть навіть не безпосередньо залежати один від одного і взаємодіяти один з одним через чисті інтерфейси. Все-таки дуже важко міркувати про цю систему, особливо якщо щось піде не так, враховуючи складний клубок взаємодій. Також буде більше взаємодій (більше з'єднання, хоч і слабкіше), ніж ECS, оскільки суб'єкти повинні знати про компоненти, які вони агрегують, навіть якщо вони знають лише про абстрактний публічний інтерфейс один одного.
Крім того, якщо в чомусь є зміни дизайну, ви отримуєте більше каскадних поломок, ніж ECS, і зазвичай буде більше причин і спокус для зміни дизайну, оскільки кожна річ намагається забезпечити приємний об'єктно-орієнтований інтерфейс та абстракцію. Це відразу ж приходить до думки, що кожна дрібниця намагатиметься накладати обмеження та обмеження на дизайн, і ці обмеження часто є тим, що вимагає зміни дизайну. Функціональність набагато більш обмежена і повинна робити набагато більше припущень щодо дизайну, ніж необроблені дані.
На практиці я виявив, що вищезгаданий тип "плоскої" системи ECS набагато простіше міркувати, ніж навіть найбільш вільно зв'язані системи зі складною павутинною мережею залежних і, що найголовніше для мене, я знаходжу так мало причин щоб версія ECS коли-небудь потребувала змін будь-яких існуючих компонентів, оскільки компоненти, від яких залежав, не несуть ніякої відповідальності, крім надання відповідних даних, необхідних для функціонування систем. Порівняйте складність проектування чистого IMotionінтерфейсу та конкретного об'єкта руху, що реалізує той інтерфейс, який забезпечує складну функціональність, намагаючись підтримувати інваріанти над приватними даними, а не компонент руху, який повинен лише надавати необроблені дані, необхідні для вирішення проблеми, і не турбує функціональність.
Функціональність набагато складніше отримати правильну, ніж дані, тому я вважаю, що часто краще спрямовувати потік залежностей на дані. Зрештою, скільки векторних / матричних бібліотек там? Скільки з них використовують точно однакове представлення даних і лише незначно відрізняються функціональністю? Незліченна кількість, і все-таки у нас все ще так багато, незважаючи на однакові представлення даних, тому що ми хочемо тонких відмінностей у функціональності. Скільки бібліотек зображень там? Скільки з них представляють пікселі по-іншому та унікальним чином? Навряд чи хтось, і знову показує, що функціональність набагато нестабільніша та схильна до змін дизайну, ніж дані у багатьох сценаріях. Звичайно, в якийсь момент нам потрібна функціональність, але ви можете спроектувати системи, де основна частина залежностей надходить до даних, а не до абстракцій чи функціональності взагалі. Таке б надавало перевагу стабільності над зчепленням.
Найбільш стабільні функції, які я коли-небудь писав (такі, які я використовував і використовував з кінця 80-х, не змінюючи їх взагалі), - це всі ті, які спиралися на необроблені дані, як функція геометрії, яка щойно прийняла масив плавці та цілі числа, а не ті, які залежать від складного Meshоб'єкта чи IMeshінтерфейсу, або множення вектора / матриці, що просто залежало від того, float[]чи double[]не залежало від цього FancyMatrixObjectWhichWillRequireDesignChangesNextYearAndDeprecateWhatWeUse.