Але чи не дуже залежить метод draw () від того, яким є інтерфейс користувача?
З прагматичного погляду, деякий код у вашій системі повинен знати, як намалювати щось на кшталт а, Rectangleякщо це вимога для користувача. І це в якийсь момент зводиться до того, щоб робити дійсно речі низького рівня, такі як растрування пікселів або показ чогось у консолі.
Питання до мене з точки зору зв'язку полягає в тому, хто / від чого повинен залежати цей тип інформації та наскільки детально (наскільки абстрактно, наприклад)?
Обмеження можливостей малювання / візуалізації
Оскільки, якщо код малювання вищого рівня залежить лише від чогось дуже абстрактного, то ця абстракція може працювати (через заміну конкретних реалізацій) на всіх платформах, на які ви плануєте націлитись. Як надуманий приклад, якийсь дуже абстрактний IDrawerінтерфейс може бути реалізований як в консольній, так і в інтерфейсі API інтерфейсу, щоб робити такі речі, як форми сюжету (реалізація консолі може трактувати консоль як деяке 80xN "зображення" з ASCII art). Звичайно, це надуманий приклад, оскільки це, як правило, не те, що ви хочете зробити, це обробляти консольний вихід, як буфер зображення / кадру; як правило, більшість потреб користувача викликають більше текстових взаємодій у консолях.
Інша думка - наскільки легко спроектувати стійку абстракцію? Тому що це може бути просто, якщо все, на що ви орієнтуєтесь, - це сучасні графічні інтерфейси API, щоб відмовитись від основних можливостей малювання фігур, таких як побудова ліній, прямокутників, контурів, тексту, подібних речей (просто проста двовимірна растеризація обмеженого набору примітивів) , з одним абстрактним інтерфейсом, який можна легко реалізувати для них за допомогою різних підтипів з невеликими витратами. Якщо ви можете ефективно спроектувати таку абстракцію та застосувати її на всіх цільових платформах, то я б сказав, що це набагато менше зла, якщо взагалі зла, для форми чи керування графічним інтерфейсом, або що б там не було відомо, як намалювати себе за допомогою такого абстракція.
Але скажіть, що ви намагаєтесь вилучити деталі горі, які залежать від Playstation Portable, iPhone, XBox One та потужного ігрового ПК, тоді як ваші потреби полягають у використанні найсучасніших методів 3D-рендерінгу / затінення в режимі реального часу на кожному. . У цьому випадку спроба розробити один абстрактний інтерфейс для абстрагування деталей візуалізації, коли основні апаратні можливості та API змінюються настільки дико, що майже впевнено призводить до величезного часу проектування та повторного проектування, велика ймовірність повторних змін дизайну з непередбачуваними. відкриття, а також рішення найменшого загального знаменника, яке не може використати повну унікальність та потужність базового обладнання.
Створення залежних потоків до стабільних, "Легких" конструкцій
В моєму полі я в тому останньому сценарії. Ми орієнтовані на безліч різноманітних апаратних засобів, що мають принципово різні основні можливості та API, і намагатися придумати одну рендеринг / малювання абстракції, щоб керувати ними всіма, є безнадійними прикордонними (ми можемо стати всесвітньо відомими, просто роблячи це ефективно, як це була б гра зміна в галузі). Тому останнім , що я хочу в моєму випадку це як аналогова Shapeабо Modelабо Particle Emitterщо вміє малювати себе, навіть якщо він висловлює , що малюнок на найвищому рівні і , можливо , найбільш абстрактний спосіб ...
... тому що ці абстракції занадто важкі для правильного проектування, і коли дизайн важко виправити, і все залежить від цього, це рецепт найдорожчих змін у центральному дизайні, які пульсують і порушують все залежно від нього. Отже, останнє, що ви хочете, - це залежність у ваших системах надходити до абстрактних конструкцій занадто важко, щоб виправитись (занадто важко стабілізуватись без нав'язливих змін).
Складне залежить від легкого, не просто залежить від складного
Тож те, що ми робимо замість цього, - змусити залежності залежати від речей, які легко спроектувати. Набагато простіше спроектувати абстрактну "Модель", яка орієнтована лише на зберігання таких речей, як багатокутники та матеріали, і зробити цю конструкцію правильною, ніж спроектувати абстрактний "Візуалізатор", який може ефективно реалізовуватися (за допомогою змінних підтипів бетону) для сервісного малювання запити рівномірно для апаратних засобів, настільки ж відмінних, як PSP від ПК.

Таким чином ми перевертаємо залежності від речей, які важко спроектувати. Замість того, щоб абстрактні моделі знали, як звернути себе до абстрактного дизайну рендерінгу, від якого всі вони залежать (і порушити їх реалізацію, якщо цей дизайн зміниться), ми натомість маємо абстрактного рендерінга, який знає, як намалювати кожен абстрактний об'єкт на нашій сцені ( моделі, випромінювачі частинок тощо), і тому ми можемо потім реалізувати підтип OpenGL-рендеріра для таких ПК, як RendererGlдля інших PSP RendererPsp, інших, для мобільних телефонів тощо. У такому випадку залежність залежить від стабільних конструкцій, їх легко виправити, від рендерінгу до різних типів сутностей (моделей, частинок, текстур тощо) на нашій сцені, а не навпаки.

- Я використовую "стабільність / нестабільність" у дещо іншому сенсі від аферентної / еферентної муфти дядька Боба, яка вимірює більше складність змін, наскільки я можу зрозуміти. Я говорю більше про "ймовірність вимагати змін", хоча його показник стабільності корисний там. Коли "ймовірність змін" пропорційна "простоті змін" (напр .: речі, які, швидше за все, потребують змін, мають найвищу нестабільність і афективні зв'язки з метрики дядька Боба), то будь-які такі ймовірні зміни є дешевими і не нав'язливими. , вимагаючи лише заміни реалізації, не торкаючись жодних центральних конструкцій.
Якщо ви намагаєтесь відрегулювати щось на центральному рівні кодової бази, і це зробити занадто складно, а не вперто бити головами об стіни і постійно вносити в нього нав'язливі зміни щомісяця / року, що вимагає оновлення 8000 вихідних файлів, оскільки це розбиваючи все, що від цього залежить, моя пропозиція номер один - це врахувати, як перевернути залежності. Подивіться, чи можете ви написати код таким чином, що річ, яку важко спроектувати, залежить від усього іншого, що спростити дизайн, не маючи речей, які легше розробити, залежно від того, що так важко розробити. Зауважте, що я говорю про конструкції (конкретно конструкції інтерфейсу), а не про їх реалізацію: іноді речі легко спроектувати і важко реалізувати, а іноді речі важко спроектувати, але легко виконати. Залежності протікають до проектів, тому слід зосередити увагу лише на тому, наскільки важко щось тут розробити, щоб визначити напрямок, в якому протікають залежності.
Принцип єдиної відповідальності
Для мене SRP тут не так цікавий (хоча залежно від контексту). Я маю на увазі, що в проекті речей, які є зрозумілими за призначенням і є реальними, є чіткий балансуючий акт, але вашим Shapeоб'єктам, можливо, доведеться розкрити більш детальну інформацію, якщо вони не знають, як намалювати себе, наприклад, і, можливо, не дуже багато значущих речей робити з формою в конкретному контексті використання, ніж будувати її та малювати. Існують компроміси з майже всім, і це не пов'язане з SRP, що дозволяє зрозуміти, як зробити себе здатним стати таким кошмаром технічного обслуговування в моєму досвіді в певних контекстах.
Це набагато більше стосується зв'язку та напрямку, в якому залежать потоки вашої системи. Якщо ви намагаєтесь перенести абстрактний інтерфейс візуалізації, від якого все залежить (оскільки вони використовують його для малювання) до нового цільового API / апаратного забезпечення та розумієте, що вам доведеться значно змінити його дизайн, щоб він там працював ефективно. це дуже дорога зміна, яка потребує заміни реалізацій у вашій системі, яка вміє малювати себе. І це найпрактичніше питання технічного обслуговування, з яким я стикаюсь із речами, які знають, як намалювати себе, якщо це означає судно залежностей, що тягнуться до абстракцій, які занадто складно правильно скласти наперед.
Гордість для розробників
Я згадую цей момент, тому що, на мій досвід, це найчастіше є найбільшою перешкодою для протікання напрямку залежностей до речей, які легше спроектувати. Розробникам дуже легко стати тут трохи амбітним і сказати: "Я буду розробляти міжплатформенну абстракцію, щоб керувати ними всіма. Я вирішу, що інші розробники витрачають місяці на перенесення, і я збираюся отримати це правильно, і це буде працювати як магія на кожній платформі, яку ми підтримуємо і використовуємо найсучасніші методи візуалізації на кожній; я вже передбачив це в своїй голові ".У такому випадку вони чинять опір практичному рішенню, яке полягає у тому, щоб уникнути цього, а просто перевернути напрямок залежностей і перекласти те, що може бути надзвичайно дорогим і повторюваним змін центрального дизайну в просто дешеві та локальні постійні зміни в реалізації. У розробниках має бути якийсь інстинкт "білого прапора", щоб відмовитися, коли щось занадто важко спроектувати до такого абстрактного рівня та переглянути всю їхню стратегію, інакше вони мають багато горя і болю. Я б запропонував передати такі амбіції та бойовий дух на сучасні втілення в життя простішої речі, ніж підняти такі амбіційні світові амбіції до рівня дизайну інтерфейсу.