ИТ развој

Architecture's Hidden Cost: When Maintainability Becomes a Burden

Скриената цена на архитектурата: Кога одржливоста станува товар

Најскапата архитектура не е секогаш онаа што откажува под оптоварување. Често, тоа е онаа што работи совршено добро, но прави секоја вообичаена промена да изгледа како преговарање со минатото.

Тимовите за бекенд се учат да ја ценат поделбата на одговорности, проширливоста, јасните граници и дизајнот отпорен на иднината. Тоа се вредни цели. Проблемот почнува кога архитектурата престанува да ја намалува сложеноста и почнува да ја прераспределува во слоеви, апстракции, конвенции и сервиси што сите мора да се разберат пред развивачот безбедно да може да промени едно поле во API-одговор.

Одржливоста е суштинска. Но, одржливоста не се мери според тоа колку обрасци користи системот. Таа се мери според тоа колку уверено способен развивач може да го разбере, промени, тестира и управува системот.

Апстракцијата има оперативен трошок

Секоја апстракција ветува дека ќе поедностави нешто. Репозиториумот ги крие деталите за перзистенцијата. Сервисниот слој ги централизира деловните правила. Редицата за пораки ги раздвојува работните оптоварувања. Локална околина базирана на Docker ги прави зависностите репродуктивни. Секој од нив може да биде вистинскиот избор.

Секој додава и постојан трошок: повеќе патеки низ кодот, повеќе конфигурација, повеќе начини на откажување и повеќе концепти што новите придонесувачи мора да ги научат. Трошокот не е теоретски. Тој се појавува при дебагирање, одговор на инциденти, воведување нови членови, промени на шемата и рутинска работа на функционалности.

Разгледајте едноставен PHP endpoint што ја ажурира претпочитаната поставка на клиентот за известувања. Во мала апликација, барањето може да тече од контролер до правило за валидација, доменски сервис и ORM модел. Тоа може да биде јасно и соодветно.

Во претерано изградена верзија, истото ажурирање може да помине низ команден објект, обработувач на команди, апликациски сервис, доменски агрегат, интерфејс на репозиториум, имплементација на репозиториум, диспечер на настани, асинхрон слушач, проекција на модел за читање и претплатник за невалидирање на кешот. Првичната операција не станала позначајна. Таа едноставно добила повеќе места на кои може да биде погрешна.

Прашањето не е дали секој слој е оправдан изолирано. Повеќето се. Прашањето е дали комбинираната структура ја прави следната промена полесна отколку што би ја направил поедноставен дизајн.

Одржливоста е локална, не церемонијална

Тимовите понекогаш ја мешаат архитектонската церемонија со одржливоста. Кодна база може да има строги конвенции за именување, интерфејси околу секоја зависност и внимателно слоевита структура на директориуми, а сепак да остане тешка за менување.

Одржлив систем ги прави важните односи видливи. Кога се менува API поле, развивачите треба да можат да најдат каде се валидира, перзистира, сериализира и тестира без да следат лавиринт од генерички помошници.

Тоа не значи да се стави сè во еден контролер или да се напуштат границите. Тоа значи да се изберат граници што одговараат на реалните обрасци на промени. Ако апликацијата има вистински деловни текови, сервисен или доменски слој може да ги разјасни. Ако има повеќе имплементации за складирање, апстракцијата на репозиториум може да биде вредна. Ако ниту еден услов не постои, додавањето на тие структури „заради доследност“ може да го направи кодот помалку искрен.

Претпочитајте имиња што ја откриваат работата

Генеричките апстракции се особено скапи бидејќи ја кријат намерата. Класа именувана Processor или Manager му кажува речиси ништо на читателот. Класа именувана SubscriptionCancellationService создава непосреден ментален модел за нејзината одговорност.

Истиот принцип важи и за пристапот до базата на податоци. Тесно фокусиран метод за барање како findOverdueInvoicesForAccount() често соопштува повеќе од широк API на репозиториум составен од повторно употребливи филтри. Повторната употреба е корисна кога однесувањето навистина се дели. Таа е штетна кога ги принудува читателите да реконструираат деловно барање од неколку генерички градбени блокови.

Дистрибуираните системи го умножуваат товарот за одржување

Разделувањето на монолит на сервиси може да реши реални проблеми: независно скалирање, посебна одговорност за распоредување, изолирани безбедносни граници или различни барања за доверливост. Исто така, може да ги претвори обичните повици на методи во мрежни договори.

Штом барањето премине преку границите на процесите, тимот мора да управува со истекување на време, повторни обиди, идемпотентност, автентикација, верзионирање, набљудливост, делумен неуспех и конзистентност на податоците. Ова не се детали за имплементација што се додаваат подоцна. Ова е архитектурата.

Повторниот обид ја илустрира поентата. Повторувањето на неуспешно HTTP барање може да биде правилно за безбедно читање. Повторувањето на барање за креирање плаќање без стратегија за идемпотентност може да создаде дупликат наплати. Повторувањето на потрошувач на пораки без трансакциско ракување може двапати да го запише истиот запис во базата на податоци. Редицата не е едноставно побрз повик на функција со одложено извршување.

