paint-brush
Kaip susidoroti su sudėtingumu kuriant programinės įrangos sistemaspateikė@fairday
64,370 skaitymai
64,370 skaitymai

Kaip susidoroti su sudėtingumu kuriant programinės įrangos sistemas

pateikė Aleksei23m2024/02/05
Read on Terminal Reader
Read this story w/o Javascript

Per ilgai; Skaityti

Sudėtingumas yra priešas! Išmokime su tuo susitvarkyti!
featured image - Kaip susidoroti su sudėtingumu kuriant programinės įrangos sistemas
Aleksei HackerNoon profile picture

Kas tai yra?

Kasdien, kiekvieną akimirką savo inžinierinės karjeros metu susiduriame su daugybe įvairiausių įvairaus sudėtingumo problemų ir situacijų, kai dėl duomenų trūkumo turime priimti sprendimą arba jį atidėti. Kurdami naujas paslaugas, kurdami infrastruktūrą ar net kurdami plėtros procesus, paliečiame didžiulį įvairių iššūkių pasaulį.


Sunku, o gal net neįmanoma, išvardyti visas problemas. Su kai kuriomis iš šių problemų susidursite tik dirbdami konkrečioje nišoje. Kita vertus, yra daug dalykų, kuriuos visi turime suprasti, nes jie yra labai svarbūs kuriant IT sistemas. Labai tikėtina, kad su jais susidursite visuose projektuose.


Šiame straipsnyje pasidalinsiu savo patirtimi, susijusia su kai kuriomis problemomis, su kuriomis susidūriau kurdamas programinę įrangą.

Kas yra bendras susirūpinimas?

Jei pažvelgsime į Vikipediją, rasime tokį apibrėžimą


Kuriant į aspektus orientuotą programinę įrangą, kompleksinės problemos yra programos aspektai, kurie turi įtakos keliems moduliams, be galimybės būti įtraukti į vieną iš jų. Šios problemos dažnai negali būti aiškiai atskirtos nuo likusios sistemos tiek kuriant, tiek įgyvendinant, todėl gali atsirasti išsklaidymas (kodo dubliavimas), susipainiojimas (reikšminga sistemų priklausomybė) arba abu.


Tai puikiai apibūdina, kas tai yra, bet noriu jį šiek tiek išplėsti ir supaprastinti:

Visapusiškas rūpestis yra sistemos/organizacijos sąvoka arba komponentas, turintis įtakos daugeliui kitų dalių.


Geriausi tokių problemų pavyzdžiai yra sistemos architektūra, registravimas, sauga, operacijų valdymas, telemetrija, duomenų bazės dizainas ir daugelis kitų. Daugelį iš jų aptarsime vėliau šiame straipsnyje.


Kodo lygmeniu kompleksinės problemos dažnai įgyvendinamos naudojant tokius metodus kaip į aspektą orientuotas programavimas (AOP) , kai šios problemos yra moduliuojamos į atskirus komponentus, kurie gali būti taikomi visoje programoje. Dėl to verslo logika yra atskirta nuo šių problemų, todėl kodas tampa lengviau skaitomas ir prižiūrimas.

Aspektų klasifikacija

Yra daug galimų būdų, kaip klasifikuoti aspektus segmentuojant juos su skirtingomis savybėmis, tokiomis kaip apimtis, dydis, funkcionalumas, svarba, tikslas ir kt., tačiau šiame straipsnyje naudosiu paprastą apimties klasifikaciją. Turiu omenyje tai, kur šis konkretus aspektas yra nukreiptas, nesvarbu, ar tai visa organizacija, konkreti sistema, ar konkretus tos sistemos elementas.


Taigi, aš suskirstysiu aspektus į makro ir mikro .


Makro aspektu pirmiausia turiu omenyje svarstymus, kuriais vadovaujamės visai sistemai, pavyzdžiui, pasirinkta sistemos architektūra ir jos dizainas (monolitinė, mikropaslaugos, į paslaugas orientuota architektūra), technologijų paketas, organizacijos struktūra ir tt Makro aspektai daugiausia susiję su strateginiu ir aukšto lygio sprendimus.


Tuo tarpu „Micro“ aspektas yra daug artimesnis kodo lygiui ir plėtrai. Pavyzdžiui, kuri sistema naudojama sąveikai su duomenų baze, aplankų ir klasių projektinė struktūra ar net konkretūs objektų dizaino modeliai.


Nors ši klasifikacija nėra ideali, ji padeda suprasti galimas problemas ir joms taikomų sprendimų svarbą bei poveikį.


