Habr po ndryshon botën. Më shumë se një vit ne kemi mbajtur blogun tonë. Gati gjashtë muaj më parë morëm një feedback të arsyeshëm nga habrovianët: «Dodo, ju gjithmonë flisni për sistemin tuaj. Çfarë është ky sistem? Dhe përse është i nevojshëm për një rrjet pica?»
Ne kemi kaluar kohë duke menduar dhe kuptuar se keni të drejtë. Ne provojmë të shpjegojmë gjithçka në mënyrë të thjeshtë, por del në mënyra të çrregullta dhe nuk ka një përshkrim të plotë të sistemit. Kështu filloi një rrugëtim i gjatë mbledhjeje informacioni, kërkimi autorësh dhe shkruajti një seri artikelesh mbi Dodo IS. Le të fillojmë!
Falënderime: faleminderit që ndani feedback-un tuaj me ne. Falë kësaj ne përfunduam përshkrimin e sistemit, përgatitëm radarin teknik dhe së shpejti do të publikojmë një përshkrim të plotë të proceseve tona. Pa ju, akoma do të ishim këtu për pesë vite të tjera.

Seria e artikujve «Çfarë është Dodo IS?» do të flasë për:
- Monoliti fillestar në Dodo IS (2011-2015). (Në proces…)
- Rruga e back-office: baza të ndara dhe një bus. (Ju jeni këtu)
- Rruga e pjesës klient: fasada mbi bazën (2016-2017). (Në proces…)
- Historia e mikrosherbimeve reale. (2018-2019). (Në proces…)
- Përfundimi i ndarjes së monolitit dhe stabilizimi i arkitekturës. (Në proces…)
Nëse dëshironi të dini diçka tjetër, shkruani në komente.
Mendim mbi përshkrimin kronologjik nga autori
Rregullisht mbaj një takim për punonjësit e rinj mbi temën «Arkitektura e sistemit». Ne e quajmë atë «Intro to Dodo IS Architecture» dhe është pjesë e procesit të onboardimit për zhvilluesit e rinj. Duke folur në një formë të ndryshme për arkitekturën tonë, për veçoritë e saj, më erdhi një qasje historike në përshkrimin.
Tradicionalisht e shohim sistemin si një grup përbërësish (teknikë ose më të nivelit të lartë), modul biznesi që ndërveprojnë me njëri-tjetrin për të arritur një qëllim. Dhe nëse për projektimin një këndvështrim i tillë është i arsyeshëm, për përshkrimin dhe kuptimin nuk është plotësisht i përshtatshëm. Ka disa arsye për këtë:
- Realisht, situata ndryshon nga ajo që është në letër. Jo gjithçka që ishte e menduar realizohet. Ne jemi të interesuar të dimë se si në të vërtetë ka ndodhur dhe funksionon gjithçka.
- Shpjegimi i informacionit në një rend kronologjik. Në thelb, mund të kalojmë nëpërmjet një rrugë kronologjike nga fillimi deri në gjendjen aktuale.
- Nga e thjeshta në të komplikuar. Nuk është universale, por në rastin tonë ndodhi kështu. Nga qasjet më të thjeshta, arkitektura kaloi në më të komplikuara. Shpesh përmes komplikimit u zgjidhën problemet e shpejtësisë së realizimit dhe stabilitetit, si dhe dhjetëra karakteristika të tjera nga lista e kërkesave jo funksionale ( mirë është folur për përballimin e kompleksitetit me kërkesat e tjera).
Në vitin 2011, arkitektura Dodo IS dukej kështu:

Në vitin 2020, ajo u komplikuar pak dhe dukej kështu:

