paint-brush
Kuinka käsitellä monimutkaisuutta ohjelmistojärjestelmiä suunniteltaessakirjoittaja@fairday
64,370 lukemat
64,370 lukemat

Kuinka käsitellä monimutkaisuutta ohjelmistojärjestelmiä suunniteltaessa

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

Liian pitkä; Lukea

Monimutkaisuus on vihollinen! Opitaan kuinka käsitellä sitä!
featured image - Kuinka käsitellä monimutkaisuutta ohjelmistojärjestelmiä suunniteltaessa
Aleksei HackerNoon profile picture

Mistä siinä on kyse?

Joka päivä, joka hetki insinööriuramme aikana kohtaamme monia erilaisia ja monimutkaisia ongelmia ja tilanteita, joissa joudumme tekemään päätöksen tai lykkäämään sitä tiedon puutteen vuoksi. Aina kun rakennamme uusia palveluita, rakennamme infrastruktuuria tai jopa muodostamme kehitysprosesseja, kosketamme valtavaa erilaisten haasteiden maailmaa.


On haastavaa ja ehkä jopa mahdotonta luetella kaikkia ongelmia. Kohtaat joitakin näistä ongelmista vain, jos työskentelet tietyllä markkinaraolla. Toisaalta on monia asioita, jotka meidän kaikkien on ymmärrettävä ratkaistavaksi, koska ne ovat tärkeitä IT-järjestelmien rakentamisessa. Suurella todennäköisyydellä kohtaat niitä kaikissa projekteissa.


Tässä artikkelissa jaan kokemukseni joistakin ongelmista, joita olen kohdannut ohjelmistojen luomisen aikana.

Mikä on monialainen huoli?

Jos katsomme Wikipediaa, löydämme seuraavan määritelmän


Aspektisuuntautuneessa ohjelmistokehityksessä poikkileikkaushuolet ovat ohjelman näkökohtia, jotka vaikuttavat useisiin moduuleihin ilman mahdollisuutta kapseloitua mihinkään niistä. Näitä huolenaiheita ei useinkaan voida selkeästi hajottaa muusta järjestelmästä sekä suunnittelussa että toteutuksessa, ja ne voivat johtaa joko hajoamiseen (koodin monistaminen), sotkeutumiseen (merkittävistä riippuvuuksista järjestelmien välillä) tai molempiin.


Se kuvaa hyvin, mitä se on, mutta haluan laajentaa ja yksinkertaistaa sitä hieman:

Monialainen huolenaihe on järjestelmän/organisaation käsite tai osa, joka vaikuttaa moniin muihin osiin (tai "kattaa").


Parhaita esimerkkejä tällaisista huolenaiheista ovat järjestelmäarkkitehtuuri, kirjaus, turvallisuus, tapahtumien hallinta, telemetria, tietokantojen suunnittelu ja monet muut. Aiomme käsitellä monia niistä myöhemmin tässä artikkelissa.


Kooditasolla monialaiset huolenaiheet toteutetaan usein käyttämällä tekniikoita, kuten AOP (Aspect-Oriented Programming) , jossa nämä huolenaiheet on modulisoitu erillisiksi komponenteiksi, joita voidaan soveltaa koko sovelluksessa. Tämä pitää liiketoimintalogiikan erillään näistä huolenaiheista, mikä tekee koodista luettavamman ja ylläpidettävämmän.

Aspektien luokittelu

On monia mahdollisia tapoja luokitella aspekteja segmentoimalla ne eri ominaisuuksilla, kuten laajuus, koko, toiminnallisuus, tärkeys, kohde ja muut, mutta tässä artikkelissa aion käyttää yksinkertaista laajuusluokitusta. Tarkoitan tällä sitä, mihin tämä erityinen näkökohta on suunnattu, onko kyseessä koko organisaatio, tietty järjestelmä vai järjestelmän tietty osa.


Joten aion jakaa näkökohdat makroon ja mikroon .


