Arkitektura & Design Patterns

Si ndërtohen sistemet që rriten pa u prishur — parimet SOLID, modelet e projektimit, arkitektura e pastër dhe projektimi i sistemeve. · 153 terma

Abstract factory

Fabrika abstrakte

Fabrika abstrakte krijon familje objektesh që shkojnë bashkë — p.sh. butona, menu dhe dritare për temën e errët ose të çelët — pa që kodi të dijë cilën familje po përdor.

Adapter pattern

Modeli përshtatës

Një adapter e bën një klasë me ndërfaqe të papërshtatshme të duket si ajo që pret kodi yt — p.sh. një librari e vjetër pagesash e mbështjellë që të përputhet me ndërfaqen tënde Pagesa.

Aggregates

Agregatet

Një agregat është një grup objektesh që trajtohen si një njësi për ndryshime — p.sh. Porosia me rreshtat e saj. Gjithçka kalon nga „rrënja“ (Porosia), që garanton rregullat (totali s'mund të jetë negativ).

Analysing architectural trade-offs

Analiza e kompromiseve arkitekturore

Për vendime të mëdha, krahaso alternativat në mënyrë të strukturuar: listo kriteret (kosto, shpejtësi, kompleksitet, aftësitë e ekipit), jepu pesha dhe vlerëso secilën. S'jep përgjigjen automatikisht, por i bën vendimet të qarta dhe të diskutueshme.

Anemic domain model

Modeli anemik i domenit

Kur klasat e domenit (Porosia, Klienti) kanë vetëm të dhëna dhe getter/setter, ndërsa gjithë logjika është në „shërbime“ — objektet bëhen thjesht kuti. Te një model „i pasur“, logjika jeton pranë të dhënave.

Anti-corruption layer

Shtresa kundër korrupsionit

Kur integron një sistem të vjetër ose të huaj me model të çuditshëm, vendos një shtresë përkthyese që e kthen në modelin tënd të pastër — që „ndotja“ e sistemit tjetër të mos përhapet në kodin tënd.

Anti-patterns

Anti-modelet

Një anti-model është një „zgjidhje“ që duket e mirë por sjell më shumë probleme: objekti zot, kodi spageti, çekiçi i artë, kopjim-ngjitja. Njohja e tyre të ndihmon t'i shmangësh — dhe t'i emërtosh në code review.

API-first & contract-first design

Projektimi që fillon nga API-ja

Para se të shkruash kod, ekipi bie dakord për API-në (me OpenAPI ose një skemë GraphQL). Frontend-i dhe backend-i punojnë pastaj paralelisht kundrejt së njëjtës kontratë, me imitime derisa të jetë gati gjithçka.

Architecture decision records (ADR)

Regjistrat e vendimeve arkitekturore

Një ADR është një dokument i shkurtër për çdo vendim të rëndësishëm: konteksti, vendimi, alternativat dhe pasojat („Zgjodhëm PostgreSQL në vend të MongoDB sepse…“). Pas dy vitesh, të gjithë e dinë pse.

Architecture diagrams (Mermaid, Excalidraw)

Diagramet e arkitekturës

Një diagram i mirë vlen sa një mijë fjalë: kutitë janë shërbime, shigjetat janë komunikime. Mermaid shkruan diagrame si tekst në Markdown (GitHub i shfaq), Excalidraw dhe draw.io vizatojnë me dorë.

Architecture for startups & small teams

Arkitektura për startup-e dhe ekipe të vogla

Për ekipe të vogla: një monolit i mirë, një databazë PostgreSQL, një platformë publikimi e thjeshtë dhe „teknologji e mërzitshme“ e provuar. Shpejtësia e mësimit dhe e ndryshimit ka më shumë rëndësi se shkallëzimi për miliona përdorues.

Architecture katas & practice

Ushtrimet e arkitekturës

Arkitektura mësohet duke praktikuar: „architecture katas“ janë ushtrime ku ekipi projekton një sistem imagjinar në një orë dhe e prezanton. Mënyra të tjera: lexo blogje inxhinierike (Netflix, Uber, Shopify) dhe rishiko projektimet e kolegëve.

Architecture of AI-powered apps

Arkitektura e aplikacioneve me AI

Një aplikacion me AI zakonisht ka: API-në e LLM-së, një databazë vektoriale për RAG, prompt-e të versionuara, guardrails, cache për përgjigjet, evals në CI dhe monitorim të kostove dhe cilësisë. AI-ja është një komponent, jo gjithë sistemi.

Architecture reviews

Rishikimet e arkitekturës

Para ndryshimeve të mëdha, një grup inxhinierësh me përvojë rishikon projektimin: a i plotëson kërkesat, a ka rreziqe sigurie ose shkallëzimi, a ka alternativa më të thjeshta. Më mirë të gjesh problemet në letër sesa në prodhim.

Architecture smells

Shenjat e arkitekturës së keqe

Shenja paralajmëruese: një ndryshim i vogël kërkon ndryshime në 10 vende („shotgun surgery“), modulet varen në cikël, shërbimet duhet të publikohen bashkë, ose askush s'di ku shkon një veçori e re. Koha për rifaktorim.

Availability patterns

Modelet e disponueshmërisë

Për të mos rënë kurrë: kopje rezervë të çdo pjese (active-passive: njëra pret; active-active: të dyja punojnë), kontrolle shëndeti, kalim automatik, shumë zona disponueshmërie dhe asnjë „pikë e vetme dështimi“.

Back-of-the-envelope estimation

Llogaritjet e përafërta

Para se të projektosh, llogarit përafërsisht: 1 milion përdorues × 10 kërkesa në ditë ≈ 115 kërkesa në sekondë; 1 KB për postim × 1 milion postime në ditë ≈ 365 GB në vit. Këto numra tregojnë nëse të duhet një server apo njëqind.

Backend for frontend (BFF)

Backend për frontend

Në vend të një API-je të përbashkët për të gjithë, çdo klient (faqja web, aplikacioni mobile) ka një backend të vogël të vetin që i përgatit saktësisht të dhënat që i duhen. Më pak kërkesa dhe më pak të dhëna të panevojshme.

Big ball of mud

Topi i madh me baltë

Sistemi pa asnjë strukturë të qartë, ku çdo gjë lidhet me çdo gjë — zakonisht rezultat i vitesh me ndryshime të nxituara. Është arkitektura më e zakonshme në botë. Shërohet ngadalë, me kufij dhe rifaktorim të vazhdueshëm.

Bounded context

Konteksti i kufizuar

E njëjta fjalë mund të ketë kuptime të ndryshme në pjesë të ndryshme të biznesit: „produkti“ te shitjet (çmimi, foto) s'është i njëjtë me „produktin“ te magazina (pesha, rafti). Çdo kontekst ka modelin e vet — dhe shpesh bëhet modul ose shërbim më vete.

Bridge & flyweight patterns

Modelet urë dhe flyweight

Bridge ndan „çfarë“ nga „si“ (forma nga mënyra e vizatimit), që të zgjerohen veç e veç. Flyweight ndan të dhënat e përbashkëta mes mijëra objekteve të ngjashme (p.sh. shkronjat në një editor) për të kursyer memorie.

Build vs buy

Ta ndërtosh vetë apo ta blesh?

Për çdo pjesë që s'është thelbi i biznesit tënd (autentikimi, pagesat, email-et, kërkimi), shpesh është më mirë të përdorësh një shërbim ekzistues. Ndërto vetë vetëm atë që të dallon nga konkurrentët. „Not invented here“ është gabim i shtrenjtë.

Bulkheads & timeouts

Ndarjet dhe afatet kohore

Si ndarjet e anijes që s'lejojnë ujin të përhapet: jepi çdo varësie një grup të veçantë burimesh (thread-e, lidhje), që po ngadalësohet njëra, të mos i bllokojë të gjitha. Dhe vendos gjithmonë afate kohore — pa to, një shërbim i ngadaltë i ngrin të gjithë.

C4 model

Modeli C4

Modeli C4 vizaton arkitekturën në katër nivele zmadhimi: Konteksti (sistemi dhe përdoruesit), Kontejnerët (aplikacionet dhe databazat), Komponentët (pjesët brenda) dhe Kodi. Si një hartë që zmadhohet.

Caching strategies (cache-aside, write-through)

Strategjitë e cache-it

Cache-aside: aplikacioni kërkon në cache, po s'gjendet lexon databazën dhe e ruan. Write-through: çdo shkrim shkon njëkohësisht në cache dhe databazë. Write-behind: shkruan në cache dhe databaza përditësohet më vonë (shpejt, por me rrezik).

Chain of responsibility

Zinxhiri i përgjegjësisë

Një kërkesë kalon nëpër një varg trajtuesish dhe secili vendos ta trajtojë ose t'ia kalojë të radhës. Middleware-t e Express-it dhe ASP.NET janë pikërisht kështu.

Classic architecture & design books

Librat klasikë të arkitekturës

Leximet më të rekomanduara: „Head First Design Patterns“ (fillestarë), „Clean Code“ dhe „Clean Architecture“ (Robert C. Martin), „Designing Data-Intensive Applications“ (Martin Kleppmann — bibla e sistemeve të shpërndara) dhe „Fundamentals of Software Architecture“.

Clean architecture

Arkitektura e pastër

Clean Architecture (Robert C. Martin) vendos logjikën e biznesit në qendër dhe gjithçka tjetër (UI, databaza, framework-et) në rrathë përreth. „Rregulli i varësisë“: varësitë tregojnë vetëm drejt qendrës — logjika s'di asgjë për databazën.

Client-server architecture

Arkitektura klient–server

Modeli më i përhapur: klientët (shfletuesi, aplikacioni mobile) i kërkojnë shërbime serverit, që mban të dhënat dhe logjikën kryesore. Pothuajse çdo aplikacion web ndjek këtë model.

Cloud architecture patterns

Modelet e arkitekturës në cloud

Ofruesit e cloud-it kanë katalogë me modele të gatshme (Azure Architecture Center, AWS Architecture Center): web app me shumë nivele, përpunim në sfond, arkitekturë serverless, analiza të dhënash. Pikënisje e mirë për projekte reale.

Cohesion in practice

Kohezioni në praktikë

Një modul me kohezion të lartë ka gjëra që ndryshojnë bashkë dhe për të njëjtën arsye (gjithçka për faturat). Kohezion i ulët: një „utils.js“ me funksione që s'kanë lidhje — çdo ndryshim prek gjëra të palidhura.

Command pattern

Modeli komandë

Modeli komandë e kthen një veprim në objekt („FshiTekstin“, „ShtoFormen“) që mund të ruhet, të vihet në radhë, të ekzekutohet më vonë ose të zhbëhet. Kështu ndërtohen „undo/redo“ në editorë.

Command-query separation (CQS)

Ndarja komandë–pyetje

Çdo metodë duhet të jetë ose „komandë“ (ndryshon diçka, s'kthen vlerë) ose „pyetje“ (kthen vlerë, s'ndryshon asgjë) — jo të dyja. Kështu leximi s'ka kurrë efekte anësore të papritura.

Composite pattern

Modeli i përbërë

Composite të lejon t'i trajtosh njësoj objektet e vetme dhe grupet e tyre — p.sh. dosjet dhe skedarët (një dosje përmban skedarë dhe dosje), ose komponentët e një faqeje. madhesia() punon për të dyja.

Composition patterns (mixins, traits, delegation)

Modelet e përbërjes

Në vend të trashëgimisë së thellë („është një“), ndërto objekte nga pjesë më të vogla („ka një“): delegim (objekti i kalon punën një tjetri), mixins dhe traits. Më fleksibël dhe më pak e brishtë.

Configuration management

Menaxhimi i konfigurimit

Cilësimet (adresat, çelësat, kufijtë, flamujt) duhen mbajtur jashtë kodit — në variabla ambienti, skedarë ose shërbime konfigurimi — që i njëjti build të punojë në çdo ambient dhe të ndryshohet pa ripublikim.

Context mapping

Harta e konteksteve

Harta e konteksteve tregon si lidhen kontekstet e kufizuara: kush varet nga kush, kush e përcakton modelin, ku duhet një shtresë kundër korrupsionit, dhe çfarë ndahet (shared kernel).

Conway's law

Ligji i Conway-t

„Sistemet pasqyrojnë strukturën e komunikimit të organizatave që i ndërtojnë.“ Tre ekipe do të ndërtojnë një sistem me tre pjesë. Prandaj organizimi i ekipeve është vendim arkitekturor.

CQRS (command query responsibility segregation)

CQRS

CQRS ndan modelin që ndryshon të dhënat (komandat) nga modeli që i lexon (pyetjet) — shpesh edhe me databaza të ndryshme, ku ajo e leximit është e optimizuar për ekrane. I fuqishëm për sisteme të mëdha, i tepërt për shumicën e aplikacioneve.

Data architecture

Arkitektura e të dhënave

Arkitektura e të dhënave vendos ku jetojnë të dhënat, cili sistem është „burimi i së vërtetës“ për secilën, si lëvizin mes sistemeve (API, ngjarje, ETL) dhe si ruhen për analiza. Të dhënat jetojnë më gjatë se kodi.

Database per service

Një databazë për çdo shërbim

Në mikroshërbime, çdo shërbim zotëron të dhënat e veta dhe të tjerët i marrin vetëm përmes API-së ose ngjarjeve. Databaza e përbashkët i lidh shërbimet fort — ndryshimi i një tabele prish të tjerët.

Decorator pattern

Modeli dekorator

Dekoratori i shton sjellje të re një objekti duke e mbështjellë, pa ndryshuar klasën — p.sh. një shërbim që shton log ose cache rreth një tjetri. Shumë dekoratorë mund të vendosen njëri mbi tjetrin.

Defensive programming

Programimi mbrojtës

Programimi mbrojtës supozon që gjërat do të shkojnë keq: valido hyrjet, kontrollo vlerat null, trajto gabimet e rrjetit, vendos afate kohore. Por mos e tepro — kontrollet e panevojshme kudo e bëjnë kodin të vështirë për t'u lexuar.

Dependency graphs & cycles

Grafi i varësive

Modulet varen nga njëri-tjetri si një graf. Ciklet (A → B → A) e bëjnë kodin të vështirë për t'u kuptuar, testuar dhe ndarë. Mjete si madge (JS) ose ArchUnit (Java) i zbulojnë dhe mund t'i ndalojnë në CI.

Dependency inversion principle (DIP)

Parimi i përmbysjes së varësive

Kodi i nivelit të lartë (logjika e biznesit) s'duhet të varet nga detajet (MySQL, Stripe), por të dyja nga abstraksione (ndërfaqe). Kështu mund ta ndërrosh databazën ose ofruesin e pagesave pa prekur logjikën.

Design by contract

Projektimi me kontratë

Çdo funksion ka një „kontratë“: parakushtet (çfarë duhet të jetë e vërtetë kur thirret), paskushtet (çfarë garanton në fund) dhe invariantet (çfarë mbetet gjithmonë e vërtetë). Assert-et dhe tipet i bëjnë të qarta.

Design docs & RFCs

Dokumentet e projektimit

Para një ndryshimi të madh, shumë kompani shkruajnë një „design doc“ ose RFC: problemi, zgjidhja e propozuar, alternativat dhe rreziqet — dhe ekipi e komenton para se të shkruhet kodi. Kursen muaj pune të gabuar.

Design patterns in functional programming

Modelet e projektimit në programimin funksional

Shumë modele OOP thjeshtohen shumë në programimin funksional: Strategy është thjesht një funksion që e kalon si parametër, Command një closure, Decorator një funksion që mbështjell një tjetër. Ideja mbetet, kodi tkurret.

Design systems & component architecture

Sistemet e dizajnit

Një sistem dizajni është një bibliotekë e përbashkët komponentësh (butona, forma, karta), ngjyrash dhe rregullash që përdoren në të gjitha produktet. „Atomic design“ i organizon nga atomet (butona) te molekulat, organizmat dhe faqet.

Designing a chat system

Projektimi i një sistemi chat

Një chat ka nevojë për lidhje të vazhdueshme (WebSocket), ruajtje mesazhesh me renditje të saktë, statusin „online“, njoftime push për përdoruesit offline dhe shkallëzim kur miliona janë të lidhur njëkohësisht.

Designing a news feed

Projektimi i një „feed“-i

Si shfaqet „feed“-i i Instagram-it? „Fan-out on write“: kur poston, postimi kopjohet te feed-et e ndjekësve (shpejt për lexim). „Fan-out on read“: feed-i ndërtohet kur e hap. Llogaritë me miliona ndjekës kërkojnë qasje të përzier.

Designing a notification system

Projektimi i një sistemi njoftimesh

Një sistem njoftimesh merr ngjarje (porosi e re, mesazh), vendos kanalin (push, email, SMS) sipas preferencave të përdoruesit, i vë në radhë, provon sërish kur dështojnë dhe shmang dërgimin e të njëjtit njoftim dy herë.

Designing a rate limiter

Projektimi i një kufizuesi kërkesash

Pyetje e zakonshme e system design: kufizo çdo përdorues në N kërkesa në minutë. Algoritmet: token bucket, dritare fikse ose rrëshqitëse; numëruesit ruhen në Redis që të ndahen mes serverëve; përgjigjja kur kalohet kufiri është 429.

Designing a URL shortener

Projektimi i një shkurtuesi lidhjesh

Pyetje klasike: krijo kode të shkurtra unike (base62 nga një numërues ose hash), ruaji në një databazë çelës–vlerë, ridrejto me 301/302, përdor cache për lidhjet popullore dhe numëro klikimet në mënyrë asinkrone.

Designing file uploads

Projektimi i ngarkimit të skedarëve

Për ngarkime të mëdha (foto, video): klienti merr një URL të nënshkruar dhe ngarkon direkt në S3 (pa kaluar nga serveri yt), pastaj një punë në sfond i përpunon (miniaturat, kompresimi) dhe CDN-ja i shpërndan.

Designing payments

Projektimi i sistemit të pagesave

Pagesat kërkojnë kujdes të veçantë: përdor një ofrues (Stripe), çelësa idempotence, webhook-e për të konfirmuar statusin, një „libër llogarish“ (ledger) që s'fshihet kurrë, dhe pajtim të rregullt me raportet e ofruesit.

Designing search

Projektimi i kërkimit

Kërkimi kërkon një indeks të veçantë (Elasticsearch, Meilisearch ose edhe një indeks në memorie si ky fjalor), tolerancë ndaj gabimeve të shkrimit, renditje sipas rëndësisë, dhe për „autocomplete“ përgjigje nën 100 ms.

DI containers & composition root

Kontejnerët e injektimit të varësive

Një kontejner DI (Spring, .NET, NestJS, InversifyJS) krijon objektet dhe u jep varësitë automatikisht. „Composition root“ është vendi i vetëm ku lidhet gjithçka. „Service locator“ (të marrësh varësitë nga një regjistër global) konsiderohet anti-model.

Distributed monolith

Monoliti i shpërndarë

Mikroshërbime që duhet të publikohen bashkë, ndajnë të njëjtën databazë dhe thërrasin njëri-tjetrin për çdo gjë — ke të gjitha problemet e monolitit plus të gjitha problemet e rrjetit. Anti-modeli më i shtrenjtë.

Documenting architecture (arc42)

Dokumentimi i arkitekturës

arc42 është një shabllon falas për dokumentimin e arkitekturës: qëllimet, kufizimet, konteksti, pamjet e ndërtimit, vendimet dhe rreziqet. Mbaje dokumentimin pranë kodit (Markdown + diagrame si kod) që të mos vjetrohet.

Domain events

Ngjarjet e domenit

Një ngjarje domeni përshkruan diçka të rëndësishme që ndodhi në biznes, në kohën e shkuar: PorosiaUKrye, PagesaDështoi. Pjesë të tjera të sistemit reagojnë ndaj tyre pa qenë të lidhura direkt.

Domain-driven design (DDD)

Projektimi i drejtuar nga domeni

DDD (Eric Evans, 2003) thotë: ndërto software-in rreth domenit të biznesit, në bashkëpunim të ngushtë me ekspertët e tij. Kodi përdor të njëjtat fjalë si biznesi dhe ndahet sipas kufijve të domenit, jo sipas teknologjisë.

Encapsulate what varies

Izolo atë që ndryshon

Gjej pjesët e kodit që ka gjasa të ndryshojnë (mënyra e pagesës, formati i eksportit) dhe izoloji pas një ndërfaqeje, që ndryshimet e ardhshme të prekin vetëm një vend.

Entities vs value objects

Entitetet dhe objektet-vlerë

Një entitet ka identitet që zgjat në kohë (nxënësi #42 mbetet i njëjti edhe po ndërron emër). Një objekt-vlerë përcaktohet vetëm nga vlerat e tij dhe është i pandryshueshëm (Paraja(10, "EUR"), Adresa) — dy me vlera të njëjta janë të barabartë.

Error-handling strategy

Strategjia e trajtimit të gabimeve

Një sistem i mirë vendos qartë: ku kapen gabimet (në kufij, jo kudo), si raportohen (log + Sentry), çfarë sheh përdoruesi (mesazh i qartë, pa detaje teknike) dhe cilat gabime provohen sërish. Pa strategji, gabimet fshihen ose rrëzojnë gjithçka.

Event bus & observer in practice

Autobusi i ngjarjeve

Një „event bus“ i lejon pjesët e aplikacionit të komunikojnë pa e njohur njëra-tjetrën: njëra publikon „shporta u ndryshua“, të tjerat që interesohen reagojnë. E thjeshton varësinë, por mund ta bëjë rrjedhën të vështirë për t'u ndjekur.

Event storming

Stuhia e ngjarjeve

Një punëtori ku zhvilluesit dhe ekspertët e biznesit shkruajnë në letra ngjitëse portokalli të gjitha ngjarjet e domenit („Porosia u krye“, „Pagesa u refuzua“) dhe i rendisin në mur. Zbulon shpejt procesin dhe kufijtë e kontekstit.

Evolutionary architecture

Arkitektura evolutive

Arkitektura s'vendoset një herë përgjithmonë — ndryshon me produktin. „Fitness functions“ (teste që kontrollojnë rregullat e arkitekturës, p.sh. „UI s'thërret databazën direkt“) e mbrojnë ndërsa evoluon.

Facade pattern

Modeli fasadë

Një fasadë fsheh një sistem të ndërlikuar pas një ndërfaqeje të thjeshtë: porosit(produkt) thërret brenda magazinën, pagesën, faturimin dhe dërgesën. Kodi tjetër s'ka nevojë t'i njohë të gjitha.

Factory method vs simple factory

Metoda fabrikë

Një „fabrikë e thjeshtë“ është një funksion që vendos cilin objekt të krijojë (krijoPagesen("karte")). „Metoda fabrikë“ ia lë klasave bija të vendosin çfarë krijojnë. Të dyja fshehin new nga kodi që i përdor.

Fail fast

Dështo shpejt

Po diçka është gabim (konfigurim që mungon, hyrje e pavlefshme), ndalo menjëherë me një mesazh të qartë — në vend që të vazhdosh dhe të dështosh shumë më vonë në një vend misterioz. Gabimet e hershme janë më të lehta për t'u gjetur.

Flux & unidirectional data flow

Flux dhe rrjedha njëdrejtimëshe

Te Flux (dhe Redux, Elm), të dhënat lëvizin vetëm në një drejtim: veprim → store → pamje → veprim i ri. S'ka ndryshime të fshehta nga kudo, prandaj gjendja e aplikacionit është e parashikueshme dhe e lehtë për debug.

Frontend architecture

Arkitektura e frontend-it

Edhe frontend-et e mëdha kanë nevojë për arkitekturë: ndarje sipas veçorive, ku jeton gjendja (lokale, globale, server), si thirren API-të, si ndahen komponentët e përbashkët. „Feature-Sliced Design“ është një qasje e njohur.

Functional core, imperative shell

Bërthamë funksionale, guaskë imperative

Mbaje logjikën kryesore si funksione të pastra (pa databazë, rrjet ose kohë) — lehtë për t'u testuar — dhe vendose gjithë punën me botën e jashtme në një „guaskë“ të hollë përreth. Arkitekturë e thjeshtë dhe e fuqishme.

Gang of Four & pattern categories

„Banda e Katërshes“ dhe kategoritë e modeleve

Libri „Design Patterns“ (1994) i katër autorëve („Gang of Four“) përshkroi 23 modele në tri kategori: krijuese (si krijohen objektet), strukturore (si bashkohen) dhe të sjelljes (si komunikojnë). Ende baza e intervistave.

God object

Objekti „zot“

Një klasë që di dhe bën gjithçka — 5 000 rreshta, qindra metoda, të gjithë varen prej saj. Çdo ndryshim rrezikon të prishë diçka tjetër. Zgjidhja: ndaje sipas përgjegjësive.

Golden hammer & cargo cult

Çekiçi i artë dhe kulti i ngarkesës

„Çekiçi i artë“: përdorimi i të njëjtit mjet për çdo problem („gjithçka me mikroshërbime“). „Kulti i ngarkesës“: kopjimi i praktikave të Google-it pa kuptuar pse — kur ti s'ke problemet e Google-it.

Hexagonal architecture (ports & adapters)

Arkitektura heksagonale

Aplikacioni ka „porta“ (ndërfaqe: RuajtesiPorosive, DerguesiEmail) dhe „adapterë“ që i lidhin me botën reale (PostgreSQL, SendGrid, REST, teste). Mund ta testosh logjikën pa databazë dhe të ndërrosh teknologjitë lehtë.

Hot spots & partitioning keys

Pikat e nxehta dhe çelësat e ndarjes

Kur ndan të dhënat mes serverëve, një çelës i keq krijon „pika të nxehta“ — p.sh. llogaria e një këngëtari të famshëm merr miliona kërkesa në një server të vetëm. Zgjidhjet: çelësa më të shpërndarë, cache dhe kopje shtesë.

Idempotency keys

Çelësat e idempotencës

Kur klienti dërgon „paguaj 50 €“ dhe s'merr përgjigje, provon sërish — por a u pagua dy herë? Me një „idempotency key“ unik për çdo veprim, serveri e njeh përsëritjen dhe s'e ekzekuton sërish. Stripe e përdor kudo.

Immutability as an architectural choice

Pandryshueshmëria si zgjedhje arkitekturore

Sisteme që s'ndryshojnë të dhënat, por vetëm shtojnë të reja (log-e, ngjarje, versione) janë më të lehta për t'u debug-uar, auditu dhe shkallëzuar. Git-i, blockchain-i dhe event sourcing ndjekin këtë ide.

Interface segregation principle (ISP)

Parimi i ndarjes së ndërfaqeve

Mos i detyro klasat të implementojnë metoda që s'u duhen. Më mirë shumë ndërfaqe të vogla (Lexues, Shkrues) se një ndërfaqe gjigante (Gjithçka) ku gjysma e metodave hedhin „not implemented“.

Interfaces at system boundaries

Ndërfaqet në kufijtë e sistemit

Vendos ndërfaqe aty ku kodi yt takon botën e jashtme — databaza, API të huaja, ora, sistemi i skedarëve. Këto „shtresa“ të lejojnë të ndërrosh teknologjinë dhe të testosh pa shërbimet e vërteta.

Inversion of control (IoC)

Përmbysja e kontrollit

Te IoC, s'e kontrollon ti kur thirret kodi yt — e thërret framework-u (React thërret komponentët e tu, Spring krijon objektet). „Mos na telefono, do të të telefonojmë ne.“ Dependency injection është një formë e saj.

Islands architecture

Arkitektura me ishuj

Faqja është kryesisht HTML statike i shpejtë, dhe vetëm disa „ishuj“ interaktivë (kërkimi, karuseli) ngarkojnë JavaScript. Astro e bëri të njohur. Shumë më pak JS se një SPA e plotë.

Iterator pattern

Modeli iterator

Iteratori të lejon të përshkosh elementet e një koleksioni një nga një pa ditur si ruhet nga brenda (varg, pemë, listë e lidhur). Sot është i integruar në çdo gjuhë: for...of, foreach, Iterator.

Latency numbers every programmer should know

Vonesat që duhet t'i dijë çdo programues

Përafërsisht: leximi nga cache i CPU-së ~1 ns, nga RAM ~100 ns, nga SSD ~100 µs, një udhëtim në rrjetin e brendshëm ~0.5 ms, Tirana–Frankfurt ~30 ms, Tirana–Kaliforni ~150 ms. Prandaj cache-i dhe CDN-ja kanë kaq shumë rëndësi.

Law of Demeter

Ligji i Demeter-it

Një objekt duhet të flasë vetëm me „miqtë e afërt“, jo me miqtë e miqve: porosia.klienti.adresa.qyteti.emri është shenjë e keqe („train wreck“). Më mirë porosia.qytetiIDergeses().

Layered (n-tier) architecture

Arkitektura me shtresa

Kodi ndahet në shtresa: prezantimi (UI/API), logjika e biznesit dhe qasja te të dhënat. Çdo shtresë flet vetëm me atë poshtë saj. E thjeshtë dhe shumë e përhapur — por logjika rrezikon të shpërndahet nëpër shtresa.

Learning software architecture: a roadmap

Si ta mësosh arkitekturën e software-it

Rruga e zakonshme: kod i pastër dhe SOLID → modelet kryesore (strategy, observer, factory, adapter, decorator) → arkitektura me shtresa dhe clean/hexagonal → DDD bazë → sistemet e shpërndara (cache, radhë, replikim) → system design. Praktiko me projekte reale.

Legacy modernization

Modernizimi i sistemeve të vjetra

Rishkrimi i plotë nga zero („big rewrite“) dështon shpesh: zgjat më shumë se pritej dhe humbet njohuri të fshehura në kodin e vjetër. Zakonisht më mirë: përmirëso hap pas hapi me strangler fig, teste karakterizimi dhe rifaktorim.

Levels of abstraction

Nivelet e abstraksionit

Një funksion i mirë qëndron në një nivel abstraksioni: regjistroNxenesin() thërret valido(), ruaj(), dergoEmail() — jo të përzier me detaje si ndërtimi i query-ve SQL. Kodi lexohet si një tregim nga lart poshtë.

Liskov substitution principle (LSP)

Parimi i zëvendësimit të Liskov-it

Kudo ku pritet një klasë prind, duhet të mund të vendosësh një klasë bijë pa prishur asgjë. Shembulli klasik: Katrori si bijë e Drejtkëndëshit thyen LSP-në, sepse ndryshimi i gjerësisë ndryshon edhe gjatësinë.

Mediator pattern

Modeli ndërmjetës

Në vend që shumë objekte të flasin të gjitha me njëra-tjetrën (rrëmujë), komunikojnë përmes një ndërmjetësi qendror. Kulla e kontrollit të aeroportit është shembulli klasik; MediatR në C# e përdor.

Memento pattern

Modeli memento

Memento ruan një „fotografi“ të gjendjes së një objekti që të rikthehet më vonë — pa ekspozuar detajet e tij të brendshme. Përdoret për ruajtje lojërash dhe „undo“.

Micro-frontends

Mikro-frontend-et

Mikro-frontend-et ndajnë një faqe të madh web në pjesë që ndërtohen dhe publikohen nga ekipe të ndryshme (kërkimi, shporta, profili), ndonjëherë edhe me framework-e të ndryshme. Për organizata të mëdha; për ekipe të vogla zakonisht e tepërt.

Microkernel & plugin architecture

Arkitektura me bërthamë dhe plugin-e

Një bërthamë e vogël me funksionet bazë, dhe pjesa tjetër shtohet me plugin-e. VS Code, WordPress, Chrome dhe Eclipse janë ndërtuar kështu — të tjerët mund ta zgjerojnë produktin pa e ndryshuar.

Migration strategies (big bang vs incremental)

Strategjitë e migrimit

Kur kalon në një sistem të ri: „big bang“ (gjithçka njëherësh — rrezik i madh), gradualisht (modul pas moduli), ose „parallel run“ (të dy sistemet punojnë njëkohësisht dhe krahasohen derisa i riu provohet i saktë).

Mobile app architecture

Arkitektura e aplikacioneve mobile

Aplikacionet mobile kanë sfida të veçanta: punojnë offline, sinkronizojnë kur ka rrjet, mbajnë gjendjen kur aplikacioni mbyllet dhe s'mund të përditësohen menjëherë te të gjithë. MVVM dhe clean architecture janë të zakonshme.

Modular monolith

Monoliti modular

Një monolit i ndarë në module me kufij të qartë (porositë, pagesat, përdoruesit) që komunikojnë vetëm përmes ndërfaqeve publike. Ke thjeshtësinë e monolitit dhe rregullin e mikroshërbimeve — dhe mund t'i ndash më vonë po të duhet.

Module boundaries & public APIs

Kufijtë e moduleve

Çdo modul duhet të ketë një „derë të përparme“ të qartë (index.ts, ndërfaqe publike) dhe të fshehë pjesën tjetër. Kur modulet thërrasin brendësinë e njëri-tjetrit, kufijtë prishen dhe ndryshimet përhapen kudo.

Monolith

Monoliti

Një monolit është një aplikacion i vetëm që publikohet si një tërësi. Shpesh zgjedhja më e mirë për fillim: i thjeshtë për t'u zhvilluar, testuar dhe publikuar. Shopify, Stack Overflow dhe Basecamp ende janë monolite.

Multi-tenant SaaS architecture

Arkitektura SaaS për shumë klientë

Një aplikacion SaaS u shërben shumë kompanive njëkohësisht. Vendimi kryesor: sa i izolon klientët — databazë e përbashkët me tenant_id (e lirë), skemë për secilin, apo infrastrukturë krejt e ndarë (e shtrenjtë, por më e sigurt).

MVP (model-view-presenter)

Modeli MVP

Si MVC, por „Presenter“-i merr gjithë logjikën e ndërfaqes dhe View-ja bëhet sa më e thjeshtë (vetëm shfaq) — e lehtë për t'u testuar. U përdor shumë në Android dhe WinForms para MVVM-së.

Null object pattern

Modeli i objektit bosh

Në vend që të kthesh null (dhe të kontrollosh if (x != null) kudo), kthe një objekt „bosh“ që s'bën asgjë — p.sh. PerdoruesiMysafir me emrin „Mysafir“ dhe pa leje. Kodi bëhet më i thjeshtë dhe pa rrëzime.

Object pool pattern

Modeli i grupit të objekteve

Kur krijimi i objekteve është i shtrenjtë (lidhje databaze, plumba në lojë), mbahen disa gati në një „pool“ dhe ripërdoren në vend që të krijohen e fshihen vazhdimisht.

Object-oriented design interviews

Intervistat për projektimin e objekteve

Pyetje si „projekto një parking“ ose „projekto një ashensor“ testojnë projektimin e klasave: gjej entitetet, përgjegjësitë, lidhjet dhe modelet e duhura. Fillo me kërkesat, vizato klasat, pastaj shkruaj metodat kryesore.

Observability by design

Vëzhgueshmëria që nga projektimi

Mendo që në fillim si do ta kuptosh sistemin kur të ketë probleme: një ID kërkese që kalon nëpër të gjitha shërbimet, log-e të strukturuara, metrika për çdo veprim të rëndësishëm dhe trace-e mes shërbimeve.

One-way & two-way door decisions

Vendimet e kthyeshme dhe të pakthyeshme

Disa vendime janë „derë me dy kahe“ (lehtë për t'u ndryshuar — merri shpejt), të tjera „me një kah“ (zgjedhja e databazës, struktura e të dhënave — mendo mirë). Shtyji vendimet e vështira deri në „momentin e fundit të përgjegjshëm“.

Onion architecture

Arkitektura qepë

E ngjashme me clean dhe hexagonal: domeni në qendër, pastaj shërbimet e aplikacionit, dhe infrastruktura (databaza, UI) në shtresën e jashtme. Të treja ndajnë të njëjtën ide: logjika e rëndësishme s'varet nga detajet teknike.

Open/closed principle (OCP)

Parimi i hapur/mbyllur

Kodi duhet të jetë „i hapur për zgjerim, i mbyllur për ndryshim“: shton sjellje të re duke shtuar kod (një klasë e re, një plugin), jo duke ndryshuar kodin që punon tashmë. Polimorfizmi dhe strategjitë e bëjnë të mundur.

Over-engineering vs under-engineering

Tepër-inxhinieria dhe mangësia e saj

Tepër-inxhinieria është ndërtimi i diçkaje shumë më të ndërlikuar se sa duhet (mikroshërbime për një blog, Kubernetes për 10 përdorues). E kundërta: kod aq i nxituar sa bëhet i pandryshueshëm. Synimi: e thjeshta që mund të rritet.

Pipes & filters

Tubat dhe filtrat

Të dhënat kalojnë nëpër një varg hapash të pavarur („filtra“) të lidhur me „tuba“ — si ls | grep | sort në terminal, ose një pipeline ETL. Çdo hap mund të testohet, ripërdoret dhe zëvendësohet veç e veç.

Platforms & internal APIs

Mendimi si platformë

Në kompani të mëdha, disa ekipe ndërtojnë „platforma“ (autentikim, pagesa, publikim) që ekipet e tjera i përdorin si shërbime. „Rruga e shtruar“ (paved road): mënyra e rekomanduar dhe më e lehtë për të bërë gjërat.

Polyglot persistence

Shumë lloje databazash

Sisteme të ndryshme të dhënash për nevoja të ndryshme: PostgreSQL për porositë, Redis për cache, Elasticsearch për kërkim, S3 për skedarë. Fleksibël — por çdo databazë shtesë do mirëmbajtje.

Premature abstraction

Abstraksioni i parakohshëm

Krijimi i ndërfaqeve, fabrikave dhe konfigurimeve „për çdo rast“ para se të ekzistojë nevoja. „Abstraksioni i gabuar kushton më shumë se përsëritja.“ Prit derisa modeli të jetë i qartë (rregulli i tre herëve).

Program to an interface, not an implementation

Programo ndaj ndërfaqes

Shkruaj kodin që varet nga çfarë bën diçka (ndërfaqja: RuajtesiSkedareve), jo nga si e bën (S3Ruajtesi). Kështu mund ta ndërrosh implementimin — për teste ose ndryshime — pa prekur pjesën tjetër.

Prototype pattern

Modeli prototip

Në vend që të krijosh një objekt nga zero, kopjon (klonon) një ekzistues dhe ndryshon vetëm atë që duhet — i dobishëm kur krijimi është i shtrenjtë. JavaScript-i ndërtohet vetë mbi prototipe.

Proxy pattern

Modeli përfaqësues

Një proxy qëndron në vend të një objekti tjetër dhe kontrollon qasjen te ai: e ngarkon vetëm kur duhet (lazy), kontrollon lejet, ruan në cache ose regjistron thirrjet.

Quality attributes (the “-ilities”)

Cilësitë e sistemit

Përveç asaj që bën, një sistem gjykohet nga cilësitë e tij: shkallëzueshmëria, disponueshmëria, performanca, siguria, mirëmbajtja, testueshmëria. Shpesh bien ndesh — arkitektura është zgjedhja e kompromisit të duhur.

Read-heavy vs write-heavy systems

Sistemet me shumë lexime ose shkrime

Shumica e faqeve lexohen shumë më shpesh se shkruhen (100:1) — ndihmojnë cache-i, CDN-ja dhe replikat e leximit. Sistemet me shumë shkrime (log-e, sensorë, klikime) kanë nevojë për radhë, shkrime në grupe dhe databaza si Cassandra.

Replacing conditionals with polymorphism

Zëvendësimi i if-eve me polimorfizëm

Kur i njëjti switch(lloji) përsëritet në shumë vende, çdo lloj i ri kërkon ndryshime kudo. Zëvendësoje me klasa (ose objekte strategjie) ku secila di si të sillet — dhe shtimi i një lloji të ri bëhet në një vend.

Repository pattern

Modeli repository

Repository fsheh mënyrën si ruhen të dhënat pas një ndërfaqeje që duket si një koleksion: nxenesit.gjej(id), nxenesit.ruaj(n). Logjika s'di nëse pas saj është PostgreSQL, MongoDB apo një listë në memorie për teste.

REST vs GraphQL vs gRPC

REST, GraphQL apo gRPC?

REST: i thjeshtë, i kuptueshëm, i përshtatshëm për API publike. GraphQL: klienti kërkon saktësisht fushat që i duhen — i mirë për frontend-e të ndërlikuara. gRPC: shumë i shpejtë dhe me tipe, ideal mes mikroshërbimeve.

Rule of three

Rregulli i tre herëve

Herën e parë shkruaj kodin; herën e dytë, ndoshta kopjoje; herën e tretë, krijo abstraksionin. Abstraksionet e nxituara (pas një rasti të vetëm) janë shpesh të gabuara dhe kushtojnë më shumë se pak përsëritje.

Saga pattern

Modeli saga

Në mikroshërbime s'ka një transaksion të vetëm mbi shumë databaza. Saga e ndan veprimin në hapa (rezervo → paguaj → dërgo), dhe po dështon një hap, ekzekuton „veprime kompensuese“ (anulo rezervimin, kthe paratë).

Scalability patterns overview

Modelet e shkallëzimit

Hapat e zakonshëm kur rritet trafiku: optimizo query-t dhe shto indekse → cache → CDN për skedarë statikë → shumë serverë pas një load balancer-i → replika leximi → radhë për punët e ngadalta → ndarja e databazës (sharding).

Security architecture

Arkitektura e sigurisë

Arkitektura e sigurisë përcakton kufijtë e besimit (çfarë vjen nga jashtë s'besohet kurrë), ku kontrollohen identiteti dhe lejet, si ruhen sekretet dhe të dhënat e ndjeshme, dhe çfarë ndodh kur një pjesë komprometohet.

Serverless architecture

Arkitektura serverless

Një arkitekturë serverless ndërtohet nga funksione të vogla, databaza të menaxhuara, radhë mesazhesh dhe shërbime të gatshme — pa asnjë server për t'u menaxhuar. E lirë për trafik të vogël, por kujdes nga varësia te një ofrues.

Service layer & application services

Shtresa e shërbimeve

Shtresa e shërbimeve koordinon një rast përdorimi të plotë (regjistro nxënësin: valido, ruaj, dërgo email) duke thirrur domenin dhe infrastrukturën. Controller-at mbeten të hollë dhe logjika s'varet nga HTTP.

Service-oriented architecture (SOA)

Arkitektura e orientuar nga shërbimet

SOA ishte paraardhësi i mikroshërbimeve në vitet 2000: sistemi ndahej në shërbime të mëdha që komunikonin shpesh përmes një „Enterprise Service Bus“ qendror. E hasni ende në banka dhe kompani të mëdha.

Sidecar & ambassador patterns

Modeli sidecar

Një „sidecar“ është një proces ndihmës që punon pranë çdo shërbimi (në të njëjtin pod) dhe merret me gjëra të përbashkëta: log-e, enkriptim, ripërpjekje, konfigurim — që kodi i shërbimit të mos i shkruajë vetë.

Single responsibility principle (SRP)

Parimi i përgjegjësisë së vetme

Çdo klasë ose modul duhet të ketë një arsye të vetme për të ndryshuar. Një klasë që lexon nga databaza, llogarit notat dhe dërgon email-e duhet ndarë — përndryshe çdo ndryshim rrezikon të prishë gjithçka.

Software architecture

Arkitektura e software-it

Arkitektura është struktura e madhe e një sistemi: nga cilat pjesë përbëhet, si komunikojnë dhe pse u zgjodh kështu. Janë vendimet që kushtojnë shumë për t'u ndryshuar më vonë — si themelet e një ndërtese.

Specification pattern

Modeli i specifikimit

Rregullat e biznesit („klient VIP“: ka blerë mbi 1 000 € dhe është aktiv) bëhen objekte që kombinohen me and/or/not dhe ripërdoren në filtra, validime dhe query.

State pattern

Modeli i gjendjes

Kur një objekt sillet ndryshe sipas gjendjes (porosia: e re, e paguar, e dërguar), modeli i gjendjes krijon një klasë për çdo gjendje në vend të if-eve të gjata. Objekti i kalon punën gjendjes aktuale.

Strangler fig pattern

Modeli i fikut mbytës

Për të zëvendësuar një sistem të vjetër pa e rishkruar gjithçka njëherësh, ndërto pjesët e reja rreth tij dhe ridrejto gradualisht trafikun drejt tyre — derisa i vjetri s'ka më punë dhe hiqet. Emri vjen nga një bimë që rritet rreth pemës.

Strong vs eventual consistency in design

Konsistenca e fortë dhe përfundimtare në projektim

Disa të dhëna duhet të jenë gjithmonë të sakta menjëherë (bilanci i bankës — konsistencë e fortë); të tjerat mund të vonohen pak (numri i pëlqimeve — konsistencë përfundimtare). Zgjidh për çdo rast — konsistenca e fortë kushton shpejtësi.

Sync vs async communication

Komunikimi sinkron dhe asinkron

Sinkron (REST, gRPC): shërbimi thërret dhe pret përgjigjen — i thjeshtë, por po bie tjetri, bie edhe ky. Asinkron (radhë, ngjarje): dërgon mesazhin dhe vazhdon — më i qëndrueshëm, por më i vështirë për t'u ndjekur.

System design

Projektimi i sistemeve

Projektimi i sistemeve është vendosja e pjesëve të mëdha të një aplikacioni që duhet të shërbejë shumë përdorues: klientët, load balancer-at, serverët, databazat, cache-i, radhët dhe CDN-ja — dhe si rriten kur rritet trafiku.

Team topologies

Topologjitë e ekipeve

Libri „Team Topologies“ propozon katër lloje ekipesh: ekipet e rrjedhës (ndërtojnë produkte), ekipet e platformës (u japin vegla të tjerëve), ekipet ndihmëse dhe ato të nënsistemeve të vështira — që secili të ketë ngarkesë të menaxhueshme.

Technical vision & roadmaps

Vizioni teknik dhe plani

Një vizion teknik përshkruan ku duhet të jetë sistemi pas 1–2 vitesh dhe pse; roadmap-i i ndan në hapa realistë. Ndihmon ekipet të marrin vendime të vogla në të njëjtin drejtim.

Tell, don't ask

Thuaj, mos pyet

Në vend që të pyesësh një objekt për të dhënat e tij dhe të vendosësh jashtë („nëse llogaria.bilanci > 100, zbrit“), thuaji objektit çfarë të bëjë (llogaria.terhiq(100)) dhe le të vendosë vetë. Logjika mbetet pranë të dhënave.

Template method pattern

Modeli i metodës shabllon

Klasa prind përcakton hapat e një algoritmi (lexo → përpuno → ruaj) dhe klasat bija plotësojnë vetëm disa hapa. Shumë framework-e punojnë kështu: ti shkruan vetëm pjesët që ndryshojnë.

Testing hexagonal architectures

Testimi i arkitekturave heksagonale

Një avantazh i madh i porteve dhe adapterëve: logjikën e testoni me adapterë në memorie (RuajtesiNeMemorie në vend të PostgreSQL), shumë shpejt; ndërsa adapterët e vërtetë testohen veç e veç me teste integrimi.

The software architect role

Roli i arkitektit të software-it

Arkitekti vendos strukturën e sistemeve, zgjedh teknologjitë, shkruan dokumente projektimi dhe ndihmon ekipet të marrin vendime të mira. Arkitektët e mirë ende shkruajnë kod dhe dëgjojnë më shumë se urdhërojnë.

Transactional outbox

Modeli outbox

Problemi: ruan porosinë në databazë dhe dërgon një mesazh në Kafka — po bie njëra, mbeten të pasinkronizuara. Zgjidhja: ruaj edhe mesazhin në një tabelë „outbox“ në të njëjtin transaksion, dhe një proces tjetër e dërgon më pas.

Ubiquitous language

Gjuha e përbashkët

Zhvilluesit dhe ekspertët e biznesit përdorin të njëjtat fjalë me të njëjtin kuptim — në biseda, dokumente dhe kod. Po biznesi thotë „regjistrim“, klasa s'quhet „UserSignupEntity“.

UML diagrams

Diagramet UML

UML është gjuha standarde e diagrameve të software-it: diagrami i klasave (klasat dhe lidhjet), i sekuencës (kush i thërret kë dhe me çfarë radhe), i rasteve të përdorimit. Në praktikë përdoren kryesisht klasat dhe sekuenca.

Unit of work

Njësia e punës

Unit of Work mban mend të gjitha ndryshimet gjatë një veprimi dhe i ruan në databazë njëherësh, në një transaksion — ose asnjë. DbContext i Entity Framework-ut dhe Session i SQLAlchemy janë të tilla.

Vertical slice architecture

Arkitektura me feta vertikale

Në vend që kodi të ndahet sipas llojit (controllers/, services/, repositories/), ndahet sipas veçorisë (porosite/, pagesat/), ku secila përmban gjithçka që i duhet. Ndryshimet mbeten në një dosje.

Visitor pattern

Modeli vizitor

Vizitori të lejon të shtosh veprime të reja mbi një strukturë objektesh (p.sh. pema e kodit në një kompajler) pa ndryshuar klasat e tyre — çdo veprim i ri është një „vizitor“ që kalon nëpër të gjitha.

Why singletons are controversial

Pse singleton-at janë të diskutueshëm

Singleton-i garanton një instancë të vetme, por në praktikë shpesh bëhet „variabël globale e maskuar“: e vështirë për t'u testuar dhe fsheh varësitë. Më mirë: krijo një instancë dhe jepja me dependency injection atyre që i duhet.