ИТ развој

Architectural Debt: How to Pay Down Maintainability Before It Bankrupts Your Project

Архитектонски долг: Како да ја отплатите одржливоста пред да го банкротира вашиот проект

Архитектонскиот долг ретко се појавува како драматичен неуспех. Почесто се појавува како безопасен исклучок: уште еден услов во контролер, една крајна точка што директно пребарува табела, едно Docker заобиколно решение што „ќе се исчисти подоцна“. Секој избор може да биде разумен изолирано. Заедно, тие ја прават вообичаената работа побавна, поризична и потешка за објаснување.

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

Архитектонскиот долг е повеќе од стар код

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

Една PHP апликација може да биде чисто форматирана, добро тестирана, а сепак да носи сериозен архитектонски долг. Размислете за кодна база во која секој контролер содржи валидација, авторизација, деловни правила, пребарувања во базата на податоци и повици кон API од трети страни. Можеби ништо не е видливо расипано, но секоја нова крајна точка зацврстува структура во која HTTP-грижите и однесувањето на доменот не можат да се раздвојат.

Предупредувачките знаци обично се однесувачки, а не естетски:

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

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

Прво пронајдете ги скапите патеки

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

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

Мапирајте одговорности, не само датотеки

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

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

final class PlaceOrder
{
    public function __construct(
        private OrderRepository $orders,
        private PaymentGateway $payments,
    ) {}

    public function handle(PlaceOrderRequest $request): Order
    {
        $order = Order::fromRequest($request);

        $this->payments->authorize($order->total(), $request->paymentToken());
        $this->orders->save($order);

        return $order;
    }
}

Ова не е барање за разработени слоеви. Тоа е начин операцијата да се направи тестирувачка и на идните промени да им се даде стабилен дом. HTTP контролерот може да преведе барање во PlaceOrderRequest; случајот на употреба го поседува работниот тек; инфраструктурата ги имплементира деталите за складирањето и платежниот портал.

Намалувајте го долгот преку разграничувања

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

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

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

Правете ги трансакциите намерни

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

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

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

Задржете ги операциите како дел од архитектурата

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

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

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

Мерете го напредокот според отстранетото триење

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

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

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

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

Mihajlo

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