paint-brush
Hoe om kompleksiteit te hanteer wanneer sagtewarestelsels ontwerp worddeur@fairday
64,370 lesings
64,370 lesings

Hoe om kompleksiteit te hanteer wanneer sagtewarestelsels ontwerp word

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

Te lank; Om te lees

Kompleksiteit is die vyand! Kom ons leer hoe om dit te hanteer!
featured image - Hoe om kompleksiteit te hanteer wanneer sagtewarestelsels ontwerp word
Aleksei HackerNoon profile picture

Waaroor gaan dit alles?

Elke dag, elke oomblik tydens ons ingenieursloopbaan, kom ons teë met baie verskillende probleme van verskillende kompleksiteit en situasies waar ons 'n besluit moet neem of dit moet uitstel weens 'n gebrek aan data. Wanneer ons ook al nuwe dienste bou, infrastruktuur bou, of selfs ontwikkelingsprosesse vorm, raak ons 'n groot wêreld van verskeie uitdagings.


Dit is uitdagend, en dalk selfs onmoontlik, om al die probleme te lys. U sal sommige van hierdie probleme slegs teëkom as u in 'n spesifieke nis werk. Aan die ander kant is daar baie wat ons almal moet verstaan hoe om op te los, aangesien dit noodsaaklik is vir die bou van IT-stelsels. Met 'n hoë waarskynlikheid sal jy hulle in alle projekte teëkom.


In hierdie artikel sal ek my ervarings deel met sommige van die probleme wat ek ondervind het tydens die skep van sagtewareprogramme.

Wat is dwarsdeursnede kommer?

As ons na Wikipedia kyk, sal ons die volgende definisie vind


In aspek-georiënteerde sagteware-ontwikkeling is kruis-snyende bekommernisse aspekte van 'n program wat verskeie modules raak, sonder die moontlikheid om in enige van hulle ingekapsuleer te word. Hierdie bekommernisse kan dikwels nie skoon van die res van die stelsel ontbind word in beide die ontwerp en implementering nie, en kan tot óf verstrooiing (kodeduplisering), verstrengeling (beduidende afhanklikhede tussen stelsels) óf beide lei.


Dit beskryf baie goed wat dit is, maar ek wil dit 'n bietjie uitbrei en vereenvoudig:

'n Dwarsdeurlopende bekommernis is 'n konsep of komponent van die stelsel/organisasie wat baie ander dele raak (of 'deursny').


Die beste voorbeelde van sulke bekommernisse is stelselargitektuur, logging, sekuriteit, transaksiebestuur, telemetrie, databasisontwerp en daar is baie ander. Ons gaan later in hierdie artikel oor baie daarvan uitbrei.


Op die kodevlak word deursnyende bekommernisse dikwels geïmplementeer deur gebruik te maak van tegnieke soos Aspect-Oriented Programming (AOP) , waar hierdie bekommernisse gemodulariseer word in afsonderlike komponente wat regdeur die toepassing toegepas kan word. Dit hou die besigheidslogika geïsoleer van hierdie bekommernisse, wat die kode meer leesbaar en onderhoubaar maak.

Aspekte Klassifikasie

Daar is baie moontlike maniere om aspekte te klassifiseer deur hulle te segmenteer met verskillende eienskappe soos omvang, grootte, funksionaliteit, belangrikheid, teiken en ander, maar in hierdie artikel gaan ek 'n eenvoudige omvangklassifikasie gebruik. Hiermee bedoel ek waar hierdie spesifieke aspek gerig is of dit nou die hele organisasie, 'n bepaalde stelsel of 'n spesifieke element van daardie stelsel is.


Dus, ek gaan aspekte in Makro en Mikro verdeel.


Met Makro- aspek bedoel ek hoofsaaklik oorwegings wat ons vir die hele stelsel volg, soos gekose stelselargitektuur en die ontwerp daarvan (monolitiese, mikrodienste, diensgeoriënteerde argitektuur), tegnologiestapel, organisasiestruktuur, ens. Makroaspekte hou hoofsaaklik verband met strategiese en hoëvlak besluite.


Intussen is die Mikro- aspek baie nader aan die kodevlak en ontwikkeling. Byvoorbeeld, watter raamwerk word gebruik vir interaksie met die databasis, die projekstruktuur van dopgehou en klasse, of selfs spesifieke voorwerpontwerppatrone.


Alhoewel hierdie klassifikasie nie ideaal is nie, help dit om 'n begrip van moontlike probleme en die belangrikheid en impak van oplossings wat ons daarop toepas, te struktureer.