Makronäkökohdalla tarkoitan pääasiassa koko järjestelmää koskevia huomioita, joita noudatamme, kuten valittu järjestelmäarkkitehtuuri ja sen suunnittelu (monoliittinen, mikropalvelut, palvelukeskeinen arkkitehtuuri), teknologiapino, organisaatiorakenne jne. Makronäkökohdat liittyvät pääasiassa strategiseen ja korkeaan tasoon. päätöksiä.


Sillä välin Micro- näkökulma on paljon lähempänä koodin tasoa ja kehitystä. Esimerkiksi mitä kehystä käytetään vuorovaikutukseen tietokannan kanssa, kansioiden ja luokkien projektirakennetta tai jopa tiettyjä objektisuunnittelumalleja.


Vaikka tämä luokittelu ei olekaan ihanteellinen, se auttaa jäsentämään ymmärrystä mahdollisista ongelmista ja niihin sovellettavien ratkaisujen tärkeydestä ja vaikutuksista.


Tässä artikkelissa keskityn ensisijaisesti makronäkökohtiin.

Makronäkökohdat

Organisaation rakenne

Kun aloin juuri oppia ohjelmistoarkkitehtuurista, luin monia mielenkiintoisia artikkeleita Conwayn laista ja sen vaikutuksesta organisaatiorakenteeseen. Varsinkin tämä . Tämä laki siis sanoo sen


Jokainen organisaatio, joka suunnittelee järjestelmän (määriteltynä laajasti), tuottaa suunnittelun, jonka rakenne on kopio organisaation viestintärakenteesta.


Olen aina uskonut, että tämä käsite on todellakin hyvin universaali ja edustaa kultaista sääntöä.


Sitten aloin oppia Eric Evansin Domain-Driven Design (DDD) -lähestymistapaa järjestelmien mallintamiseen. Eric Evans korostaa rajatun kontekstin tunnistamisen merkitystä. Tämä konsepti sisältää monimutkaisen toimialueen mallin jakamisen pienempiin, paremmin hallittaviin osiin, joista jokaisella on omat rajalliset tietonsa. Tämä lähestymistapa auttaa tehokkaassa tiimiviestinnässä, koska se vähentää tarvetta saada laajaa tietoa koko toimialueesta ja minimoi kontekstin vaihtamisen, mikä tekee keskusteluista tehokkaampia. Kontekstin vaihtaminen on kaikkien aikojen pahin ja resursseja vievin asia. Jopa tietokoneet kamppailevat sen kanssa. Vaikka on epätodennäköistä, että kontekstin vaihtamisen täydellistä puuttumista ei saavuteta, siihen meidän pitäisi mielestäni pyrkiä.


Fantasy about keeping in mind a lot of bounded contexts

Palatakseni Conwayn lakiin, olen löytänyt sen kanssa useita ongelmia.


Ensimmäinen ongelma, jonka olen kohdannut Conwayn laissa, joka ehdottaa, että järjestelmän suunnittelu heijastelee organisaatiorakennetta, on mahdollisuus muodostaa monimutkaisia ja kattavia rajattuja konteksteja. Tämä monimutkaisuus syntyy, kun organisaatiorakenne ei ole linjassa toimialueen rajojen kanssa, mikä johtaa rajallisiin konteksteihin, jotka ovat voimakkaasti riippuvaisia toisistaan ja täynnä tietoa. Se johtaa usein kehitystiimin kontekstin vaihtamiseen.


Toinen ongelma on, että organisaation terminologia vuotaa kooditasolle. Kun organisaatiorakenteet muuttuvat, se edellyttää koodikannan muutoksia, mikä kuluttaa arvokkaita resursseja.


Siten Inverse Conway Maneuverin seuraaminen auttaa rakentamaan järjestelmän ja organisaation, jotka edistävät haluttua ohjelmistoarkkitehtuuria. On kuitenkin huomionarvoista sanoa, että tämä lähestymistapa ei toimi kovin hyvin jo muodostuneessa arkkitehtuurissa ja rakenteissa, koska muutokset tässä vaiheessa pitkittyvät, mutta se toimii poikkeuksellisen hyvin startupeissa, koska ne ovat nopeita tekemään muutoksia.

Suuri mutapallo