Si ndodhi kjo evolucion? Pse janë të nevojshme pjesët e ndryshme të sistemit? Cilët janë zgjidhjet arkitektonike dhe përse u bënë? Do t'i shqyrtojmë në këtë seri artikujsh.
Problemet e para të vitit 2016: përse shërbimet duhet të dalin nga monoliti
Artikujt e parë të ciklit do të flasin për shërbimet që u ndanë fillimisht nga monoliti. Për t'ju futur në kontekst, do të tregoj se cilat janë problemet që kishim në sistem në fillim të vitit 2016, se çfarë na duhej të merreshim me ndarjen e shërbimeve.
Një bazë e vetme MySql, në të cilën të gjitha aplikacionet që ekzistonin në atë kohë në Dodo IS shkruanin regjistrimet e tyre. Pasojat ishin këto:
- Ngarkesë e madhe (këtu 85% e kërkesave ishin për lexim).
- Baza u rrit. Për shkak të kësaj, kostoja e saj dhe mirëmbajtja po bëheshin një problem.
- Një pikë e vetme dështimi. Nëse një aplikacion, që shkruante në bazë, papritur fillonte ta bënte këtë më shpesh, aplikacionet e tjera e ndienin këtë.
- Efiçiencë e dobët në ruajtje dhe kërkesa. Shpesh të dhënat ruhet në një strukturë që ishte e përshtatshme për disa skenarë, por e papërshtatshme për të tjerët. Indekset shpejtonin disa operacione, por mund të ngadalësonin të tjera.
- Disa nga problemet u lehtësuan nga keshët dhe read-replikat që u bënë me ngut për bazat (kjo do të jetë një artikull i veçantë), por ato vetëm fituan kohë dhe nuk e zgjidhen problemin në thelb.
Problemi ishte prania e vetë monoliti. Pasojat ishin këto:
- Çlirimet e përbashkëta dhe të rralla.
- Vështirësi në zhvillimin e përbashkët për një numër të madh njerëzish.
- Pamundësia për të sjellë teknologji të reja, framework-e dhe biblioteka.
Problemet me bazën dhe monolitin janë përshkruar shumë herë, për shembull, në kontekstin e rënieve në fillim të vitit 2018 (, dhe ), kështu që nuk do të ndalem shumë. Thjesht do të them se dëshironim të ofronim më shumë fleksibilitet në zhvillimin e shërbimeve. Kjo në radhë të parë i përkiste atyre që ishin më të ngarkuar dhe rrënjësorë në të gjithë sistemin — Auth dhe Tracker.
Rruga e backoffice: baza të ndara dhe shina
Navigimi në kapitull
Skema e monolitit të vitit 2016
Para jush janë blloqet kryesore të monolitit Dodo IS të vitit 2016, dhe pak më poshtë është shpjegimi i detyrave të tyre kryesore.

Kasa e Dërgesës. Regjistrimi i kurierëve, dhënia e porosive kurierëve.
Qendra e Kontaktit. Pranimi i porosive përmes operatorit.
Site. Website-t tona (dodopizza.ru, dodopizza.co.uk, dodopizza.by etj.).
Auth. Shërbimi i autorizimit dhe autentikimit për backoffice.
Tracker. Tracker i porosive në kuzhinë. Shërbimi i shënimit të statusit të gatishmërisë gjatë përgatitjes së porosisë.
Kasa e Restorantit. Pranimi i porosive në restorant, ndërfaqet e kasieres.
Eksport. Eksportimi i raporteve në 1C për kontabilitetin.
Njoftimet dhe dokumentet. Komandat me zë në kuzhinë (p.sh., "Arriti një pizzë e re") + printimi i dokumenteve për kurierët.
Menaxheri i Ndrrimit. Ndërfaqet për punën e menaxherit të ndrrimit: lista e porosive, grafikët e performancës, shfaqja e punonjësve në ndrrim.
Menaxheri i Zyrës. Ndërfaqet për punën e franchizës dhe menaxherit: pranimi i punonjësve, raportet mbi punën e picerive.
Tabela e Restorantit. Shfaqja e menusë në televizorët në pizzeri.
Adminka. Cilësimet në pizzerinë e caktuar: menu, çmimet, regjistrimi, kodet promovuese, oferta, banners për website etj.
Këndi Personal i Punonjësit. Grafikët e punës së punonjësve, informacion për punonjësit.
Tabela e Motivimit në Kuzhinë. Një ekran i veçantë që ndodhet në kuzhinë dhe tregon shpejtësinë e punës së pizzamaker-ëve.
Komunikimi. Dërgimi i sms dhe email.
FileStorage. Shërbimi ynë për pranimin dhe dorëzimin e skedarëve statikë.
Përpjekjet e para për të zgjidhur problemet na ndihmuan, por ishin vetëm një pushim përkohësor. Nuk ishin zgjidhje sistemike, prandaj ishte e qartë se duhej të bëhej diçka me bazat. Për shembull, ndarja e bazës së përgjithshme në disa më të specializuara.
Duke filluar të shkarkojmë monolitin: ndarja e Auth dhe Tracker
Shërbimet kryesore që atëherë regjistronin dhe lexonin më shumë nga baza ishin:
- Auth. Shërbimi i autorizimit dhe autentikimit për backoffice.
- Tracker. Tracker i porosive në kuzhinë. Shërbimi i shënimit të statusit të gatishmërisë gjatë përgatitjes së porosisë.
Çfarë bën Auth
Auth është shërbimi përmes të cilit përdoruesit identifikohen në backoffice (në anën e klientit ka një hyrje të pavarur). Gjithashtu, bëhet kërkesa për të vërtetuar se ka të drejtat e nevojshme për qasje dhe se këto të drejta nuk janë ndryshuar që nga hera e fundit e hyrjes. Përdoret gjithashtu për hyrjen e pajisjeve në pizzeri.
Për shembull, nëse dëshirojmë të hapim në televizorin që v hanging në sallë, një tabelë me statuset e porosive të gatshme. Atëherë hapim auth.dodopizza.ru, zgjedhim "Hyrje si pajisje", shfaqet një kod, i cili mund të vendoset në një faqe speciale në kompjuterin e menaxherit të ndrrimit, duke specifikuar tipin e pajisjes. Televizori do të kalojë vetë në ndërfaqen e nevojshme të pizzerisë së tij dhe do të fillojë të shfaqë emrat e klientëve të cilëve porositë janë gati.