Šiame straipsnyje daugiausia dėmesio skirsiu makrokomandoms.

Makro aspektai

Organizacijos struktūra

Kai tik pradėjau mokytis apie programinės įrangos architektūrą, perskaičiau daug įdomių straipsnių apie Conway dėsnį ir jo poveikį organizacijos struktūrai. Ypač šitą . Taigi, šis įstatymas tai nurodo


Bet kuri organizacija, kurianti sistemą (apibrėžta plačiai), parengs projektą, kurio struktūra yra organizacijos komunikacijos struktūros kopija.


Visada tikėjau, kad ši sąvoka iš tiesų yra labai universali ir atspindi Auksinę taisyklę.


Tada pradėjau mokytis Erico Evanso domenu valdomo dizaino (DDD) metodo modeliavimo sistemoms. Ericas Evansas pabrėžia riboto konteksto identifikavimo svarbą. Ši koncepcija apima sudėtingo domeno modelio padalijimą į mažesnes, lengviau valdomas dalis, kurių kiekviena turi savo ribotą žinių rinkinį. Šis metodas padeda efektyviai bendrauti su komanda, nes sumažina poreikį turėti išsamių žinių apie visą sritį ir sumažina konteksto perjungimą, todėl pokalbiai tampa efektyvesni. Konteksto keitimas yra pats blogiausias ir daugiausiai išteklių reikalaujantis dalykas. Net kompiuteriai su tuo kovoja. Nors vargu ar pavyks pasiekti visišką konteksto perjungimo nebuvimą, manau, kad būtent to turėtume siekti.


Fantasy about keeping in mind a lot of bounded contexts

Grįžtant prie Conway dėsnio, radau keletą su juo susijusių problemų.


Pirmoji problema, su kuria susidūriau su Conway dėsniu, kuris rodo, kad sistemos dizainas atspindi organizacijos struktūrą, yra galimybė sudaryti sudėtingus ir išsamius ribotus kontekstus. Šis sudėtingumas kyla, kai organizacinė struktūra nėra suderinta su domeno ribomis, todėl susidaro riboti kontekstai, kurie yra labai priklausomi vienas nuo kito ir yra apkrauti informacija. Dėl to kūrimo komanda dažnai keičia kontekstą.


Kita problema yra ta, kad organizacinė terminija patenka į kodo lygį. Pasikeitus organizacinėms struktūroms, reikia keisti kodų bazę, o tai sunaudoja vertingų išteklių.


Taigi Inverse Conway manevras padeda sukurti sistemą ir organizaciją, kuri skatina norimą programinės įrangos architektūrą. Tačiau pažymėtina, kad toks požiūris nelabai veiks jau suformuotoje architektūroje ir struktūrose, nes pokyčiai šiame etape užsitęsia, tačiau jis ypač efektyvus startuoliams, nes jie greitai įveda bet kokius pakeitimus.

Didelis purvo kamuolys

Šis modelis arba „anti-modelis“ skatina kurti sistemą be jokios architektūros. Nėra taisyklių, ribų ir strategijos, kaip suvaldyti neišvengiamai didėjantį sudėtingumą. Sudėtingumas yra didžiausias priešas kuriant programinės įrangos sistemas.


Entertaining illustration made by ChatGPT

Kad nekurtume tokio tipo sistemos, turime laikytis konkrečių taisyklių ir apribojimų.

Sistemos architektūra

Yra daugybė programinės įrangos architektūros apibrėžimų. Man patinka daugelis iš jų, nes jie apima skirtingus aspektus. Tačiau, kad galėtume samprotauti apie architektūrą, kai kuriuos iš jų natūraliai turime suformuoti mintyse. Ir verta pasakyti, kad šis apibrėžimas gali keistis. Taigi, bent jau kol kas turiu sau tokį aprašymą.


Programinės įrangos architektūra yra apie kasdienius sprendimus ir pasirinkimus, kurie daro įtaką sukurtai sistemai.


Norint priimti sprendimus, kurių „maišelyje“ turi būti iškylančių problemų sprendimo principai ir modeliai, taip pat būtina pasakyti, kad norint sukurti tai, ko reikia verslui, labai svarbu suprasti reikalavimus. Tačiau kartais reikalavimai nėra skaidrūs ar net neapibrėžti, tokiu atveju geriau palaukti, kol gausite daugiau paaiškinimų arba pasikliauti savo patirtimi ir pasikliauti savo intuicija. Bet šiaip negalite tinkamai priimti sprendimų, jei neturite principų ir modelių, kuriais galėtumėte pasikliauti. Štai čia aš einu prie programinės įrangos architektūros stiliaus apibrėžimo.


