Hver dag, hvert øjeblik i vores ingeniørkarriere, støder vi på mange forskellige problemer af forskellig kompleksitet og situationer, hvor vi er nødt til at træffe en beslutning eller udskyde den på grund af mangel på data. Når vi bygger nye tjenester, konstruerer infrastruktur eller endda danner udviklingsprocesser, berører vi en enorm verden af forskellige udfordringer.
Det er udfordrende, og måske endda umuligt, at opremse alle problemerne. Du vil kun støde på nogle af disse problemer, hvis du arbejder i en bestemt niche. Til gengæld er der mange, som vi alle skal forstå at løse, da de er afgørende for opbygningen af it-systemer. Med stor sandsynlighed vil du støde på dem i alle projekter.
I denne artikel vil jeg dele mine erfaringer med nogle af de problemer, jeg er stødt på under oprettelse af softwareprogrammer.
Hvis vi kigger på Wikipedia, finder vi følgende definition
I aspektorienteret softwareudvikling er tværgående bekymringer aspekter af et program, der påvirker flere moduler, uden mulighed for at blive indkapslet i nogen af dem. Disse bekymringer kan ofte ikke dekomponeres rent fra resten af systemet i både design og implementering, og kan resultere i enten spredning (kodeduplikering), sammenfiltring (betydelige afhængigheder mellem systemer) eller begge dele.
Det beskriver i høj grad, hvad det er, men jeg vil gerne udvide og forenkle det lidt:
En tværgående bekymring er et koncept eller en komponent i systemet/organisationen, der påvirker (eller 'skærer på tværs') mange andre dele.
De bedste eksempler på sådanne bekymringer er systemarkitektur, logning, sikkerhed, transaktionsstyring, telemetri, databasedesign og der er mange andre. Vi kommer til at uddybe mange af dem senere i denne artikel.
På kodeniveau implementeres tværgående bekymringer ofte ved hjælp af teknikker som Aspect-Oriented Programming (AOP) , hvor disse bekymringer er modulariseret i separate komponenter, der kan anvendes i hele applikationen. Dette holder forretningslogikken isoleret fra disse bekymringer, hvilket gør koden mere læsbar og vedligeholdelig.
Der er mange mulige måder at klassificere aspekter ved at segmentere dem med forskellige egenskaber som omfang, størrelse, funktionalitet, vigtighed, mål og andre, men i denne artikel vil jeg bruge en simpel omfangsklassificering. Med dette mener jeg, hvor dette specifikke aspekt er rettet, uanset om det er hele organisationen, et bestemt system eller et specifikt element i det system.
Så jeg vil opdele aspekter i makro og mikro .
Med makroaspekt mener jeg hovedsageligt overvejelser, vi følger for hele systemet, såsom valgt systemarkitektur og dets design (monolitisk, mikrotjenester, serviceorienteret arkitektur), teknologistak, organisationsstruktur osv. Makroaspekter er hovedsageligt relateret til strategisk og højt niveau beslutninger.
I mellemtiden er Micro- aspektet meget tættere på kodeniveauet og udviklingen. For eksempel, hvilken ramme der bruges til at interagere med databasen, projektstrukturen af mapper og klasser eller endda specifikke objektdesignmønstre.
Selvom denne klassifikation ikke er ideel, hjælper den med at strukturere en forståelse af mulige problemer og vigtigheden og virkningen af løsninger, vi anvender på dem.
I denne artikel vil mit primære fokus være på makroaspekterne.
Da jeg lige begyndte at lære om softwarearkitektur, læste jeg mange interessante artikler om Conways lov og dens indvirkning på organisationsstrukturen. Især denne . Så det siger denne lov
Enhver organisation, der designer et system (defineret bredt) vil producere et design, hvis struktur er en kopi af organisationens kommunikationsstruktur.
Jeg har altid troet, at dette koncept faktisk er meget universelt og repræsenterer den gyldne regel.
Så begyndte jeg at lære Eric Evans's Domain-Driven Design (DDD) tilgang til modellering af systemer. Eric Evans understreger vigtigheden af Bounded Context identifikation. Dette koncept involverer opdeling af en kompleks domænemodel i mindre, mere håndterbare sektioner, hver med sit eget begrænsede sæt af viden. Denne tilgang hjælper med effektiv teamkommunikation, da den reducerer behovet for omfattende viden om hele domænet og minimerer kontekstskifte, hvilket gør samtaler mere effektive. Kontekstskift er det værste og mest ressourcekrævende nogensinde. Selv computere kæmper med det. Selvom det er usandsynligt at opnå et fuldstændigt fravær af kontekstskifte, regner jeg med, at det er det, vi bør stræbe efter.
For at vende tilbage til Conways lov, har jeg fundet flere problemer med den.
Det første problem, jeg er stødt på med Conways lov, som antyder, at systemdesign afspejler organisatorisk struktur, er potentialet for at danne komplekse og omfattende Bounded Contexts. Denne kompleksitet opstår, når den organisatoriske struktur ikke er tilpasset domænegrænser, hvilket fører til Bounded Contexts, der er stærkt indbyrdes afhængige og fyldt med information. Det fører til hyppige kontekstskifte for udviklingsteamet.
Et andet problem er, at organisatorisk terminologi lækker til kodeniveauet. Når organisatoriske strukturer ændrer sig, nødvendiggør det kodebasemodifikationer, hvilket tærer på værdifulde ressourcer.
Følgende Inverse Conway Maneuver hjælper således med at opbygge systemet og organisationen, der fremmer den ønskede softwarearkitektur. Det er dog bemærkelsesværdigt at sige, at denne tilgang ikke vil fungere særlig godt i allerede dannede arkitekturer og strukturer, da ændringer på dette stadium er langvarige, men den er exceptionelt præsterende i startups, da de er hurtige til at indføre ændringer.
Dette mønster eller "anti-mønster" driver opbygningen af et system uden arkitektur. Der er ingen regler, ingen grænser og ingen strategi for, hvordan man kontrollerer den uundgåelige voksende kompleksitet. Kompleksitet er den mest formidable fjende på rejsen med at bygge softwaresystemer.
For at undgå at konstruere en sådan type system er vi nødt til at følge specifikke regler og begrænsninger.
Der er utallige definitioner for softwarearkitektur. Jeg kan godt lide mange af dem, da de dækker forskellige aspekter af det. Men for at kunne ræsonnere om arkitektur, er vi naturligvis nødt til at danne nogle af dem i vores sind. Og det er bemærkelsesværdigt at sige, at denne definition kan udvikle sig. Så, i det mindste for nu, har jeg følgende beskrivelse for mig selv.
Softwarearkitektur handler om beslutninger og valg, du træffer hver dag, og som påvirker det byggede system.
For at træffe beslutninger, du skal have i din "bag" principper og mønstre for at løse opståede problemer, er det også vigtigt at sige, at forståelse af kravene er nøglen til at opbygge, hvad en virksomhed har brug for. Men nogle gange er kravene ikke gennemsigtige eller endda ikke definerede, i dette tilfælde er det bedre at vente med at få mere afklaring eller stole på din erfaring og stole på din intuition. Men alligevel kan du ikke træffe beslutninger ordentligt, hvis du ikke har principper og mønstre at stole på. Det er her, jeg kommer til definitionen af Software Architecture Style.
Software Architecture Style er et sæt principper og mønstre, der angiver, hvordan man bygger software.
Der er mange forskellige arkitektoniske stilarter med fokus på forskellige sider af den planlagte arkitektur, og det er en normal situation at anvende flere af dem på én gang.
For eksempel, såsom:
Monolitisk arkitektur
Domænedrevet design
Komponentbaseret
Mikrotjenester
Rør og filtre
Begivenhedsdrevet
Mikrokerne
Serviceorienteret
og så videre…
Selvfølgelig har de deres fordele og ulemper, men det vigtigste, jeg har lært, er, at arkitekturen udvikler sig gradvist, mens den afhænger af faktiske problemer. Begyndende med den monolitiske arkitektur er et godt valg til at reducere operationelle kompleksiteter, meget sandsynligt vil denne arkitektur passe til dine behov, selv efter at have nået ud til Product-market Fit (PMI) fasen af opbygningen af produktet. I stor skala kan du overveje at gå i retning af en begivenhedsdrevet tilgang og mikrotjenester for at opnå uafhængig implementering, heterogent teknologisk stackmiljø og mindre koblet arkitektur (og mindre gennemsigtig i mellemtiden på grund af arten af begivenhedsdrevne og pub-under-tilgange, hvis disse er vedtaget). Enkelhed og effektivitet er tæt på og har stor indflydelse på hinanden. Normalt påvirker komplicerede arkitekturer udviklingshastigheden af nye funktioner, understøtter og vedligeholder eksisterende og udfordrer systemets naturlige udvikling.
Imidlertid kræver komplekse systemer ofte kompleks og omfattende arkitektur, hvilket er uundgåeligt.
Dette er rimeligvis et meget bredt emne, og der er mange gode ideer om, hvordan man strukturerer og bygger systemer til naturlig evolution. På baggrund af mine erfaringer har jeg udarbejdet følgende fremgangsmåde:
Det er også vigtigt at forstå tallene og målene som DAU (Daily Active Users), MAU (Monthly Active Users), RPC (Request Per Second) og TPC (Transaction Per Second), da det kan hjælpe dig med at træffe valg, fordi arkitektur for 100 aktive brugere og 100 millioner aktive brugere er forskellige.
Som en sidste bemærkning vil jeg sige, at arkitektur har en væsentlig indflydelse på produktets succes. Dårligt designet arkitektur til produkterne er påkrævet i skalering, hvilket med stor sandsynlighed fører til fejl, da kunderne ikke vil vente, mens du skalerer systemet, de vil vælge en konkurrent, så vi skal være på forkant med potentiel skalering. Selvom jeg indrømmer, at det nogle gange ikke kunne være en slank tilgang, er ideen at have et skalerbart, men ikke allerede skaleret system. På den anden side vil det at have et meget kompliceret og allerede skaleret system uden kunder eller planer om at få mange af dem koste dig penge på din virksomhed for ingenting.
At vælge en teknologistack er også en beslutning på makroniveau, da det påvirker ansættelser, systemets naturlige udviklingsperspektiver, skalerbarhed og systemets ydeevne.
Dette er listen over grundlæggende overvejelser for at vælge en teknologistak:
Hvordan kan det påvirke virksomhedens vækst at have flere teknologistakke?
Fra et perspektiv kunne introduktion af en stak mere skalere din ansættelse, men på den anden side medfører det ekstra vedligeholdelsesomkostninger, da du skal understøtte begge stakke. Så, som jeg sagde tidligere, efter mit synspunkt, burde kun ekstra behov være et argument for at inkorporere flere teknologistakke.
Men hvad handler om princippet om at vælge det bedste værktøj til et specifikt problem?
Nogle gange har du ikke andet valg end at bringe nye værktøjer til at løse et specifikt problem baseret på de samme overvejelser førnævnte, i sådanne tilfælde giver det mening at vælge den bedste løsning.
At skabe systemer uden høj kobling til en specifik teknologi kan være en udfordring. Alligevel er det nyttigt at stræbe efter en tilstand, hvor systemet ikke er tæt koblet til teknologi, og det vil ikke dø, hvis i morgen, en specifik ramme eller et værktøj bliver sårbart eller endda forældet.
En anden vigtig overvejelse er relateret til open source og proprietære softwareafhængigheder. Proprietær software giver dig mindre fleksibilitet og mulighed for at blive tilpasset. Alligevel er den farligste faktor leverandørlåsning, hvor du bliver afhængig af en leverandørs produkter, priser, vilkår og køreplan. Dette kan være risikabelt, hvis leverandøren ændrer retning, hæver priserne eller stopper produktet. Open source-software reducerer denne risiko, da en enkelt enhed ikke kontrollerer den. At eliminere et enkelt fejlpunkt på alle niveauer er nøglen til at opbygge pålidelige systemer til vækst.
Et enkelt fejlpunkt (SPOF) refererer til enhver del af et system, der, hvis det fejler, vil få hele systemet til at holde op med at fungere. Eliminering af SPOF'er på alle niveauer er afgørende for ethvert system, der kræver høj tilgængelighed. Alt, inklusive viden, personale, systemkomponenter, cloud-udbydere og internetkabler, kan fejle.
Der er flere grundlæggende teknikker, vi kan anvende for at eliminere enkelte fejlpunkter:
I denne artikel dækkede vi flere vigtige makroaspekter , og hvordan vi kan håndtere deres kompleksitet.
Tak fordi du læste med! Vi ses næste gang!