Nga vijnë ngarkesat?
Çdo përdorues i regjistruar në backoffice për çdo kërkesë kontrollet nga baza, në tabelën e përdoruesve, duke përdorur një запрос sql për të marrë përdoruesin dhe kontrolluar nëse ka të drejtat e nevojshme dhe të drejtat për këtë faqe.
Çdo pajisje bën të njëjtën gjë, vetëm me tabelën e pajisjeve duke kontrolluar rolin dhe të drejtat e saj. Një numër i madh kërkesash në bazën master çon në ngarkesa dhe shpenzime burimesh të bazës së përgjithshme për këto operacione.
Duke shkarkuar Auth
Auth ka një domain të izoluar, që do të thotë se të dhënat mbi përdoruesit, hyrjet ose pajisjet shkojnë në shërbimin (deri tani të ardhshëm) dhe atje mbeten. Nëse ndokush ka nevojë për to, ai do të shkonte në këtë shërbim për të marrë të dhënat.
I SHKONI. Schema e punës fillimisht ishte kështu:

Dëshiroj të shpjegoj pak sesi funksiononte:
- Kërkesa nga jashtë vjen në backend (aty është Asp.Net MVC), sjell me vete një cookie seance, e cila përdoret për të marrë të dhënat e seancës nga Redis(1). Ajo ose ka informacion për qasjet, dhe atëherë qasja në kontrollues është e hapur (3,4), ose jo.
- Nëse nuk ka qasje, duhet të kaloni procedurën e autorizimit. Këtu për thjeshtësim ajo tregohet si pjesë e rrugës në atë atribut, megjithatë, është një kalim në faqen e hyrjes. Në rastin e një skenari pozitiv, ne do të marrim një seancë të mbushur siç duhet dhe do të kalojmë në Kontrollerin e Backoffice.
- Nëse të dhënat janë aty, duhet të kontrollohet nëse janë të sakta në bazën e përdoruesit. A e ka ndryshuar roli i tij, a duhet ta ndalojmë tani të hyjë në këtë faqe. Në këtë rast, pas marrjes së seancës (1), duhet të shkojmë direkt në bazë dhe të kontrollojmë të drejtat e përdoruesit përmes shtresës së logjikës së autentifikimit (2). Më pas ose në faqen e hyrjes ose kalimi në kontrollues. Një sistem i tillë i thjeshtë, por megjithatë jo shumë standart.
- Nëse të gjitha procedurat janë përfunduar, atëherë kalojmë më tutje në logjikën në kontrollet dhe metoda.
Të dhënat e përdoruesve janë të ndara nga të gjitha të dhënat e tjera, ato ruhen në një tabelë të veçantë të anëtarësisë, funksionet nga shtresa e logjikës AuthService mjaft mirë mund të bëhen metoda API. Kufijtë e domainit janë të përcaktuar qartë: përdoruesit, rolet e tyre, të dhënat për qasjen, dhënia dhe tërheqja e qasjes. Të gjitha duken se mund të nxirren në një shërbim të veçantë.
KISHA. Kështu edhe bëmë:

