Архитектирање на PHP бекенд-системи надвор од трендовите за вистинска одржливост
Архитектурата на бекендот лесно може да се прекомплицира кога секоја нова функционалност на рамка, образец за база на податоци или алатка за распоредување се претставува како следниот неопходен стандард. Долготрајниот PHP бекенд ретко е оној што ги прифаќа најмногу трендови. Тоа е оној што ги прави промените безбедни, однесувањето разбирливо, а операциите доволно рутински за развивачите да можат да се фокусираат на работата на производот.
Одржливоста не е визуелен стил. Таа е практична способност да се одговорат вообичаени прашања без долга истрага: каде ова барање влегува во системот, кои правила го одредуваат исходот, кои податоци се менуваат и како може да се опорави од неуспех? PHP и понатаму е добар избор за оваа работа кога неговите апликации се дизајнирани околу јасни граници, наместо околу модерни апстракции.
Почнете со обликот на промената
Архитектурата треба да одразува како се менува бизнисот, а не како рамката ги организира директориумите. Мала апликација може да биде совршено здрава со контролери, сервиси и модели. Меѓутоа, како што правилата стануваат посложени, сместувањето на сè во генерички слој на сервиси често создава збирка од големи класи што истовремено знаат премногу за HTTP, перзистенција и деловна политика.
Покорисна разлика е онаа меѓу аспектите на испорака и одлуките во доменот. Контролерот преведува HTTP барање во апликациска команда. Апликацискиот сервис ја координира работата. Кодот на доменот ги изразува правилата. Инфраструктурниот код се справува со детали како SQL, редици, складирање датотеки и надворешни API.
final class CreateSubscription
{
public function __construct(
private SubscriptionRepository $subscriptions,
private BillingGateway $billing
) {
}
public function handle(CreateSubscriptionRequest $request): Subscription
{
$subscription = Subscription::start(
customerId: $request->customerId,
plan: $request->plan
);
$this->billing->createCustomerSubscription($subscription);
$this->subscriptions->save($subscription);
return $subscription;
}
}
Ова не е барање за разработен дизајн воден од доменот. Поентата е едноставно дека правилото за започнување претплата е видливо, тестирачко и не е скриено во контролер или ORM повратен повик. Користете побогати обрасци кога правилата ги оправдуваат; избегнувајте да создавате апстракција за правило што сè уште не постои.
Направете го API договорот експлицитен
API-јата стануваат тешки за одржување кога нивниот договор е подразбран од кодот на контролерот, колоните во базата на податоци и претпоставките на клиентот. Третирајте ги барањата и одговорите како намерно дефинирани јавни интерфејси, дури и за внатрешно API. Валидирајте го влезот на границата, враќајте конзистентни форми на грешки и избегнувајте директно изложување на модели за перзистенција.
Поле во база на податоци наречено status може да биде корисно интерно, но на API клиентот му треба да знае кои вредности се валидни, кои транзиции се дозволени и што се случува кога барањето се повторува. Овие прашања се архитектонски, а не само прашања за документација.
- Користете стабилни идентификатори на ресурси наместо да откривате последователни ID на базата на податоци таму каде што тоа создава поврзаност или несакано изложување.
- Дефинирајте ги грешките при валидација конзистентно, вклучувајќи машински читливо име на поле кога е соодветно.
- Дизајнирајте ги крајните точки за запишување имајќи го предвид однесувањето при повторен обид, особено кај плаќања, вебхукови и поднесување задачи.
- Верзионирајте само кога промената што ја нарушува компатибилноста е неизбежна; дополнителните промени обично полесно се поддржуваат.
Идемпотентноста е особено вредна во дистрибуирани системи. Ако клиентот истече по испраќањето барање, може безбедно да се обиде повторно само кога серверот може да препознае дека бараната акција веќе се случила. Ова може да бара клуч за идемпотентност, ограничување на единственост или внимателно моделирана транзиција на состојба. Повторен обид што тивко создава втора нарачка не е мрежен проблем; тоа е недостасувачка деловна гаранција.
Нека базата на податоци ја заштити вистината
Валидацијата во апликацијата ја подобрува повратната информација за корисникот, но не може да биде конечен авторитет за интегритетот на податоците. Истовремени барања, работници во заднина, увози и скрипти за одржување можат да ги заобиколат претпоставките направени во една кодна патека. Важните инваријанти треба да бидат одразени во базата на податоци.
Користете надворешни клучеви кога релациите мора да постојат, ограничувања на единственост кога дупликатите се невалидни и трансакции кога неколку промени мора заедно да успеат или да не успеат. Апликацијата треба да ги преведува неуспесите на базата на податоци во корисно однесување, но не треба да се преправа дека може сама да го спроведе интегритетот.
На пример, проверката дали постои е-поштена адреса пред вметнување корисник е корисна, но не е доволна при истовременост. Уникатниот индекс е вистинската гаранција. PHP кодот треба да се обиде да го изврши вметнувањето, предвидливо да обработи неуспех поради дупликатен клуч и да го врати соодветниот API одговор.
Држете ги прашањата блиску до нивната цена
ORM-ите се продуктивни, но не ја отстрануваат потребата да се разбере SQL. Внимавајте на неограничени множества на резултати, повторени прашања во циклуси, недостасувачки индекси и крајни точки што вчитуваат цел граф на објекти за да прикажат мал одговор. Читливо прашање што избира точно што ѝ треба на една крајна точка често е поодржливо од паметен синџир на ORM повици.
Работата на перформансите треба да следи докази. Воспоставете корисни метрики и логови за барањата, репродуцирајте ја бавната патека, прегледајте го генерираното прашање и неговиот план за извршување, па потоа менувајте по една работа. Кеширањето може да биде вредно, но кеш додаден пред да се разбере прашањето или образецот на пристап често создава проблеми со поништување што го надживуваат првичното тесно грло.
Користете Docker за да ги намалите разликите, не за да ги скриете
Контејнерите се најкорисни кога ги прават средините за локален развој, континуирана интеграција и продукција попредвидливи. PHP апликацијата треба јасно да ги наведе своите потреби за извршување: PHP верзија, потребни екстензии, веб-сервер или менаџер на процеси, инсталација на зависности и конфигурација обезбедена преку околината.
Одржувајте ја сликата на контејнерот фокусирана. Не вградувајте тајни во неа. Не потпирајте се на зависности само за развој во продукциска слика. Извршувајте миграции на базата на податоци како експлицитен чекор при распоредување, наместо како изненадувачки несакан ефект од секое стартување на апликацијата, освен ако оперативниот модел не е дизајниран специјално за такво однесување.
composer install --no-dev --prefer-dist --optimize-autoloader
php bin/console cache:warmup
php bin/console doctrine:migrations:migrate --no-interaction
Точните команди варираат според рамката, но принципот е стабилен: инсталацијата на зависности, загревањето на кешот и промените на шемата треба да бидат видливи и јасно да не успеваат. Распоредување што делумно успева мора да има познат пат за опоравување. Промени на базата на податоци компатибилни наназад, постепено активирање функционалности и реверзибилни миграции го намалуваат ризикот рутинското издание да се претвори во инцидент.
Дизајнирајте ги неуспесите како нормални патеки
Надворешните услуги откажуваат, редиците ја одложуваат работата, базите на податоци одбиваат врски, а корисниците го поднесуваат истото барање двапати. Зрелите системи ги признаваат овие услови во кодот и операциите. Истекувањата треба да бидат намерни. Повторните обиди треба да бидат ограничени и сведени на неуспеси што може да успеат подоцна. Задачите во заднина треба да запишат доволно контекст за дијагностицирање неуспеси без непотребно складирање чувствителни податоци.
Логирањето треба да помогне да се реконструира барање низ слоевите. Вклучете идентификатор за корелација, релевантни идентификатори на ресурси и исходот од важните операции. Избегнувајте да логирајте ингеренции, заглавија за авторизација, необработени податоци за плаќање или неселективни тела на барања. Набљудливоста е корисна само кога останува безбедна и читлива под притисок.
Изберете ја наједноставната архитектура што ги зачувува опциите
Нема доблест во присилувањето скромна PHP апликација во микросервиси, извори на настани или сложен систем на приклучоци пред нејзините проблеми да го бараат тоа. Добро структуриран модуларен монолит може долго време да обезбедува јасни граници, едноставно дебагирање и едноставни трансакции. Разделувањето услуги станува вредно кога потребите за независно распоредување, скалирање, сопственост или сигурност се конкретни — не кога дијаграмот изгледа помодерно.
Најодржливиот бекенд не е замрзнат на место. Тој е организиран така што утрешната промена има очигледно место, ограничен радиус на влијание и тестирачки исход. Во PHP, тоа обично значи експлицитни граници, искрени ограничувања на базата на податоци, предвидливи практики за распоредување и подготвеност да се претпочита јасност пред новина. Трендовите минуваат. Системот што неговиот тим може самоуверено да го менува е архитектурата што трае.