Tämä malli tai "anti-kuvio" ajaa järjestelmän rakentamista ilman arkkitehtuuria. Ei ole sääntöjä, ei rajoja eikä strategiaa väistämättömän kasvavan monimutkaisuuden hallitsemiseksi. Monimutkaisuus on ohjelmistojärjestelmien rakentamisen pahin vihollinen.


Entertaining illustration made by ChatGPT

Välttääksemme rakentamasta tällaista järjestelmää, meidän on noudatettava erityisiä sääntöjä ja rajoituksia.

Järjestelmän arkkitehtuuri

Ohjelmistoarkkitehtuurille on olemassa lukemattomia määritelmiä. Pidän monista niistä, koska ne kattavat sen eri puolia. Kuitenkin, jotta voimme perustella arkkitehtuuria, meidän on luonnollisesti muodostettava niitä mielessämme. Ja on huomionarvoista sanoa, että tämä määritelmä voi kehittyä. Joten ainakin toistaiseksi minulla on seuraava kuvaus itselleni.


Ohjelmistoarkkitehtuurissa on kyse päätöksistä ja valinnoista, joita teet joka päivä ja jotka vaikuttavat rakennettuun järjestelmään.


Tehdäksesi päätöksiä, jotka tarvitsevat "laukussasi" periaatteet ja mallit nousevien ongelmien ratkaisemiseksi, on myös oleellista todeta, että vaatimusten ymmärtäminen on avainasemassa yrityksen tarpeiden rakentamisessa. Joskus vaatimukset eivät kuitenkaan ole läpinäkyviä tai niitä ei ole edes määritelty, tässä tapauksessa on parempi odottaa saadaksesi lisäselvitystä tai luottaa kokemukseesi ja luottaa intuitioon. Mutta joka tapauksessa, et voi tehdä päätöksiä kunnolla, jos sinulla ei ole periaatteita ja malleja, joihin tukeutua. Tässä olen tulossa ohjelmistoarkkitehtuurityylin määritelmään.


Ohjelmistoarkkitehtuurityyli on joukko periaatteita ja malleja, jotka määrittelevät kuinka ohjelmisto rakennetaan.


Suunnitellun arkkitehtuurin eri puolille keskittyy paljon erilaisia arkkitehtonisia tyylejä, joiden soveltaminen kerralla on normaali tilanne.


Esimerkiksi, kuten:

  1. Monoliittista arkkitehtuuria

  2. Verkkotunnuslähtöinen suunnittelu

  3. Komponenttipohjainen

  4. Mikropalvelut

  5. Putki ja suodattimet

  6. Tapahtumalähtöinen

  7. Mikroydin

  8. Palvelukeskeinen


ja niin edelleen…


Tietysti niillä on hyvät ja huonot puolensa, mutta tärkein asia, jonka olen oppinut, on se, että arkkitehtuuri kehittyy vähitellen todellisista ongelmista riippuen. Aloittaen monoliittisesta arkkitehtuurista, se on loistava valinta toimintojen monimutkaisuuden vähentämiseen. Hyvin todennäköisesti tämä arkkitehtuuri sopii tarpeisiisi jopa tuotteen rakennusvaiheen (PMI) saavuttamisen jälkeen. Suuressa mittakaavassa voit harkita siirtymistä kohti tapahtumalähtöistä lähestymistapaa ja mikropalveluita itsenäisen käyttöönoton, heterogeenisen teknologiapinoympäristön ja vähemmän kytketyn arkkitehtuurin saavuttamiseksi (ja vähemmän läpinäkyvän sillä välin tapahtumalähtöisten ja pubi-lähestymistapojen luonteen vuoksi, jos nämä hyväksytään). Yksinkertaisuus ja tehokkuus ovat lähellä toisiaan ja niillä on suuri vaikutus toisiinsa. Yleensä monimutkaiset arkkitehtuurit vaikuttavat uusien ominaisuuksien kehitysnopeuteen, tukevat ja ylläpitävät olemassa olevia ominaisuuksia ja haastavat järjestelmän luonnollisen kehityksen.


Monimutkaiset järjestelmät vaativat kuitenkin usein monimutkaista ja kattavaa arkkitehtuuria, mikä on väistämätöntä.


