Я переглянув кілька відповідей і шукав у Google, але не зміг знайти нічого корисного (тобто, що не мало б ніяких побічних ефектів).
Моя проблема, абстрактно, полягає в тому, що у мене є об'єкт і потрібно виконувати довгу послідовність операцій над ним; Я думаю про це як про якусь складальну лінію, як про побудову машини.
Я вважаю, що ці об'єкти будуть називатися методами об'єктів .
Тож у цьому прикладі в якийсь момент я мав би CarWithoutUpholstery, на якій мені тоді потрібно запустити installBackSeat, installFrontSeat, installWoodenInserts (операції не заважають одна одній, і навіть можуть бути виконані паралельно). Ці операції виконуються CarWithoutUpholstery.worker () і дають новий об'єкт, який би був CarWithUpholstery, на якому я б тоді запустив, можливо, cleanInsides (), verifyNoUpholsteryDefects () тощо.
Операції в одну фазу вже є незалежними, тобто я вже бореться з їх підмножиною, яка може бути виконана в будь-якому порядку (переднє і заднє сидіння можуть бути встановлені в будь-якому порядку).
Наразі моя логіка використовує Reflection для простоти реалізації.
Тобто, коли у мене є CarWithoutUpholstery, об'єкт перевіряє себе на предмет методів, які називаються performSomething (). У цей момент він виконує всі ці методи:
myObject.perform001SomeOperation();
myObject.perform002SomeOtherOperation();
...
перевіряючи помилки та інше. Незважаючи на те, що порядок роботи є неважливим, я призначив лексикографічний наказ у випадку, якщо я коли-небудь виявляю якийсь порядок, важливий зрештою. Це суперечить YAGNI , але це коштувало дуже мало - простий сорт () - і це могло б врятувати масовий метод перейменування (або запровадити якийсь інший метод виконання тестів, наприклад, масив методів) вниз.
Інший приклад
Скажімо, що замість того, щоб будувати автомобіль, я повинен скласти звіт про секретну поліцію про когось і подати його моєму Evil Overlord . Моїм кінцевим об’єктом буде ReadyReport. Для його побудови я починаю з збору основної інформації (ім'я, прізвище, дружина ...). Це моя фаза А. Залежно від того, є подружжя чи ні, мені, можливо, доведеться перейти до фаз B1 або B2 і зібрати дані про сексуальність на одного або двох людей. Це складається з декількох різних запитів до різних Evil Minions, які контролюють нічне життя, вуличні камери, квитанції про продаж секс-магазинів і що ні. І так далі, і так далі.
Якщо у потерпілого немає родини, я навіть не вступлю до фази отримання інформації про сім'ю, але якщо це зробити, то неважливо, чи спочатку я націлююсь на батька чи матір чи братів і сестер (якщо такі є). Але я не можу цього зробити, якщо я не виконав FamilyStatusCheck, який, отже, належить до більш ранньої фази.
Це все чудово працює ...
- якщо мені потрібна додаткова операція, мені потрібно лише додати приватний метод,
- якщо операція є загальною для декількох фаз, я можу її успадкувати від суперкласу,
- операції прості та самостійні. Ні одне значення з однієї операції не завжди вимагає будь - якого з інших (операцій , які дійсно виконуються в іншій фазі),
- об'єктам вниз лінії не потрібно виконувати багато тестів , так як вони не могли навіть існувати , якщо їх об'єкти творці не перевірили ті умови , в першу чергу. Тобто, розміщуючи вставки на приладовій панелі, прибираючи приладну панель і перевіряючи приладову панель, мені не потрібно перевіряти, що приладова панель насправді є .
- це дозволяє легко протестувати. Я можу легко знущатися над частковим об’єктом і запускати на ньому будь-який метод, а всі операції є детермінованими чорними полями.
... але ...
Проблема виникла, коли я додав одну останню операцію в один із моїх об'єктів методу, через що загальний модуль перевищив обов'язковий індекс складності ("менше N приватних методів").
Я вже взяв цю справу наверх і припустив, що в цьому випадку багатство приватних методів не є повістю катастрофи. Складність є , але вона є тому, що операція є складною, а насправді це не все так складно - вона просто довга .
Використовуючи приклад Evil Overlord, моя проблема полягає в тому, що Злий Оверлорд ( він же, хто не повинен відмовлятись ), запитуючи всю дієтичну інформацію, мої дієтичні мініони говорять мені, що мені потрібно запитувати ресторани, кухонні куточки, вуличні торговці, неліцензовані торгові вулиці, парник власники тощо, і Злий (суб) Оверлорд - відомий під назвою Той, Хто також не повинен бути відхилений - скаржиться, що я виконую надто багато запитів у фазі GetDietaryInformation.
Примітка . Я усвідомлюю, що з кількох точок зору це зовсім не проблема (ігнорування можливих проблем з роботою тощо). Все, що відбувається, полягає в тому, що конкретний показник нещасний, і для цього є виправдання.
Що я думаю, я міг би зробити
Окрім першого, усі ці варіанти є придатними і, я думаю, захисними.
- Я переконався, що я можу бути підлим і заявляю половину своїх методів
protected
. Але я б використовував слабкість у процедурі тестування, і окрім того, що виправдовувати себе, коли потрапляють, мені це не подобається. Також це міра зупинки. Що робити, якщо кількість необхідних операцій подвоїться? Навряд чи, але що тоді? - Я можу розділити цю фазу довільно на AnnealedObjectAlpha, AnnealedObjectBravo та AnnealedObjectCharlie і мати третину операцій, що виконуються на кожному етапі. Мені здається, що це фактично додає складності (ще N-1 класи), без користі, крім проходження тесту. Звичайно, я можу стверджувати, що CarWithFrontSeatsInstalled та CarWithAllSeatsInstalled є логічно послідовними етапами. Ризик того, що Альфа пізніше вимагатиме методу Браво, невеликий і навіть менший, якщо я добре його зіграю. Але все ж.
- Я можу купувати різні операції, віддалено схожі, в одній.
performAllSeatsInstallation()
. Це лише міра зупинки, яка збільшує складність однієї операції. Якщо мені коли-небудь потрібно буде робити операції A і B в іншому порядку, і я запакував їх всередині E = (A + C) і F (B + D), мені доведеться роз'єднати E і F і перетасувати код навколо . - Я можу використовувати масив лямбда-функцій і акуратно пройти повний чек, але я вважаю це незграбним. Однак це найкраща альтернатива поки що. Це позбулося б роздумів. Дві проблеми, які у мене є, полягають у тому, що мене, мабуть, попросять переписати всі об'єкти методу, не лише гіпотетичні
CarWithEngineInstalled
, і хоча це було б дуже гарною безпекою роботи, вона насправді не дуже сподобається; і що перевірка покриття коду має проблеми з лямбдами (які вирішуються, але все-таки ).
Тому...
- Який, ти думаєш, мій найкращий варіант?
- Чи є кращий спосіб, який я не розглядав? ( можливо, я б краще прийшов чистий і прямо запитав, що це? )
- Хіба що цей дизайн безнадійно хибний, і я краще визнаю поразку та рів - ця архітектура взагалі? Не годиться для моєї кар’єри, але чи було б написання погано розробленого коду в майбутньому краще?
- Чи є моїм поточним вибором насправді єдиний вірний шлях, і мені потрібно боротись, щоб встановити якісні показники (та / або інструментарій)? Для цього останнього варіанту мені знадобляться посилання ... Я не можу просто помахати рукою на @PHB під час бурчання. Це не ті показники, які ви шукаєте . Скільки б я не хотів би вміти