In hierdie artikel sal my primêre fokus op die makro-aspekte wees.

Makro-aspekte

Organisasiestruktuur

Toe ek net oor sagteware-argitektuur begin leer het, het ek baie interessante artikels gelees oor Conway se wet en die impak daarvan op organisasiestruktuur. Veral hierdie een . So, hierdie wet bepaal dit


Enige organisasie wat 'n stelsel ontwerp (wyd gedefinieer) sal 'n ontwerp produseer waarvan die struktuur 'n kopie van die organisasie se kommunikasiestruktuur is.


Ek het nog altyd geglo dat hierdie konsep inderdaad baie universeel is en die Goue Reël verteenwoordig.


Toe het ek begin om Eric Evans se Domain-Driven Design (DDD)-benadering vir modelleringstelsels te leer. Eric Evans beklemtoon die belangrikheid van Bounded Context-identifikasie. Hierdie konsep behels die verdeling van 'n komplekse domeinmodel in kleiner, meer hanteerbare afdelings, elk met sy eie beperkte stel kennis. Hierdie benadering help met effektiewe spankommunikasie, aangesien dit die behoefte aan uitgebreide kennis van die hele domein verminder en kontekswisseling tot die minimum beperk, en sodoende gesprekke doeltreffender maak. Konteksskakeling is die ergste en mees hulpbronverbruikende ding ooit. Selfs rekenaars sukkel daarmee. Alhoewel dit onwaarskynlik is om 'n volledige afwesigheid van kontekswisseling te bereik, reken ek dit is waarna ons moet streef.


Fantasy about keeping in mind a lot of bounded contexts

Om terug te keer na Conway's Law, het ek verskeie probleme daarmee gevind.


Die eerste kwessie wat ek met Conway se wet teëgekom het, wat daarop dui dat stelselontwerp organisatoriese struktuur weerspieël, is die potensiaal om komplekse en omvattende Begrensde kontekste te vorm. Hierdie kompleksiteit ontstaan wanneer die organisasiestruktuur nie in lyn is met domeingrense nie, wat lei tot Begrensde kontekste wat sterk interafhanklik is en met inligting gelaai is. Dit lei tot gereelde kontekswisseling vir die ontwikkelingspan.


Nog 'n probleem is dat organisatoriese terminologie na die kodevlak lek. Wanneer organisatoriese strukture verander, noodsaak dit kodebasis wysigings, wat waardevolle hulpbronne verbruik.


Om Inverse Conway Maneuver te volg, help dus om die stelsel en organisasie te bou wat gewenste sagteware-argitektuur aanmoedig. Dit is egter opmerklik om te sê dat hierdie benadering nie baie goed sal werk in reeds gevormde argitektuur en strukture nie, aangesien veranderinge op hierdie stadium verleng word, maar dit presteer buitengewoon in opstarters aangesien hulle vinnig enige veranderinge instel.

Groot modderbal

Hierdie patroon of "anti-patroon" dryf die bou van 'n stelsel sonder enige argitektuur. Daar is geen reëls, geen grense en geen strategie oor hoe om die onvermydelike groeiende kompleksiteit te beheer nie. Kompleksiteit is die mees gedugte vyand in die reis om sagtewarestelsels te bou.


Entertaining illustration made by ChatGPT

Om te verhoed dat so 'n tipe stelsel gebou word, moet ons spesifieke reëls en beperkings volg.

Stelsel argitektuur

Daar is talle definisies vir sagteware-argitektuur. Ek hou van baie van hulle aangesien hulle verskillende aspekte daarvan dek. Om egter oor argitektuur te kan redeneer, moet ons natuurlik sommige daarvan in ons gedagtes vorm. En dit is opmerklik om te sê dat hierdie definisie kan ontwikkel. So, ten minste vir nou, het ek die volgende beskrywing vir myself.


Sagteware-argitektuur gaan oor besluite en keuses wat jy elke dag maak wat die geboude stelsel beïnvloed.


Om besluite te neem wat jy in jou "tas" moet hê beginsels en patrone vir die oplossing van probleme wat ontstaan, is dit ook noodsaaklik om te sê dat die begrip van die vereistes die sleutel is om te bou wat 'n besigheid nodig het. Soms is vereistes egter nie deursigtig of selfs nie gedefinieer nie, in hierdie geval is dit beter om te wag om meer duidelikheid te kry of op jou ervaring staat te maak en jou intuïsie te vertrou. Maar in elk geval, jy kan nie behoorlik besluite neem as jy nie beginsels en patrone het om op staat te maak nie. Dit is waar ek by die definisie van sagteware-argitektuurstyl kom.