Tämä on todella laaja aihe, ja on olemassa monia hienoja ideoita siitä, miten luonnollista evoluutiota varten rakennetaan ja rakennetaan järjestelmiä. Kokemukseni perusteella olen kehittänyt seuraavan lähestymistavan:

  1. Lähes aina alkaa monoliittisella arkkitehtuurityylillä, koska se eliminoi suurimman osan hajautettujen järjestelmien luonteesta johtuvista ongelmista. On myös järkevää seurata modulaarista monoliittia keskittyäksesi rakennuskomponentteihin, joilla on selkeät rajat. Komponenttipohjaisen lähestymistavan soveltaminen voisi auttaa heitä kommunikoimaan keskenään tapahtumien avulla, mutta suorat puhelut (alias RPC) yksinkertaistavat asioita alussa. On kuitenkin tärkeää seurata komponenttien välisiä riippuvuuksia, koska jos komponentti A tietää paljon komponentista B, on ehkä järkevää yhdistää ne yhdeksi.
  2. Kun tulet lähemmäksi tilannetta, jossa sinun on skaalattava kehitystäsi ja järjestelmääsi, voit harkita Stangler- mallin noudattamista ja poimia asteittain komponentteja, jotka on otettava käyttöön itsenäisesti tai jopa skaalattava tiettyjen vaatimusten mukaan.
  3. Nyt, jos sinulla on selkeä näkemys tulevaisuudesta, mikä on vähän uskomatonta onnea, voit päättää halutun arkkitehtuurin. Tällä hetkellä voit päättää siirtyäksesi kohti mikropalveluarkkitehtuuria soveltamalla myös orkestrointi- ja koreografialähestymistapoja, sisällyttämällä CQRS-kuvion itsenäiseen mittakaavaan kirjoitus- ja lukutoimintoihin, tai jopa päättää pysyä monoliittisessa arkkitehtuurissa, jos se sopii tarpeisiisi.


On myös tärkeää ymmärtää numerot ja mittarit, kuten DAU (Daily Active Users), MAU (Monthly Active Users), RPC (Request Per Second) ja TPC (Tapahtuma sekunnissa), koska ne voivat auttaa sinua tekemään valintoja, koska 100 aktiivista käyttäjää ja 100 miljoonaa aktiivista käyttäjää ovat erilaisia.


Viimeisenä huomautuksena sanoisin, että arkkitehtuurilla on merkittävä vaikutus tuotteen menestykseen. Skaalauksessa vaaditaan tuotteiden huonosti suunniteltua arkkitehtuuria, mikä todennäköisesti johtaa epäonnistumiseen, koska asiakkaat eivät odota järjestelmän skaalausta, vaan he valitsevat kilpailijan, joten meidän on oltava edellä mahdollisia skaalauksia. Vaikka myönnän, että toisinaan se ei voisi olla laiha lähestymistapa, ideana on skaalautuva, mutta ei jo skaalattu järjestelmä. Toisaalta erittäin monimutkainen ja jo skaalattu järjestelmä ilman asiakkaita tai suunnitelmia hankkia monia heistä maksaa yrityksellesi turhaan rahaa.

Teknologiapinon valinta

Teknologiapinon valitseminen on myös makrotason päätös, koska se vaikuttaa palkkaamiseen, järjestelmän luonnollisen kehityksen näkökulmiin, skaalautumiseen ja järjestelmän suorituskykyyn.