Ky qasje ka një sërë problemesh. Për shembull, thirrja e metodës brenda një procesi nuk është e njëjtë me thirrjen për një shërbim të jashtëm përmes http. Latenza, besueshmëria, mirëmbajtja, transparenca e operacionit janë krejtësisht të tjera. Më shumë rreth këtyre problemeve ka folur Andrey Morevsky në referatin e tij .
Shërbimi i autentifikimit dhe shërbimi i pajisjeve përdoren për backoffice, pra për shërbimet dhe ndërfaqet që përdoren në prodhim. Autentifikimi për shërbimet e klientëve (si websiti apo aplikacioni mobil) ndodh veçmas pa përdorur Auth. Ndara zgjati rreth një vit, dhe tani përsëri po merremi me këtë temë, duke e kaluar sistemin tashmë në shërbime të reja autentifikimi (me protokollet standarde).
Pse ndarja zgjati kaq gjatë?
Në rrugë kishte shumë probleme që ngadalësuan:
- Dëshironim të transferonim të dhënat për përdoruesit, pajisjet dhe autentifikimin nga bazat e të dhënave në vend në një të vetme. Për këtë duhej të transferonim të gjitha tabelat dhe përdorimin nga identifikatori int në identifikatorin global UUId (këtë kod e riprhojti së fundmi) dhe projekti open-source ). Ruajtja e të dhënave për përdoruesit (sepse është informacion personal) ka kufizime dhe për disa vende duhet t'i ruhet veçmas. Por identifikatori global i përdoruesit duhet të ekzistojë.
- Shumë tabela në bazë kanë informacionin mbi auditimin e atij përdoruesi që ka kryer operacionin. Kjo kërkonte një mekanizëm shtesë për të siguruar konsistencën.
- Pas krijimit të shërbimeve API kishte një periudhë të gjatë dhe graduale kalimi në një sistem tjetër. Kalimet duhej të ndodhnin pa probleme për përdoruesit dhe kërkonin punë manuale.
Schema e regjistrimit të pajisjeve në picerinë:

Arkitektura e përgjithshme pas ndarjes së Auth dhe shërbimit të Pajisjeve:

Shënim. Në vitin 2020 ne po punojmë mbi një version të ri të Auth, i cili është i bazuar në standardin e autorizimit OAuth 2.0. Ky standard është mjaft kompleks, por do të jetë i dobishëm për zhvillimin e një shërbimi të vazhdueshëm të autentifikimit. Në artikullin «», Alexey Chernyaev ka përshkruar standardin sa më thjesht dhe qartë që të kurseni kohë në studimin e tij.
Çfarë bën Tracker
Tani për shërbimin e dytë të ngarkuar. Tracker-i luan një rol të dyfishtë:
- Nga njëra anë, detyra e tij është të tregojë punonjësve në kuzhinë se cilat porosi janë aktualisht në punë, cilat produkte duhet të gatuhen tani.
- Nga ana tjetër — të dixhitalizojë të gjitha proceset në kuzhinë.