Sagteware-argitektuurstyl is 'n stel beginsels en patrone wat aandui hoe om sagteware te bou.


Daar is baie verskillende argitektoniese style wat op verskillende kante van die beplande argitektuur gefokus is, en om veelvuldige daarvan gelyktydig toe te pas is 'n normale situasie.


Byvoorbeeld, soos:

  1. Monolitiese argitektuur

  2. Domein-gedrewe ontwerp

  3. Komponent-gebaseer

  4. Mikrodienste

  5. Pyp en filters

  6. Gebeurtenisgedrewe

  7. Mikrokern

  8. Diensgerig


en so aan...


Natuurlik het hulle hul voordele en nadele, maar die belangrikste ding wat ek geleer het, is dat argitektuur geleidelik ontwikkel terwyl dit afhang van werklike probleme. Om met die monolitiese argitektuur te begin, is 'n uitstekende keuse om operasionele kompleksiteite te verminder, baie waarskynlik sal hierdie argitektuur by u behoeftes pas, selfs nadat u die produkmarkfiksheidsfase (PMI) bereik het om die produk te bou. Op skaal kan jy dit oorweeg om na 'n gebeurtenisgedrewe benadering en mikrodienste te beweeg vir die bereiking van onafhanklike ontplooiing, heterogene tegnologiestapelomgewing en minder gekoppelde argitektuur (en minder deursigtig in die tussentyd as gevolg van die aard van gebeurtenisgedrewe en pub-sub-benaderings indien dit word aangeneem). Eenvoud en doeltreffendheid is naby en het 'n groot impak op mekaar. Gewoonlik beïnvloed ingewikkelde argitekture die ontwikkelingspoed van nuwe kenmerke, ondersteun en onderhou bestaandes, en daag die stelsel se natuurlike evolusie uit.


Komplekse stelsels vereis egter dikwels komplekse en omvattende argitektuur, wat onvermydelik is.


Redelik, dit is 'n baie baie breë onderwerp, en daar is baie goeie idees oor hoe om stelsels vir natuurlike evolusie te struktureer en te bou. Op grond van my ervaring het ek die volgende benadering uitgewerk:

  1. Begin byna altyd met die monolitiese argitektuurstyl aangesien dit die meeste van die probleme wat ontstaan as gevolg van die aard van verspreide stelsels uitskakel. Dit maak ook sin om modulêre monoliet te volg om te fokus op boukomponente met duidelike grense. Die toepassing van 'n komponent-gebaseerde benadering kan hulle help om met mekaar te kommunikeer deur gebeurtenisse te gebruik, maar om direkte oproepe (ook bekend as RPC) te hê, vergemaklik dinge in die begin. Dit is egter belangrik om afhanklikhede tussen komponente op te spoor, want as komponent A baie van komponent B weet, is dit miskien sinvol om hulle in een saam te voeg.
  2. Wanneer jy nader aan die situasie kom wanneer jy jou ontwikkeling en stelsel moet skaal, kan jy dit oorweeg om die Stangler- patroon te volg om geleidelik komponente te onttrek wat onafhanklik ontplooi moet word of selfs met spesifieke vereistes afgeskaal moet word.
  3. Nou, as jy 'n duidelike visie van die toekoms het, wat 'n bietjie ongelooflike geluk is, kan jy op die gewenste argitektuur besluit. Op hierdie oomblik kan jy besluit om na mikrodienste-argitektuur te beweeg deur ook Orkestrasie- en Choreografie-benaderings toe te pas, CQRS-patroon in te sluit vir onafhanklike skaalskryf- en leesbewerkings, of selfs besluit om by monolitiese argitektuur te bly as dit by jou behoeftes pas.


Dit is ook noodsaaklik om die getalle en maatstawwe soos DAU (Daily Active Users), MAU (Monthly Active Users), RPC (Request Per Second) en TPC (Transaction Per Second) te verstaan, aangesien dit jou kan help om keuses te maak omdat argitektuur vir 100 aktiewe gebruikers en 100 miljoen aktiewe gebruikers verskil.