Tässä on luettelo perusnäkökohdista teknologiapinon valinnassa:

  • Projektin vaatimukset ja monimutkaisuus. Esimerkiksi yksinkertainen verkkosovellus voidaan rakentaa Blazor-kehyksen avulla, jos kehittäjilläsi on kokemusta siitä, mutta WebAssemblyn kypsyyden puutteen vuoksi Reactin ja Typescriptin valitseminen pitkän aikavälin menestykseen voisi olla parempi päätös.
  • Skaalautuvuus ja suorituskykyvaatimukset. Jos odotat saavasi paljon liikennettä, ASP.NET Coren valitseminen Djangon sijaan voi olla viisas valinta sen erinomaisen suorituskyvyn vuoksi samanaikaisten pyyntöjen käsittelyssä. Tämä päätös riippuu kuitenkin odottamastasi liikenteen laajuudesta. Jos sinun täytyy hallita mahdollisesti miljardeja pyyntöjä alhaisella viiveellä, roskienkeräys voi olla haaste.
  • Palkkaus, kehitysaika ja kustannukset. Useimmissa tapauksissa nämä ovat tekijöitä, joista meidän on huolehdittava. Markkinoille tuloaika, ylläpitokustannukset ja vakaus rekrytoinnissa ohjaavat yrityksesi tarpeita ilman esteitä.
  • Tiimin asiantuntemus ja resurssit. Kehitystiimisi osaaminen on kriittinen tekijä. Yleensä on tehokkaampaa käyttää tiimisi jo tuntemia teknologioita, ellei ole painavaa syytä investoida uuden pinon oppimiseen.
  • Kypsyys. Vahva yhteisö ja rikas kirjastojen ja työkalujen ekosysteemi voivat helpottaa kehitysprosessia huomattavasti. Suosituilla teknologioilla on usein parempi yhteisön tuki, mikä voi olla korvaamatonta ongelmien ratkaisemisessa ja resurssien löytämisessä. Näin voit säästää resursseja ja keskittyä pääasiassa tuotteeseen.
  • Pitkäaikainen huolto ja tuki. Harkitse tekniikan pitkän aikavälin elinkelpoisuutta. Laajalti omaksutut ja tuetut tekniikat eivät todennäköisesti vanhene ja saavat yleensä säännöllisesti päivityksiä ja parannuksia.


Kuinka useiden teknologiapintojen käyttö voi vaikuttaa liiketoiminnan kasvuun?

Yhdestä näkökulmasta yhden pinon lisääminen voi skaalata palkkaamistasi, mutta toisaalta se tuo ylimääräisiä ylläpitokustannuksia, koska sinun on tuettava molempia pinoja. Joten, kuten sanoin aiemmin, minun näkökulmastani vain ylimääräisen tarpeen pitäisi olla peruste teknologiapinojen sisällyttämiselle.


Mutta mikä on periaate, jonka mukaan valitaan paras työkalu tiettyyn ongelmaan?

Joskus sinulla ei ole muuta vaihtoehtoa kuin tuoda uusia työkaluja tietyn ongelman ratkaisemiseen samojen edellä mainittujen näkökohtien pohjalta, tällaisissa tapauksissa on järkevää valita paras ratkaisu.


Sellaisten järjestelmien luominen, joissa ei ole korkeaa yhteyttä tiettyyn teknologiaan, voi olla haaste. Silti on hyödyllistä pyrkiä tilanteeseen, jossa järjestelmä ei ole tiukasti kytketty teknologiaan, eikä se kuole, jos huomenna tietystä viitekehyksestä tai työkalusta tulee haavoittuva tai jopa vanhentunut.


Toinen tärkeä näkökohta liittyy avoimen lähdekoodin ja ohjelmistojen riippuvuuteen. Oma ohjelmisto antaa sinulle vähemmän joustavuutta ja mahdollisuuden mukauttaa. Silti vaarallisin tekijä on toimittajan lukkiutuminen, jossa sinusta tulee riippuvainen myyjän tuotteista, hinnoista, ehdoista ja etenemissuunnitelmasta. Tämä voi olla riskialtista, jos myyjä muuttaa suuntaa, nostaa hintoja tai lopettaa tuotteen. Avoimen lähdekoodin ohjelmistot vähentävät tätä riskiä, koska yksittäinen kokonaisuus ei hallitse sitä. Yhden vikakohdan poistaminen kaikilla tasoilla on avain luotettavien kasvujärjestelmien rakentamiseen.

Single Point of Failure (SPOF)

Yksi vikapiste (SPOF) viittaa mihin tahansa järjestelmän osaan, joka epäonnistuessaan aiheuttaa koko järjestelmän toiminnan pysähtymisen. SPOF:ien poistaminen kaikilla tasoilla on ratkaisevan tärkeää kaikissa korkeaa käytettävyyttä vaativissa järjestelmissä. Kaikki, mukaan lukien tieto, henkilöstö, järjestelmäkomponentit, pilvipalveluntarjoajat ja Internet-kaapelit, voi epäonnistua.