Programinės įrangos architektūros stilius – tai principų ir modelių rinkinys, nurodantis, kaip kurti programinę įrangą.


Įvairių architektūros stilių, orientuotų į įvairias planuojamos architektūros puses, yra labai daug, o kelių jų taikymas vienu metu yra įprasta situacija.


Pavyzdžiui, tokių kaip:

  1. Monolitinė architektūra

  2. Domenu pagrįstas dizainas

  3. Komponentų pagrindu

  4. Mikropaslaugos

  5. Vamzdis ir filtrai

  6. Įvykių paskatintas

  7. Mikrobranduolis

  8. Orientuotas į paslaugas


ir taip toliau…


Žinoma, jie turi savo privalumų ir trūkumų, bet svarbiausias dalykas, kurį sužinojau, yra tai, kad architektūra vystosi palaipsniui, priklausomai nuo aktualių problemų. Pradedant nuo monolitinės architektūros, tai puikus pasirinkimas norint sumažinti veiklos sudėtingumą. Labai tikėtina, kad ši architektūra atitiks jūsų poreikius net ir pasiekus produkto kūrimo etapą produkto rinkai tinkamas (PMI). Esant dideliam mastui, galite apsvarstyti galimybę pereiti prie įvykiais pagrįsto požiūrio ir mikropaslaugų, kad būtų pasiektas nepriklausomas diegimas, nevienalytė technologijų krūvos aplinka ir mažiau susietos architektūros (o tuo tarpu mažiau skaidrios dėl įvykiais pagrįstų ir viešųjų paslaugų metodų pobūdžio, jei šie yra priimti). Paprastumas ir efektyvumas yra artimi ir turi didelę įtaką vienas kitam. Paprastai sudėtingos architektūros turi įtakos naujų funkcijų kūrimo greičiui, palaiko ir palaiko esamas, ir meta iššūkį natūraliai sistemos evoliucijai.


Tačiau sudėtingoms sistemoms dažnai reikalinga sudėtinga ir visapusiška architektūra, o tai neišvengiama.


Tiesą sakant, tai labai plati tema, ir yra daug puikių idėjų, kaip struktūrizuoti ir sukurti natūralios evoliucijos sistemas. Remdamasis savo patirtimi, aš parengiau tokį metodą:

  1. Beveik visada prasideda monolitinės architektūros stilius, nes jis pašalina daugumą problemų, kylančių dėl paskirstytų sistemų pobūdžio. Taip pat prasminga vadovautis moduliniu monolitu, siekiant sutelkti dėmesį į pastato komponentus su aiškiomis ribomis. Komponentais pagrįsto požiūrio taikymas galėtų padėti jiems bendrauti tarpusavyje naudojant įvykius, tačiau tiesioginiai skambučiai (dar žinomas kaip RPC) iš pradžių viską supaprastina. Tačiau svarbu stebėti priklausomybes tarp komponentų, nes jei komponentas A daug žino apie komponentą B, galbūt prasminga juos sujungti į vieną.
  2. Kai priartėsite prie situacijos, kai reikia išplėsti savo kūrimo ir sistemos mastelį, galite apsvarstyti galimybę vadovautis „Stangler“ modeliu, kad palaipsniui išgautumėte komponentus, kuriuos reikia diegti atskirai arba netgi pakeisti pagal konkrečius reikalavimus.
  3. Dabar, jei turite aiškią ateities viziją, kuri yra neįtikėtina sėkmė, galite nuspręsti dėl pageidaujamos architektūros. Šiuo metu galite nuspręsti pereiti prie mikropaslaugų architektūros, taip pat taikydami orkestravimo ir choreografijos metodus, įtraukdami CQRS šabloną nepriklausomoms mastelio rašymo ir skaitymo operacijoms arba net nuspręsdami likti prie monolitinės architektūros, jei ji atitinka jūsų poreikius.


Taip pat labai svarbu suprasti skaičius ir metrikas, pvz., DAU (Daily Active Users), MAU (Mėnesio aktyvūs naudotojai), RPC (Užklausa per sekundę) ir TPC (Operacija per sekundę), nes tai gali padėti jums pasirinkti, nes 100 aktyvių vartotojų ir 100 milijonų aktyvių vartotojų skiriasi.