As 'n laaste opmerking, sou ek sê dat argitektuur 'n beduidende impak op die produk se sukses het. Swak ontwerpte argitektuur vir die produkte word vereis in skaal, wat heel waarskynlik tot mislukking lei, aangesien kliënte nie sal wag terwyl jy die stelsel skaal nie, hulle sal 'n mededinger kies, so ons moet voor potensiële skaal wees. Alhoewel ek erken dat dit soms nie 'n skraal benadering kan wees nie, is die idee om 'n skaalbare maar nie reeds geskaalde stelsel te hê nie. Aan die ander kant, om 'n baie ingewikkelde en reeds afgeskaalde stelsel te hê sonder kliënte of planne om baie van hulle te kry, sal jou verniet geld op jou besigheid kos.

Tegnologie stapel keuse

Die keuse van 'n tegnologiestapel is ook 'n makrovlakbesluit, aangesien dit huur, stelsel natuurlike evolusieperspektiewe, skaalbaarheid en stelselprestasie beïnvloed.


Dit is die lys van basiese oorwegings vir die keuse van 'n tegnologiestapel:

  • Projekvereistes en kompleksiteit. Byvoorbeeld, 'n eenvoudige webtoepassing kan met die Blazor-raamwerk gebou word as u ontwikkelaars ondervinding daarmee het, maar as gevolg van die gebrek aan volwassenheid van WebAssembly, kan die keuse van React en Typescript vir langtermyn sukses 'n beter besluit wees
  • Skaalbaarheid en prestasiebehoeftes. As jy verwag om 'n groot hoeveelheid verkeer te ontvang, kan die keuse van ASP.NET Core bo Django 'n wyse keuse wees as gevolg van sy uitstekende prestasie in die hantering van gelyktydige versoeke. Hierdie besluit hang egter af van die omvang van die verkeer wat jy verwag. As jy potensieel miljarde versoeke met 'n lae latensie moet bestuur, kan die teenwoordigheid van Garbage Collection 'n uitdaging wees.
  • Huur, ontwikkelingstyd en koste. In die meeste gevalle is dit die faktore waaroor ons moet omgee. Tyd om te bemark, instandhoudingskoste en huurstabiliteit dryf u besigheidsbehoeftes sonder struikelblokke.
  • Span Kundigheid en Hulpbronne. Die vaardighede van jou ontwikkelingspan is 'n kritieke faktor. Dit is oor die algemeen meer effektief om tegnologieë te gebruik waarmee u span reeds vertroud is, tensy daar 'n sterk rede is om te belê om 'n nuwe stapel te leer.
  • Volwassenheid. 'n Sterk gemeenskap en 'n ryk ekosisteem van biblioteke en gereedskap kan die ontwikkelingsproses baie vergemaklik. Gewilde tegnologieë het dikwels beter gemeenskapsondersteuning, wat van onskatbare waarde kan wees om probleme op te los en hulpbronne te vind. U kan dus hulpbronne bespaar en hoofsaaklik op die produk fokus.
  • Langtermyn onderhoud en ondersteuning. Oorweeg die langtermyn lewensvatbaarheid van die tegnologie. Tegnologieë wat wyd aangeneem en ondersteun word, is minder geneig om verouderd te raak en ontvang oor die algemeen gereelde opdaterings en verbeterings.


Hoe kan dit besigheidsgroei beïnvloed om verskeie tegnologiestapels te hê?

Vanuit een perspektief kan die bekendstelling van nog een stapel jou huur skaal, maar aan die ander kant bring dit ekstra onderhoudskoste mee, aangesien jy albei stapels moet ondersteun. Dus, soos ek voorheen gesê het, volgens my oogpunt, moet slegs ekstra behoefte 'n argument wees om meer tegnologiestapels in te sluit.


Maar wat gaan oor die beginsel om die beste hulpmiddel vir 'n spesifieke probleem te kies?

Soms het jy geen ander keuse as om nuwe gereedskap te bring om 'n spesifieke probleem op te los op grond van dieselfde oorwegings wat hierbo genoem is nie, in sulke gevalle maak dit sin om die beste oplossing te kies.


Die skepping van stelsels sonder hoë koppeling aan 'n spesifieke tegnologie kan 'n uitdaging wees. Tog is dit nuttig om te streef na 'n toestand waar die stelsel nie stewig gekoppel is aan tegnologie nie, en dit sal nie sterf as môre, 'n spesifieke raamwerk of instrument kwesbaar word of selfs afgekeur word nie.