On olemassa useita perustekniikoita, joita voimme soveltaa yksittäisten vikakohtien poistamiseen:

  1. Redundanssi. Ota käyttöön kriittisten komponenttien redundanssi. Tämä tarkoittaa, että sinulla on varmuuskopiokomponentit, jotka voivat ottaa haltuunsa, jos ensisijainen komponentti epäonnistuu. Redundanssia voidaan soveltaa järjestelmän eri tasoilla, mukaan lukien laitteistot (palvelimet, levyt), verkot (linkit, kytkimet) ja ohjelmistot (tietokannat, sovelluspalvelimet). Jos isännöit kaikkea yhdessä pilvipalveluntarjoajassa ja sinulla on siellä jopa varmuuskopioita, harkitse säännöllisen lisävarmuuskopion luomista toiseen, jotta menetät kustannukset katastrofin sattuessa.
  2. Palvelinkeskukset. Jaa järjestelmäsi useisiin fyysisiin paikkoihin, kuten datakeskuksiin tai pilvialueisiin. Tämä lähestymistapa suojaa järjestelmääsi paikkakohtaisilta häiriöiltä, kuten sähkökatkoilta tai luonnonkatastrofilta.
  3. Failover. Käytä vikasietotapaa kaikille komponenteillesi (DNS, CDN, kuormituksen tasaajat, Kubernetes, API-yhdyskäytävät ja tietokannat). Koska ongelmia voi ilmaantua odottamatta, on erittäin tärkeää, että sinulla on varmuuskopiointisuunnitelma minkä tahansa komponentin korvaamiseksi sen kloonilla tarvittaessa nopeasti.
  4. Korkean saatavuuden palvelut. Varmista, että palvelusi on rakennettu vaakasuunnassa skaalautuviksi ja erittäin saataville alusta alkaen noudattamalla seuraavia periaatteita:
    • Harjoittele palvelun valtiottomuutta ja vältä käyttäjien istuntojen tallentamista muistin välimuistiin. Käytä sen sijaan hajautettua välimuistijärjestelmää, kuten Redis.
    • Vältä luottamista viestien kulutuksen kronologiseen järjestykseen logiikkaa kehitettäessä.
    • Minimoi rikkoutuvat muutokset estääksesi häiritsevät API-kuluttajia. Jos mahdollista, valitse taaksepäin yhteensopivat muutokset. Harkitse myös kustannuksia, koska joskus murtuvan muutoksen toteuttaminen voi olla kustannustehokkaampaa.
    • Sisällytä siirron suorittaminen käyttöönottoprosessiin.
    • Luo strategia samanaikaisten pyyntöjen käsittelemiseksi.
    • Ota palveluhaku, seuranta ja kirjaaminen käyttöön parantaaksesi luotettavuutta ja havaittavuutta.
    • Kehitä liiketoimintalogiikka idempotenttiksi ja tunnusta, että verkkohäiriöt ovat väistämättömiä.
  5. Riippuvuuden tarkistus. Tarkista säännöllisesti ja minimoi ulkoiset riippuvuudet. Jokainen ulkoinen riippuvuus voi aiheuttaa mahdollisia SPOF:ita, joten on tärkeää ymmärtää ja lieventää näitä riskejä.
  6. Säännöllinen tiedon jakaminen. Älä koskaan unohda tiedon levittämisen tärkeyttä organisaatiossasi. Ihmiset voivat olla arvaamattomia, ja yhteen yksilöön luottaminen on riskialtista. Kannusta tiimin jäseniä digitalisoimaan tietonsa dokumentoinnin avulla. Muista kuitenkin liiallinen dokumentointi. Käytä erilaisia tekoälytyökaluja tämän prosessin yksinkertaistamiseksi.

Johtopäätös

Tässä artikkelissa käsittelimme useita makronäkökohtia ja kuinka voimme käsitellä niiden monimutkaisuutta.


Kiitos kun luit! Nähdään ensi kerralla!