Пред да извлечете сервис, прашајте дали границата за распоредување одразува трајна организациска или оперативна потреба. Ако главната причина е почист код, модуларен монолит може да обезбеди најголем дел од јасноста без мрежната сложеност.

  • Одржувајте ги модулите независни во една апликација што се распоредува кога нивните податоци и ритамот на изданија остануваат тесно поврзани.
  • Извлечете сервис кога му е потребна независна сопственост, скалирање, безбедносни контроли или карактеристики на достапност.
  • Дефинирајте го однесувањето при неуспех пред интеграцијата: ограничувања за истекување на време, правила за повторен обид, очекувања за идемпотентност и исходи видливи за корисникот.
  • Изложете значајни метрики и логови на секоја далечинска граница, бидејќи дебагирањето во продукција не може да се потпира на локални претпоставки.

Дизајнот на базата на податоци треба да му служи на системот што го имате

Одлуките за базата на податоци се уште еден чест извор на архитектонско претерување. Високо нормализирана шема може да го зачува интегритетот и да го намали дуплирањето, но може и да ги направи вообичаените читања скапи и тешки за разбирање. Денормализиран документ може да поедностави патека за читање, но ја префрла работата за конзистентност во апликацискиот код.

Ниту еден пристап не е автоматски поодржлив. Корисното прашање е: кои операции мора да останат едноставни, доверливи и брзи?

На пример, ако административна контролна табла постојано има потреба од сметка, нејзиниот активен план, нејзината најнова фактура и неколку агрегатни броења, принудувањето на секое барање да поминува низ долг синџир на ORM релации може да сокрие неефикасен план за барање. Експлицитно барање за читање, намерен индекс или мал модел за читање може да биде полесен за одржување бидејќи го прави барањето за перформанси видливо.

ORM-ите се продуктивни, но не го отстрануваат однесувањето на базата на податоци. Развивачите сè уште треба да ги разбираат трансакциите, заклучувањето, бројот на барања, индексите и безбедноста на миграциите. Миграција што додава колона што не дозволува null, пополнува голема табела и распоредува код што го очекува новото поле одеднаш може да создаде оперативен ризик, дури и кога PHP кодот е елегантен.

Дизајнирајте промени за безбедно воведување

Промените на шемата често имаат корист од фазно распоредување. Прво додадете компатибилна промена на шемата. Потоа распоредете код што може да работи и со старите и со новите претставувања. Пополнете податоци каде што е потребно. Конечно, отстранете ги застарените патеки откако транзицијата ќе заврши.

Овој редослед може да изгледа помалку уреден од една миграција, но ја почитува реалноста дека апликацискиот код, состојбата на базата на податоци, позадинските работници и распоредените контејнери не се менуваат секогаш во точно истиот момент.

Docker треба да го намали триењето, а не да симулира продукциски лавиринт

Контејнерите се вредни кога го прават локалното поставување повторливо и зависностите експлицитни. Тие стануваат товар кога на развивачот му требаат десетина сервиси, неколку датотеки со тајни и долг водич за решавање проблеми само за да изврши мала гранка на функционалност.

Корисната локална околина фаворизира брз пат. Развивачите треба да можат да ја стартуваат апликацијата, да извршуваат тестови, да ги прегледуваат логовите и да ресетираат привремени податоци со разбирливи команди. Паритетот со продукција е важен, но совршената имитација ретко е практична. Локалната околина треба да ги репродуцира ризиците што се важни, а не секој инфраструктурен детаљ.

Истото важи за CI конфигурацијата, ознаките за функционалности, слоевите за кеширање и каналите за распоредување. Сложеноста што штити значајно ограничување е инвестиција. Сложеноста што постои само затоа што „сериозните системи го прават тоа на овој начин“ обично е долг со одлична документација.

Практичниот тест за архитектура

Пред да воведете нов слој, сервис, функционалност на рамка или зависност од платформа, поставете неколку директни прашања:

  • Кој конкретен проблем го решава ова денес?
  • Која промена ќе стане полесна откако ќе постои?
  • Кои нови начини на откажување и оперативни задачи ги воведува?
  • Може ли тимот да го објасни и тестира без да се потпира на еден специјалист?
  • Дали поедноставен дизајн би го исполнил тековното барање со јасен пат за надградба?

Нема награда за најразработен дијаграм на архитектура. Доброто инженерство остава простор за раст без да го принудува сегашниот систем да ја носи целата тежина на хипотетичните иднини.

Најдобрите одржливи системи не се оние со најмалку одлуки. Туку оние чии одлуки остануваат разбирливи. Кога архитектурата ја прави секојдневната работа помирна, побезбедна и побрза, таа го оправдува својот трошок. Кога прави едноставните промени да изгледаат опасни, време е да се отстрани слој, да се спојат сервиси, да се поедностави договор или со сигурност да се избере здодевното решение.

Портрет на автор на блогот

Mihajlo

Јас сум Михајло - развивач поттикнат од љубопитност, дисциплина и постојаната желба да создадам нешто значајно. Споделувам увиди, упатства и бесплатни услуги за да им помогнам на другите да ја поедностават својата работа и да растат во постојано развивачкиот свет на софтверот и вештачката интелигенција.