Nog 'n belangrike oorweging hou verband met oopbron- en eie sagteware-afhanklikhede. Eie sagteware gee jou minder buigsaamheid en die moontlikheid om aangepas te word. Die gevaarlikste faktor is egter die toesluit van die verkoper, waar jy afhanklik word van 'n verkoper se produkte, pryse, terme en padkaart. Dit kan riskant wees as die verkoper van rigting verander, pryse verhoog of die produk staak. Oopbronsagteware verminder hierdie risiko, aangesien 'n enkele entiteit dit nie beheer nie. Die uitskakeling van 'n enkele punt van mislukking op alle vlakke is 'n sleutel tot die bou van betroubare stelsels vir groei.

Enkelpunt van mislukking (SPOF)

'n Enkelpunt van mislukking (SPOF) verwys na enige deel van 'n stelsel wat, indien dit misluk, sal veroorsaak dat die hele stelsel ophou funksioneer. Die uitskakeling van SPOF's op alle vlakke is noodsaaklik vir enige stelsel wat hoë beskikbaarheid vereis. Alles, insluitend kennis, personeel, stelselkomponente, wolkverskaffers en internetkabels, kan misluk.


Daar is verskeie basiese tegnieke wat ons kan toepas om enkele punte van mislukking uit te skakel:

  1. Oortolligheid. Implementeer oortolligheid vir kritieke komponente. Dit beteken om rugsteunkomponente te hê wat kan oorneem as die primêre komponent misluk. Oortolligheid kan oor verskillende lae van die stelsel toegepas word, insluitend hardeware (bedieners, skywe), netwerk (skakels, skakelaars) en sagteware (databasisse, toepassingsbedieners). As jy alles in een Wolkverskaffer huisves en selfs rugsteun daar het, oorweeg dit om 'n gereelde bykomende rugsteun in 'n ander te bou om jou verlore koste in geval van rampspoed te verminder.
  2. Datasentrums. Versprei jou stelsel oor verskeie fisiese liggings, soos datasentrums of wolkstreke. Hierdie benadering beskerm jou stelsel teen liggingspesifieke foute soos kragonderbrekings of natuurrampe.
  3. Failover. Pas 'n failover-benadering toe vir al jou komponente (DNS, CDN, laaibalanseerders, Kubernetes, API-poorte en databasisse). Aangesien probleme onverwags kan ontstaan, is dit van kardinale belang om 'n rugsteunplan te hê om enige komponent vinnig met sy kloon te vervang soos benodig.
  4. Hoë beskikbaarheid dienste. Maak seker dat jou dienste gebou is om horisontaal skaalbaar en hoogs beskikbaar te wees van die begin af deur te voldoen aan die volgende beginsels:
    • Oefen diensstaatloosheid en vermy die stoor van gebruikersessies in in-geheue-geheue. Gebruik eerder 'n verspreide kasstelsel, soos Redis.
    • Vermy vertroue op die chronologiese volgorde van boodskapverbruik wanneer logika ontwikkel word.
    • Minimaliseer breekveranderings om te voorkom dat API-verbruikers ontwrig word. Waar moontlik, kies vir terugwaarts-versoenbare veranderinge. Oorweeg ook koste, want soms kan die implementering van 'n breekverandering meer koste-effektief wees.
    • Inkorporeer migrasie-uitvoering in die ontplooiingspyplyn.
    • Vestig 'n strategie vir die hantering van gelyktydige versoeke.
    • Implementeer diensontdekking, monitering en logboek om betroubaarheid en waarneembaarheid te verbeter.
    • Ontwikkel besigheidslogika om idempotent te wees, met die erkenning dat netwerkfoute onvermydelik is.
  5. Hersiening van afhanklikheid. Hersien gereeld eksterne afhanklikhede en minimaliseer dit. Elke eksterne afhanklikheid kan potensiële SPOF's bekendstel, so dit is noodsaaklik om hierdie risiko's te verstaan en te versag.
  6. Gereelde deel van kennis. Moet nooit die belangrikheid daarvan vergeet om kennis binne jou organisasie te versprei nie. Mense kan onvoorspelbaar wees, en om op 'n enkele individu te vertrou is riskant. Moedig spanlede aan om hul kennis deur dokumentasie te digitaliseer. Wees egter bedag op oordokumentering. Gebruik verskeie KI-instrumente om hierdie proses te vereenvoudig.

Gevolgtrekking

In hierdie artikel het ons verskeie belangrike makro- aspekte behandel en hoe ons die kompleksiteit daarvan kan hanteer.


Dankie dat jy gelees het! Sien jou volgende keer!