Pabaigoje norėčiau pasakyti, kad architektūra turi didelę įtaką produkto sėkmei. Prastai suprojektuota produktų architektūra reikalinga mastelio keitimui, o tai labai tikėtina, kad sukels nesėkmę, nes klientai nelauks, kol pakeisite sistemos mastelį, jie pasirinks konkurentą, todėl turime aplenkti galimą mastelio keitimą. Nors pripažįstu, kad kartais tai negali būti liesas požiūris, idėja yra turėti keičiamo dydžio, bet dar nepadidintą sistemą. Kita vertus, turėdami labai sudėtingą ir jau išplėtotą sistemą, kurioje nėra klientų ar neplanuojate jų gauti, verslui už dyką kainuosite pinigus.

Technologijų kamino pasirinkimas

Technologijų paketo pasirinkimas taip pat yra makrolygio sprendimas, nes jis turi įtakos įdarbinimui, natūralios sistemos evoliucijos perspektyvoms, mastelio keitimui ir sistemos našumui.


Tai yra pagrindinių renkantis technologijų paketą sąrašas:

  • Projekto reikalavimai ir sudėtingumas. Pavyzdžiui, paprasta žiniatinklio programa gali būti sukurta naudojant „Blazor“ sistemą, jei jūsų kūrėjai turi su ja patirties, tačiau dėl „WebAssembly“ subrendimo stokos ilgalaikei sėkmei pasirinkti „React“ ir „Typescript“ gali būti geresnis sprendimas.
  • Mastelio keitimo ir našumo poreikiai. Jei tikitės sulaukti didelio srauto, ASP.NET Core, o ne „Django“ pasirinkimas gali būti protingas pasirinkimas, nes jis puikiai tvarko vienalaikes užklausas. Tačiau šis sprendimas priklauso nuo jūsų laukiamo srauto masto. Jei jums reikia tvarkyti potencialiai milijardus užklausų su maža delsa, šiukšlių surinkimas gali būti iššūkis.
  • Įdarbinimas, kūrimo laikas ir kaina. Daugeliu atvejų tai yra veiksniai, į kuriuos turime rūpintis. Laikas patekti į rinką, priežiūros išlaidos ir samdymo stabilumas užtikrina jūsų verslo poreikius be kliūčių.
  • Komandos patirtis ir ištekliai. Jūsų kūrimo komandos įgūdžių rinkinys yra labai svarbus veiksnys. Paprastai veiksmingiau naudoti technologijas, kurias jūsų komanda jau pažįsta, nebent yra rimta priežastis investuoti į naujo krūvio mokymąsi.
  • Brandumas. Stipri bendruomenė ir turtinga bibliotekų bei įrankių ekosistema gali labai palengvinti kūrimo procesą. Populiarios technologijos dažnai turi geresnį bendruomenės palaikymą, kuris gali būti neįkainojamas sprendžiant problemas ir ieškant išteklių. Taigi galite sutaupyti išteklių ir daugiausia dėmesio skirti produktui.
  • Ilgalaikė priežiūra ir palaikymas. Apsvarstykite ilgalaikį technologijos gyvybingumą. Mažiau tikėtina, kad plačiai priimtos ir palaikomos technologijos pasens ir paprastai bus reguliariai atnaujinamos ir patobulintos.


Kaip kelių technologijų paketų turėjimas gali paveikti verslo augimą?

Vienu požiūriu, įvedus dar vieną krūvą, jūsų samdymas gali padidėti, tačiau, kita vertus, dėl to atsiras papildomų priežiūros išlaidų, nes reikia palaikyti abi krūvas. Taigi, kaip sakiau anksčiau, mano nuomone, tik papildomas poreikis turėtų būti argumentas įtraukti daugiau technologijų paketų.


Bet koks yra principas pasirinkti geriausią įrankį konkrečiai problemai?

Kartais jūs neturite kito pasirinkimo, kaip tik pateikti naujus įrankius konkrečiai problemai išspręsti, remiantis tais pačiais minėtais svarstymais, tokiais atvejais prasminga pasirinkti geriausią sprendimą.


Sukurti sistemas be didelio ryšio su konkrečia technologija gali būti iššūkis. Vis dėlto naudinga siekti tokios būklės, kai sistema nėra glaudžiai susieta su technologijomis ir ji nemirs, jei rytoj konkreti sistema ar įrankis taps pažeidžiamas ar net nebenaudojamas.


Kitas svarbus aspektas yra susijęs su atvirojo kodo ir patentuotos programinės įrangos priklausomybėmis. Patentuota programinė įranga suteikia jums mažiau lankstumo ir galimybę būti pritaikytam. Vis dėlto pavojingiausias veiksnys yra pardavėjo užsiblokavimas, kai tampama priklausomas nuo pardavėjo produktų, kainų, sąlygų ir veiksmų plano. Tai gali būti rizikinga, jei pardavėjas pakeičia kryptį, padidina kainas arba nutraukia produkto gamybą. Atvirojo kodo programinė įranga sumažina šią riziką, nes vienas subjektas jos nekontroliuoja. Vieno gedimo taško pašalinimas visais lygmenimis yra raktas į patikimų augimo sistemų kūrimą.