Kur një produkt i ri shfaqet në porosi (për shembull, pica), ai shkon në stacionin e tracker-it «Rashtimi». Në këtë stacion qëndron pica-maker që merr testin e duhur dhe e rashton atë, pas së cilës shënon në tabletën e tracker-it se ka kryer detyrën e tij dhe i kalon bazën e rashtuar në stacionin tjetër — «Fillimi».
Aty pica-maker-i tjetër e mbush picën, më pas shënon në tabletë se ka kryer detyrën e tij dhe e vendos picën në furrë (kjo gjithashtu është një stacion tjetër që duhet shënuar në tabletë). Ky sistem ka qenë që në fillim në Dodo dhe që në fillimin e ekzistencës së Dodo IS. Ajo lejon të monitorohet dhe dixhitalizohet të gjitha operacionet. Për më tepër, tracker-i sugjeron se si të gatuhen produktet të ndryshme, udhëzon çdo lloj produkti përmes skemave të tij të prodhimit, ruan kohën optimale të gatimit dhe ndjek të gjitha operacionet mbi produktin.
Kështu duket ekrani i tabletës në stacionin e tracker-it «Rashtimi»
Nga vijnë ngarkesat?
Në çdo piceri ka rreth pesë tabletë me tracker. Në vitin 2016, kishim më shumë se 100 piceritë (dhe tani më shumë se 600). Çdo tablet bën një kërkesë çdo 10 sekonda në backend dhe nxjerr të dhëna nga tabela e porosive (lidhet me klientin dhe adresën), përbërja e porosisë (lidhet me produktin dhe tregon sasinë), tabela e regjistrimit të motivacionit (ato regjistrojnë kohën e klikimeve). Kur kuzhinieri i picës klikon në produktin në tracker, ndodh përditësimi i regjistrimeve në të gjitha këto tabela. Tabela e porosive është e përbashkët, po aty ndodhin edhe fushtimat në momentin e pranimit të porosisë, përditësimet nga pjesë të tjera të sistemit dhe shumë lexime, për shembull, në televizorin që është pezull në piceri dhe tregon porositë e gatshme për klientët.
Në periudhën e luftës me ngarkesat, kur çdo gjë dhe çdo person ishte ndihmuar dhe ishte transferuar në një replikë asinkrone të bazës, këto operacione me tracker vazhdonin të shkonin në bazën kryesore. Nuk duhet të ketë asnjë vonesë këtu, të dhënat duhet të jenë aktuale, pasaktësia është e papranueshme.
Gjithashtu, mungesa e tabelave dhe indekseve të veta nuk lejonte të shkruheshin kërkesa më specifike, të përshtatura për përdorimin e tyre. Për shembull, trackerit mund t’i nevojitet që të ketë një indeks për picerinë në tabelën e porosive. Ne gjithmonë nxjerrim në bazën e trackerit porositë sipas picerisë. Në këtë rast, për pranimin e porosisë nuk ka rëndësi në cilën piceri bie, më e rëndësishme është cili klient e bëri këtë porosi. Prandaj, atje nevojitet një indeks për klientin. Në përveçim, për trackerin në tabelën e porosive nuk është e nevojshme të ruhet ID e kontrollit të printuar ose promocionet e lidhura me porosinë. Kjo informacion nuk e intereson shërbimin tonë të trackerit. Në bazën e përgjithshme monolitike, tabelat mund të ishin vetëm një variant kompromisi midis të gjithë përdoruesve. Kjo ishte një nga problemet fillestare.
I SHKONI. Fillimisht, arkitektura ishte e tillë:

Edhe pas ndarjes në procese të veçanta, pjesa më e madhe e kodit mbeti e përbashkët për shërbime të ndryshme. Çdo gjë, pos controllers, ishte e njëjtë dhe jetonte në një depo. U përdorën metoda të përbashkëta të shërbimeve, repository-ëve, një bazë e përbashkët, ku ndodheshin tabelat e përbashkëta.
Duke shkarkuar Tracker
Problemi kryesor me tracker-in është se të dhënat duhet të sinkronizohen midis bazave të ndryshme. Ky është gjithashtu dallimi i tij kryesor nga ndarja e shërbimit Auth, porosinë dhe statusin e saj mund të ndryshojnë dhe duhet të shfaqen në shërbime të ndryshme.
Ne pranojmë porosi në Kassen e Restauranti (ky është një shërbim), ajo ruhet në bazën e të dhënave me statusin "Pranuar". Pas kësaj, ajo duhet të kalojë në tracker, ku statusi i saj do të ndryshojë disa herë: nga "Kuzhina" në "I Paketuar". Në të njëjtën kohë, me porosinë mund të ndodhin disa ndikime të jashtme nga Kassa ose ndërfaqja e Menaxherit të Ndërrimit. Më poshtë është një tabelë me statuset e porosisë dhe përshkrimet e tyre:

Skema e ndryshimit të statuset të porosisë duket kështu:

Statuset ndryshojnë mes sistemeve të ndryshme. Dhe këtu tracker-i nuk është sistemi përfundimtar ku mbyllet informacioni. Ne kemi parë disa qasje të mundshme për ndarje në këtë rast:
- Konsolidojmë të gjitha veprimet e porosisë në një shërbim. Në rastin tonë, ky opsion kërkon shumë shërbim për përpunimin e porosisë. Nëse do të ndaleshim këtu, do të krijonim një monolit të dytë. Problemet nuk do të zgjidhen.
- Një sistem bën thirrje në një tjetër. Opsioni i dytë është më interesant. Por me këtë janë të mundshme zinxhirë thirrjesh (), lidhshmëria e komponentëve është më e lartë, dhe menaxhimi i saj është më i komplikuar.
- Organizojmë ngjarjet, dhe çdo shërbim komunikon me tjetrin përmes këtyre ngjarjeve. Si rezultat, u zgjodh opsioni i tretë, sipas të cilit të gjithë shërbimet fillojnë të shkëmbejnë ngjarje me njëra-tjetrën.
Fakti që zgjodhëm opsionin e tretë do të thotë se për tracker-in do të jetë baza e saj, dhe për çdo ndryshim në porosi do të dërgojë një ngjarje për këtë, në të cilën regjistrohen shërbime të tjera dhe që gjithashtu shkon në bazën kryesore. Për këtë na nevojitej një shërbim që do të siguronte dërgimin e mesazheve midis shërbimeve.
Në atë kohë, në stekun tonë tashmë kishim RabbitMQ, nga i cili erdhi zgjidhja përfundimtare për ta përdorur si broker të mesazheve. Në skemë tregohet kalimi i porosisë nga Kassa e Restauranti përmes Tracker-it, ku ajo ndryshon statuset e saj dhe shfaqet në ndërfaqen e Porosive të menaxherit. U BË:

Rruga e porosisë përmes hapave
Rruga e porosisë fillon në një nga shërbimet burim të porosisë. Këtu është Kassa e Restauranti:
- Në Kasa, porosia është plotësisht gati dhe është koha ta dërgojmë në tracker. Aktivizohet ngjarja për të cilën është regjistruar tracker-i.
- Tracker-i, duke pranuar porosinë, e ruan atë në bazën e tij të dhënave, duke krijuar kështu ngjarjen "PorosiaEPranuarNgaTracker-i" dhe e dërgon atë në RMQ.
- Në shiritin e ngjarjeve të porosisë tashmë janë regjistruar disa procesorë. E rëndësishme për ne është ai që bën sinkronizimin me bazën monolitike.
- Procesori merr ngjarjen, zgjidh të dhënat e rëndësishme për të: në rastin tonë, ky është statusi i porosisë "Pranuar nga Tracker" dhe azhurnon entitetin e porosisë në bazën kryesore.
Nëse dikush ka nevojë për porosinë saktësisht nga tabela monolitike orders, atëherë mund të merret edhe nga aty. Për shembull, kjo është e nevojshme për ndërfaqen e Porosive në Menaxherin e Ndërrimit:

Të gjitha shërbimet e tjera gjithashtu mund të regjistrohen për ngjarjet e porosisë nga tracker-i për t’i përdorur ato për vete.
Nëse pas një kohe të caktuar porosia merret në punë, statusi i saj fillimisht ndryshohet në bazën e saj (bazën e Tracker-it), dhe më pas menjëherë gjenerohet ngjarja "Porosia në Punë". Kjo gjithashtu kalon në RMQ, ku sinkronizohet në bazën monolitike dhe dërgohet në shërbimet e tjera. Në këtë proces mund të ketë probleme të ndryshme, më shumë detaje mund të shikoni në raportin e Zhenya Peshkov .
Arkitektura përfundimtare pas ndryshimeve në Auth dhe Tracker

Duke përmbledhur përfundimisht: fillimisht kisha mendimin ta paketoj historinë nëntëvjeçare të sistemit Dodo IS në një artikull. Dëshiroja të flisja shpejt dhe thjesht për etapat e evolucionit. Megjithatë, duke u ulur për materialin, kuptova se gjithçka është shumë më e komplikuar dhe më interesante se sa duket.
Duke reflektuar mbi dobinë (ose mungesën e saj) nga një material i tillë, arrita në përfundimin se zhvillimi i vazhdueshëm është i pamundur pa kronika të plota ngjarjesh, retrospektivë të zhvilluara dhe analiza të vendimeve tona të kaluara.
Shpresoj se ju ka qenë e dobishme dhe interesante të mësoni për rrugën tonë. Tani jam përballë zgjedhjes, se cila pjesë e sistemit Dodo IS të përshkruaj në artikullin e ardhshëm: shkruani në komentet ose voto.
Vetëm përdoruesit e regjistruar mund të marrin pjesë në anketë. , ju lutemi.
Për cilën pjesë të Dodo IS do të donit të dinit në artikullin e ardhshëm?
24,1%Monoliti i hershëm në Dodo IS (2011-2015)
24,1%Problemet e para dhe zgjidhjet e tyre (2015-2016)
20,7%Rruga e pjesës klient: fasada mbi bazën (2016-2017)
36,2%Historia e mikrosherbimeve të vërteta (2018-2019)
44,8%Përfundimi i prerjes së monolitit dhe stabilizimi i arkitekturës
29,3%Për planet e mëtejshme të zhvillimit të sistemit
19,0%Nuk dua të di asgjë për Dodo IS
58 përdorues votuan. 6 përdorues abstenuan.
Burimi: habr.com