Vienas gedimo taškas (SPOF)

Vienas gedimo taškas (SPOF) reiškia bet kurią sistemos dalį, kuriai sugedus nustos veikti visa sistema. SPOF pašalinimas visais lygiais yra labai svarbus bet kuriai sistemai, kuriai reikalingas didelis prieinamumas. Viskas, įskaitant žinias, personalą, sistemos komponentus, debesų paslaugų teikėjus ir interneto kabelius, gali sugesti.


Yra keletas pagrindinių metodų, kuriuos galime taikyti, kad pašalintume atskirus gedimo taškus:

  1. Perteklius. Įdiekite svarbiausių komponentų perteklių. Tai reiškia, kad turite atsarginių komponentų, kurie gali perimti, jei sugenda pagrindinis komponentas. Atleidimas gali būti taikomas įvairiuose sistemos sluoksniuose, įskaitant techninę įrangą (serverius, diskus), tinklą (nuorodos, jungikliai) ir programinę įrangą (duomenų bazes, taikomųjų programų serverius). Jei viską talpinate viename „Cloud Provider“ ir netgi turite atsargines kopijas, apsvarstykite galimybę sukurti įprastą papildomą atsarginę kopiją kitame, kad sumažintumėte prarastas išlaidas nelaimės atveju.
  2. Duomenų centrai. Paskirstykite savo sistemą keliose fizinėse vietose, pvz., duomenų centruose arba debesų regionuose. Šis metodas apsaugo jūsų sistemą nuo konkrečios vietos gedimų, pvz., elektros energijos tiekimo nutraukimo ar stichinių nelaimių.
  3. Failover. Taikykite perjungimo metodą visiems savo komponentams (DNS, CDN, apkrovos balansavimo priemonėms, „Kubernetes“, API šliuzams ir duomenų bazėms). Kadangi problemų gali kilti netikėtai, labai svarbu turėti atsarginį planą, kaip greitai pakeisti bet kurį komponentą jo klonu.
  4. Aukšto prieinamumo paslaugos. Laikydamiesi šių principų, įsitikinkite, kad jūsų paslaugos yra horizontaliai keičiamos ir labai prieinamos nuo pat pradžių:
    • Praktikuokite paslaugų be pilietybės režimą ir venkite saugoti vartotojo seansus atminties talpyklose. Vietoj to naudokite paskirstytą talpyklos sistemą, pvz., Redis.
    • Kurdami logiką venkite pasikliauti chronologine pranešimų vartojimo tvarka.
    • Sumažinkite lūžtančius pakeitimus, kad išvengtumėte trikdžių API vartotojų. Jei įmanoma, rinkitės atgalinius pakeitimus. Be to, atsižvelkite į išlaidas, nes kartais pertraukiamo pakeitimo įgyvendinimas gali būti ekonomiškesnis.
    • Įtraukite perkėlimo vykdymą į diegimo dujotiekį.
    • Sukurkite lygiagrečių užklausų tvarkymo strategiją.
    • Įdiekite paslaugų aptikimą, stebėjimą ir registravimą, kad padidintumėte patikimumą ir stebėjimą.
    • Sukurkite verslo logiką, kad būtumėte idempotentas, pripažindami, kad tinklo gedimai yra neišvengiami.
  5. Priklausomybės peržiūra. Reguliariai peržiūrėkite ir sumažinkite išorines priklausomybes. Kiekviena išorinė priklausomybė gali sukelti galimus SPOF, todėl labai svarbu suprasti ir sumažinti šią riziką.
  6. Reguliarus dalijimasis žiniomis. Niekada nepamirškite, kaip svarbu skleisti žinias savo organizacijoje. Žmonės gali būti nenuspėjami, o pasikliauti vienu asmeniu yra rizikinga. Skatinkite komandos narius skaitmeninti savo žinias naudojant dokumentus. Tačiau nepamirškite per daug dokumentuoti. Norėdami supaprastinti šį procesą, naudokite įvairius AI įrankius.

Išvada

Šiame straipsnyje aptarėme kelis pagrindinius makrokomandos aspektus ir tai, kaip galime susidoroti su jų sudėtingumu.


Ačiū, kad skaitėte! Iki pasimatymo kitą kartą!