{"id":36721,"date":"2019-10-31T22:13:20","date_gmt":"2019-10-31T19:13:20","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-dark-razvertyvaet-kod-za-50-ms\/"},"modified":"2019-10-31T22:13:20","modified_gmt":"2019-10-31T19:13:20","slug":"kak-dark-razvertyvaet-kod-za-50-ms","status":"publish","type":"post","link":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","title":{"rendered":"Hvordan Dark implementerer kode p\u00e5 50 ms","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Hvordan Dark implementerer kode p\u00e5 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/c159a36eb52bf488f3a70ea511690366.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jo hurtigere udviklingsprocessen er, desto hurtigere vokser teknologivirksomheden.<\/p>\n<p><\/p>\n<p>Desv\u00e6rre arbejder moderne applikationer imod os - vores systemer skal opdateres i realtid uden at genere nogen og uden at f\u00f8re til nedetid og afbrydelser. Udrulning i s\u00e5danne systemer bliver en kompleks opgave og kr\u00e6ver komplekse pipelines til kontinuerlig levering, selv i sm\u00e5 teams.<\/p>\n<p><\/p>\n<p>Disse pipelines har ofte en sn\u00e6ver anvendelse, arbejder langsomt og er ikke s\u00e6rlig p\u00e5lidelige. Udviklere skal f\u00f8rst oprette dem manuelt og derefter administrere dem, og virksomheder ans\u00e6tter ofte hele DevOps-teams til dette.<\/p>\n<p><\/p>\n<p>Hastigheden af disse pipelines bestemmer hastigheden af udviklingen. For de bedste teams tager udrulning 5-10 minutter, men normalt tager det meget l\u00e6ngere, og \u00e9n udrulning kr\u00e6ver flere timer.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>I Dark tager det 50 ms. <em>Fifty. Milliseconds<\/em>. Dark - <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">det er en omfattende l\u00f8sning med et programmeringssprog, en editor og infrastruktur<\/a><\/noindex>, der er skabt specifikt til kontinuerlig levering, og alle aspekter af Dark, herunder selve sproget, er bygget med henblik p\u00e5 sikker \u00f8jeblikkelig udrulning.<\/p>\n<p><\/p>\n<h3 id=\"pochemu-konveyery-nepreryvnoy-postavki-takie-medlennye\">Hvorfor er pipelines til kontinuerlig levering s\u00e5 langsomme?<\/h3>\n<p><\/p>\n<p>Lad os sige, vi har en Python-webapplikation, og vi allerede har oprettet en fantastisk og moderne pipeline til kontinuerlig levering. For udvikleren, der dagligt arbejder p\u00e5 dette projekt, vil udrulning af en lille \u00e6ndring se nogenlunde s\u00e5ledes ud:<\/p>\n<p><\/p>\n<h3 id=\"vnesenie-izmeneniy\">Foretagelse af \u00e6ndringer<\/h3>\n<p><\/p>\n<ul>\n<li>Oprettelse af en ny gren i git<\/li>\n<li>Foretagelse af \u00e6ndringer bag en funktionsskifter<\/li>\n<li>Modultest for at kontrollere \u00e6ndringer med og uden funktionsskifter<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pul-rekvest\">Pull-request<\/h3>\n<p><\/p>\n<ul>\n<li>Commit af \u00e6ndringer<\/li>\n<li>Send \u00e6ndringer til den fjerne repository p\u00e5 github<\/li>\n<li>Pull-request<\/li>\n<li>CI-bygningen udf\u00f8res automatisk i baggrunden<\/li>\n<li>Kodegennemgang<\/li>\n<li>Yderligere nogle gennemgange, hvis n\u00f8dvendigt<\/li>\n<li>Sammenflet \u00e6ndringerne med master-grenen i git.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"ci-vypolnyaetsya-na-mastere\">CI udf\u00f8res p\u00e5 masteren<\/h3>\n<p><\/p>\n<ul>\n<li>Installation af frontend-afh\u00e6ngigheder via npm<\/li>\n<li>Bygning og optimering af HTML+CSS+JS-ressourcer<\/li>\n<li>K\u00f8rsel af modul\u00e6re og funktionelle tests i frontenden<\/li>\n<li>Installation af Python-afh\u00e6ngigheder fra PyPI<\/li>\n<li>K\u00f8rsel af modul\u00e6re og funktionelle tests i backend<\/li>\n<li>Integrationstest i begge ender<\/li>\n<li>Send frontend-ressourcer til CDN<\/li>\n<li>Bygning af containeren til Python-programmet<\/li>\n<li>Afsendelse af container til registrering<\/li>\n<li>Opdatering af Kubernetes-manifest<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"zamena-starogo-koda-novym\">Udskiftning af gammel kode med ny<\/h3>\n<p><\/p>\n<ul>\n<li>Kubernetes k\u00f8rer flere instanser af den nye container<\/li>\n<li>Kubernetes venter p\u00e5, at instanserne bliver operationelle<\/li>\n<li>Kubernetes tilf\u00f8jer instanser til HTTP-loadbalanceret<\/li>\n<li>Kubernetes venter p\u00e5, at de gamle instanser ikke l\u00e6ngere bliver brugt<\/li>\n<li>Kubernetes stopper de gamle instanser<\/li>\n<li>Kubernetes gentager disse operationer, indtil alle gamle instanser er blevet udskiftet<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"vklyuchenie-novogo-pereklyuchatelya-funkcii\">Aktivering af den nye funktionsskifter<\/h3>\n<p><\/p>\n<ul>\n<li>Den nye kode aktiveres kun for sig selv for at sikre, at alt fungerer korrekt<\/li>\n<li>Den nye kode aktiveres for 10% af brugerne; drifts- og forretningsmetrikker overv\u00e5ges<\/li>\n<li>Den nye kode aktiveres for 50% af brugerne; drifts- og forretningsmetrikker overv\u00e5ges<\/li>\n<li>Den nye kode aktiveres for 100% af brugerne; drifts- og forretningsmetrikker overv\u00e5ges<\/li>\n<li>Til sidst gentager du hele proceduren for at fjerne den gamle kode og skifteren<\/li>\n<\/ul>\n<p><\/p>\n<p>Processen afh\u00e6nger af v\u00e6rkt\u00f8jer, sprog og brug af serviceorienterede arkitekturer, men generelt ser det s\u00e5dan ud. Jeg n\u00e6vnte ikke implementeringer med database-migrering, fordi det kr\u00e6ver omhyggelig planl\u00e6gning, men nedenfor vil jeg beskrive, hvordan Dark h\u00e5ndterer dette.<\/p>\n<p><\/p>\n<p>Der er mange komponenter, og mange af dem kan let bremse, fejle, skabe midlertidig konkurrence eller kn\u00e6kke det arbejdende system.<\/p>\n<p><\/p>\n<p>Og da disse pipelines n\u00e6sten altid er skr\u00e6ddersyede, er de sv\u00e6re at stole p\u00e5. Mange oplever dage, hvor koden ikke kan implementeres, fordi der er problemer i Dockerfilen, en af de mange tjenester fejler, eller den n\u00f8dvendige specialist er p\u00e5 ferie.<\/p>\n<p><\/p>\n<p>V\u00e6rre endnu, mange af disse trin g\u00f8r slet ikke noget nyttigt. De var n\u00f8dvendige tidligere, da vi implementerede kode direkte til brugerne, men nu har vi skiftere til den nye kode, og disse processer er blevet opdelt. Resultatet er, at det trin, hvor koden implementeres (den gamle udskiftes med den nye), nu blot er en un\u00f8dig risiko.<\/p>\n<p><\/p>\n<p>Selvf\u00f8lgelig er dette en meget gennemf\u00f8rt pipeline. Holdet, der skabte den, har ikke sk\u00e5net tid eller penge for hurtig implementering. Normalt er implementeringspipelines meget langsommere og mindre p\u00e5lidelige.<\/p>\n<p><\/p>\n<h3 id=\"realizaciya-nepreryvnoy-postavki-v-dark\">Implementering af kontinuerlig levering i Dark<\/h3>\n<p><\/p>\n<p>Den kontinuerlige leverance er s\u00e5 vigtig for Dark, at vi fra starten sigtede mod en tid p\u00e5 mindre end et sekund. Vi har gennemg\u00e5et alle trin i pipeline for at fjerne un\u00f8dvendigheder og perfekt udforme det resterende. S\u00e5dan fjernede vi trin.<\/p>\n<p><\/p>\n<blockquote><p>Jessie Frazelle (<noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex>) opfandt det nye ord deployless (uden deployment) p\u00e5 konferencen Future of Software Development i Reykjavik.<\/p><\/blockquote>\n<p>Vi besluttede straks, at Dark ville v\u00e6re baseret p\u00e5 konceptet 'deployless' (tak til <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex> for neologismen). Deployless betyder, at enhver kode straks deployeres og er klar til brug i produktion. Selvf\u00f8lgelig vil vi ikke lade defekt eller ufuldst\u00e6ndig kode slippe igennem (sikkerhedsprincipperne vil jeg beskrive nedenfor).<\/p>\n<p><\/p>\n<p>Under Dark-demonstrationer blev vi ofte spurgt, hvordan vi kunne accelerere deployment s\u00e5 meget. Underligt sp\u00f8rgsm\u00e5l. Folk t\u00e6nker sikkert, at vi har opfundet en superteknologi, der sammenligner koden, kompilere den, pakkere den i en container, starter en virtuel maskine, og ved kolde opstarter containeren, alt sammen p\u00e5 50 ms. Det er n\u00e6ppe muligt. Men vi har skabt en s\u00e6rlig deployment-motor, der ikke har brug for det.<\/p>\n<p><\/p>\n<p>Dark k\u00f8rer tolke i skyen. Antag, at du skriver kode i en funktion eller en HTTP- eller event-handler. Vi sender forskellen til det abstrakte syntaktiske tr\u00e6 (den kodeimplementering, som vores editor og servere bruger internt) til vores servere og udf\u00f8rer s\u00e5 denne kode, n\u00e5r der kommer foresp\u00f8rgsler. S\u00e5 deployment ser ganske enkelt ud som en besked til databasen \u2014 \u00f8jeblikkelig og simpel. Deployment foreg\u00e5r s\u00e5 hurtigt, fordi det kun inkluderer det mest n\u00f8dvendige.<\/p>\n<p><\/p>\n<p>I fremtiden planl\u00e6gger vi at lave Dark til en infrastrukturcompiler, som vil skabe og k\u00f8re den ideelle infrastruktur for h\u00f8j ydeevne og p\u00e5lidelighed af applikationer. \u00d8jeblikkelig deployment forsvinder selvf\u00f8lgelig ikke.<\/p>\n<p><\/p>\n<h2 id=\"bezopasnoe-razvertyvanie\">Sikker deployment<\/h2>\n<p><\/p>\n<h3 id=\"strukturirovannyy-redaktor\">Struktureret editor<\/h3>\n<p><\/p>\n<p>Koden i Dark skrives i Dark-editoren. Den strukturerede editor tillader ikke syntaksfejl. Faktisk findes der ikke engang en parser i Dark. Mens du indtaster tekst, arbejder vi direkte med det abstrakte syntaktiske tr\u00e6 (AST), ligesom <noindex><a rel=\"nofollow\" href=\"http:\/\/danmidwood.com\/content\/2014\/11\/21\/animated-paredit.html\">Paredit<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/ravichugh.github.io\/sketch-n-sketch\/\">Sketch-n-Sketch<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/gregoor.github.io\/tofu\/\">Tofu<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.facebook.com\/notes\/kent-beck\/prune-a-code-editor-that-is-not-a-text-editor\/1012061842160013\/\">Prune<\/a><\/noindex> og <noindex><a rel=\"nofollow\" href=\"https:\/\/www.jetbrains.com\/mps\/\">MPS<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Enhver ufuldendt kode i Dark har en gyldig k\u00f8rselssemantikken, omtrent som <noindex><a rel=\"nofollow\" href=\"https:\/\/hazel.org\/\">typed holes i Hazel<\/a><\/noindex>For example, if you change the function call, we keep the old function until the new one is ready.<\/p>\n<p><\/p>\n<p>Every program in Dark has its purpose, so incomplete code does not interfere with completed code.<\/p>\n<p><\/p>\n<h3 id=\"rezhimy-redaktirovaniya\">Editing Modes<\/h3>\n<p><\/p>\n<p>You write code in Dark in two cases. First: you are writing new code and are the sole user. For example, it\u2019s in REPL, and other users will never have access to it, or it\u2019s a new HTTP route that you\u2019re not referencing anywhere. Here you can work without any precautions, and you\u2019re currently doing just that in the development environment.<\/p>\n<p><\/p>\n<p>The second situation: the code is already in use. If traffic is flowing through the code (functions, event handlers, databases, etc.), caution is required. For this, we block all used code and require more structured tools for editing it. I\u2019ll talk about the structured tools below: feature toggles for HTTP and event handlers, a powerful migration platform for databases, and a new version management method for functions and types.<\/p>\n<p><\/p>\n<h3 id=\"pereklyuchateli-funkciy\">Feature Toggles<\/h3>\n<p><\/p>\n<p>One way <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">to reduce unnecessary complexity<\/a><\/noindex> in Dark is to solve multiple problems with one solution. Feature toggles perform various tasks: replacing the local development environment, git branches, deploying code, and of course, the traditional slow and controlled release of new code.<\/p>\n<p><\/p>\n<p>Creating and deploying a feature toggle is done in our editor in one operation. It creates an empty space for the new code and provides controls to access both the old and new code, as well as buttons and commands for gradually shifting to the new code or excluding it.<\/p>\n<p><\/p>\n<p>Feature toggles are built into the Dark language, and even incomplete toggles do their job\u2014if the condition in the toggle isn\u2019t met, the old blocked code will execute.<\/p>\n<p><\/p>\n<h3 id=\"sreda-razrabotki\">Development Environment<\/h3>\n<p><\/p>\n<p>Funktionsv\u00e6lgere erstatter det lokale udviklingsmilj\u00f8. I dag er det sv\u00e6rt for teams at holde styr p\u00e5, at alle bruger de samme versioner af v\u00e6rkt\u00f8jer og biblioteker (kodeformateringsv\u00e6rkt\u00f8jer, linters, pakkeh\u00e5ndterere, compilere, preprocessorer, testv\u00e6rkt\u00f8jer osv.). Med Dark er der ikke behov for at installere afh\u00e6ngigheder lokalt, administrere en lokal Docker-installation eller tage andre skridt for at sikre nogen form for lighed mellem udviklingsmilj\u00f8et og produktionen. <noindex><a rel=\"nofollow\" href=\"https:\/\/thenewstack.io\/honeycombs-charity-majors-go-ahead-test-in-production\/\">Da s\u00e5danne ligheder alligevel er umulige,<\/a><\/noindex>, vil vi ikke engang lade som om, at vi str\u00e6ber efter det.<\/p>\n<p><\/p>\n<p>I stedet for at oprette et klonet lokalt milj\u00f8, skaber funktionvelgere i Dark en ny sandkasse i produktionen, der erstatter udviklingsmilj\u00f8et. I fremtiden planl\u00e6gger vi ogs\u00e5 at skabe sandkasser til andre dele af applikationen (f.eks. \u00f8jeblikkelige kloner af databaser), selvom det ikke virker s\u00e5 vigtigt lige nu.<\/p>\n<p><\/p>\n<h3 id=\"vetki-i-razvertyvaniya\">Grene og implementeringer<\/h3>\n<p><\/p>\n<p>Der er i \u00f8jeblikket flere m\u00e5der at f\u00e5 ny kode ind i systemerne p\u00e5: git-grene, implementeringsfaser og funktionsvelgere. De adresserer et problem i forskellige dele af arbejdsgangen: git \u2014 i faserne f\u00f8r implementeringen, implementeringen \u2014 i det \u00f8jeblik, vi g\u00e5r fra gammel kode til ny, og funktionsvelgere \u2014 til kontrolleret udgivelse af ny kode.<\/p>\n<p><\/p>\n<p>Den mest effektive metode er funktionsvelgere (og ogs\u00e5 den nemmeste at forst\u00e5 og bruge). Med dem kan man helt undv\u00e6re de to andre metoder. Is\u00e6r er det nyttigt at eliminere implementeringen \u2014 hvis vi trods alt bruger funktionsvelgere til at aktivere koden, s\u00e5 skaber skridtet med at overf\u00f8re servere til den nye kode kun un\u00f8dige risici.<\/p>\n<p><\/p>\n<p>Git er sv\u00e6rt at bruge, is\u00e6r for nybegyndere, hvilket begr\u00e6nser dets anvendelse, men det har den fordel, at det har praktiske grene. Vi har afhjulpet mange af git's ulemper. Dark redigeres i realtid og muligg\u00f8r samarbejde i stil med Google D\/docs, s\u00e5 man ikke beh\u00f8ver at sende kode, og man kan oftere undg\u00e5 rebase og merge.<\/p>\n<p><\/p>\n<p>Funktioneressourcer udg\u00f8r kernen i sikker implementering. Sammen med \u00f8jeblikkelige implementeringer giver de mulighed for hurtigt at teste koncepter i sm\u00e5 bidder med lav risiko i stedet for at anvende \u00e9n stor \u00e6ndring, der kan bringe systemet i fare.<\/p>\n<p><\/p>\n<h3 id=\"versionirovanie\">Versionering<\/h3>\n<p><\/p>\n<p>Til \u00e6ndring af funktioner og typer benytter vi versionering. Hvis du \u00f8nsker at \u00e6ndre en funktion, opretter Dark en ny version af denne funktion. Du kan derefter kalde denne version med en switch i HTTP- eller begivenhedsh\u00e5ndteringen. (Hvis det er en funktion dybt i kaldetr\u00e6et, oprettes der automatisk en ny version for hver funktion. Det kan virke overdrevet, men funktionerne interfererer ikke, hvis du ikke bruger dem, s\u00e5 du vil ikke engang bem\u00e6rke det.)<\/p>\n<p><\/p>\n<p>Af de samme grunde versionerer vi typer. Vi har tidligere beskrevet vores typesystem <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">i det forrige indl\u00e6g<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Med versionering af funktioner og typer kan du implementere \u00e6ndringer i applikationen gradvist. Du kan kontrollere, at hver enkelt handler fungerer med den nye version uden at skulle \u00e6ndre alt i applikationerne p\u00e5 \u00e9n gang (men vi har v\u00e6rkt\u00f8jer til hurtigt at g\u00f8re det, hvis du \u00f8nsker).<\/p>\n<p><\/p>\n<p>Det er langt sikrere end straks at implementere alt p\u00e5 \u00e9n gang, som det er tilf\u00e6ldet nu.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-paketov-i-standartnaya-biblioteka\">Nye versioner af pakker og standardbiblioteket<\/h3>\n<p><\/p>\n<p>N\u00e5r du opdaterer en pakke i Dark, erstatter vi ikke straks brugen af hver funktion eller type i hele kodebasen. Det er ikke sikkert. Koden forts\u00e6tter med at bruge den samme version, som den brugte f\u00f8r, mens du opdaterer brugen af funktioner og typer til den nye version for hvert enkelt tilf\u00e6lde ved hj\u00e6lp af switches.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/rh\/t3\/4w\/rht34wyibolrgracbz88tnqqhg0.png\"><img decoding=\"async\" alt=\"Hvordan Dark implementerer kode p\u00e5 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/54fdb566b4bcbc10e06e51c47a3820f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Sk\u00e6rmbillede af en del af den automatiske proces i Dark, der viser to versioner af funktionen Dict::get. Dict::get_v0 returnerede typen Any (som vi fraskriver os), mens Dict::get_v1 returnerer typen Option.<\/em><\/p>\n<p><\/p>\n<p>Vi tilbyder ofte en ny funktion i standardbiblioteket og fjerner \u00e6ldre versioner. Brugere med \u00e6ldre versioner i koden vil stadig have adgang til dem, men nye brugere vil ikke kunne f\u00e5 adgang til dem. Vi planl\u00e6gger at tilbyde v\u00e6rkt\u00f8jer til at migrere brugere fra \u00e6ldre versioner til nye med et enkelt trin, ogs\u00e5 ved hj\u00e6lp af funktionsswitch.<\/p>\n<p><\/p>\n<p>Dark giver ogs\u00e5 en unik mulighed: da vi k\u00f8rer din arbejds kode, kan vi selv teste nye versioner ved at sammenligne output for nye og gamle foresp\u00f8rgsler, s\u00e5 vi kan informere dig om \u00e6ndringerne. Som f\u00f8lge heraf indeb\u00e6rer opdatering af pakker, som ofte udf\u00f8res blindt (eller kr\u00e6ver omfattende sikkerhedstest), langt f\u00e6rre risici og kan udf\u00f8res automatisk.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-dark\">Nye versioner af Dark<\/h3>\n<p><\/p>\n<p>Overgangen fra Python 2 til Python 3 strakte sig over et \u00e5rti og forbliver stadig et problem. Da vi udvikler Dark til kontinuerlig levering, skal disse sprog\u00e6ndringer tages i betragtning.<\/p>\n<p><\/p>\n<p>N\u00e5r vi laver mindre \u00e6ndringer i sproget, opretter vi en ny version af Dark. Den gamle kode forbliver i den gamle version af Dark, mens den nye kode anvendes i den nye version. For at skifte til den nye version af Dark kan du bruge omskiftere eller funktionsversioner.<\/p>\n<p><\/p>\n<p>Dette er s\u00e6rligt nyttigt, da Dark er relativt nyt. Mange \u00e6ndringer i sproget eller biblioteket kan vise sig at v\u00e6re mislykkede. Trinvist versionering af sproget g\u00f8r det muligt for os at foretage sm\u00e5 opdateringer, dvs. vi beh\u00f8ver ikke at skynde os og kan uds\u00e6tte mange beslutninger om sproget, indtil vi har flere brugere, hvilket betyder, at vi ogs\u00e5 f\u00e5r mere information.<\/p>\n<p><\/p>\n<h3 id=\"migracii-baz-dannyh\">Database-migrationer<\/h3>\n<p><\/p>\n<p>Der findes en standardformel til sikker migration af databaser <noindex><a rel=\"nofollow\" href=\"http:\/\/www.brunton-spall.co.uk\/post\/2014\/05\/06\/database-migrations-done-right\/\">Tilpas koden til at underst\u00f8tte nye og gamle formater<\/a><\/noindex>:<\/p>\n<p><\/p>\n<ul>\n<li>Konverter alle data til det nye format<\/li>\n<li>Fjern gammel adgang til data<\/li>\n<li>Som f\u00f8lge heraf tr\u00e6kker database-migrationen ud og kr\u00e6ver mange ressourcer. Og vi har et ophobning af for\u00e6ldede skemaer, da selv simple opgaver som at rette navnet p\u00e5 en tabel eller kolonne ikke er v\u00e6rd at den tid, der bruges.<\/li>\n<\/ul>\n<p><\/p>\n<p>Dark har en effektiv database-migrationsplatform, der (forh\u00e5bentlig) vil forenkle processen s\u00e5 meget, at du ikke l\u00e6ngere vil frygte den. Alle datalagre i Dark (key-value par lagre eller permanente hash-tabeller) har en type. For at overf\u00f8re datalageret, skal du blot tildele det en ny type og en rollback- og rollforward-funktion til konvertering af v\u00e6rdier mellem de to typer.<\/p>\n<p><\/p>\n<p>Dark har en effektiv database migrationsplatform, som (vi h\u00e5ber) vil g\u00f8re processen s\u00e5 simpel, at du ikke l\u00e6ngere vil frygte den. Alle datalagre i Dark (key-value par lagre eller permanente hash-tabeller) har en type. For at overf\u00f8re et datalager tildeler du det blot en ny type og en rollback- og redeploy-funktion til at konvertere v\u00e6rdierne mellem de to typer.<\/p>\n<p><\/p>\n<p>Adgang til datalagre i Dark sker gennem versionsstyrede variabelnavne. For eksempel vil datalageret Users oprindeligt blive kaldt Users-v0. N\u00e5r der oprettes en ny version med en anden type, \u00e6ndres navnet til Users-v1. Hvis data er gemt via Users-v0, og du tilg\u00e5r dem gennem Users-v1, anvendes rollback-funktionen. Hvis data er gemt via Users-v1, og du tilg\u00e5r dem gennem Users-v0, anvendes rollback-funktionen.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/ui\/sl\/wd\/uislwdrfrvact0d1ts5icnk-4ka.png\"><img decoding=\"async\" alt=\"Hvordan Dark implementerer kode p\u00e5 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/35743ba246f327ca9e8b71f0069a3800.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Sk\u00e6rmbilledet til migrering af databasen indeholder navne p\u00e5 felterne i den gamle database, rollback- og undo-udtryk samt instruktioner til at aktivere migreringen.<\/em><\/p>\n<p><\/p>\n<p>Brug funktionsswitcher til at dirigere kald til Users-v0 til version Users-v1. Dette kan g\u00f8res en HTTP-handler ad gangen for at mindske risiciene, og switcherne fungerer for enkelte brugere, s\u00e5 du kan teste, at alt fungerer som forventet. N\u00e5r der ikke er flere brugere af Users-v0, konverterer Dark alle resterende data i baggrunden fra det gamle format til det nye. Du vil n\u00e6ppe bem\u00e6rke det.<\/p>\n<p><\/p>\n<h3 id=\"testirovanie\">Testning<\/h3>\n<p><\/p>\n<p>Dark er en <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">funktionsbaseret programmeringssprog med statisk type<\/a><\/noindex> og umodificerbare v\u00e6rdier, s\u00e5 testfladen er betydeligt mindre sammenlignet med objektorienterede sprog med dynamisk type. Men der skal stadig testes.<br \/>\nI Dark udf\u00f8rer editoren automatisk unit tests i baggrunden for den redigerede kode og k\u00f8rer som standard disse tests for alle funktionsswitcher. I fremtiden \u00f8nsker vi at udf\u00f8re fuzzing af koden automatisk ved hj\u00e6lp af statiske typer, s\u00e5 vi kan finde fejl.<\/p>\n<p><\/p>\n<p>Derudover k\u00f8rer Dark din infrastruktur i produktion, hvilket \u00e5bner nye muligheder. Vi gemmer automatisk HTTP-anmodninger i Dark-infrastrukturen (indtil videre gemmer vi alle anmodninger, men senere \u00f8nsker vi at overg\u00e5 til sampling). Vi tester nyt kode og udf\u00f8rer unit tests p\u00e5 dem, og hvis du \u00f8nsker det, kan du nemt konvertere interessante anmodninger til unit tests.<\/p>\n<p><\/p>\n<h3 id=\"ot-chego-my-izbavilis\">Hvad vi har sagt farvel til<\/h3>\n<p><\/p>\n<p>Da vi ikke har deployment, men har funktionsswitcher, forbliver omkring 60% af deploymentsystemet udenfor. Vi har ikke brug for git branches eller pull requests, bygging af backend-ressourcer og containere, upload af ressourcer og containere til registre eller deployment-trin i Kubernetes.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/gc\/9e\/g-\/gc9eg-szouq0dtrxxr8jd6c6dyo.jpeg\"><img decoding=\"async\" alt=\"Hvordan Dark implementerer kode p\u00e5 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/d584b13a1f91e9eef1e2e40c25e90052.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Sammenligning af den standardiserede pipeline til kontinuerlig levering (til venstre) og kontinuerlig levering Dark (til h\u00f8jre). I Dark best\u00e5r leveringen af 6 trin og 1 cyklus, mens den traditionelle version inkluderer 35 trin og 3 cyklusser.<\/em><\/p>\n<p><\/p>\n<p>I Dark er der kun 6 trin og 1 cyklus i deployment (trin, der gentages flere gange), mens den moderne pipeline til kontinuerlig levering best\u00e5r af 35 trin og 3 cyklusser. I Dark k\u00f8res testene automatisk, og du ser det endda ikke; afh\u00e6ngigheder installeres automatisk; alt, der relaterer til git eller Github, er ikke l\u00e6ngere n\u00f8dvendigt; at bygge, teste og sende Docker-containere er ikke n\u00f8dvendigt; deployment i Kubernetes er ikke l\u00e6ngere n\u00f8dvendigt.<\/p>\n<p><\/p>\n<p>Selv de resterende trin i Dark er blevet enklere. Da funktionsswitchene kan styres med \u00e9n handling, beh\u00f8ver man ikke at gennemg\u00e5 hele deployment-pipelinen igen for at fjerne gammel kode.<\/p>\n<p><\/p>\n<p>Vi har gjort vores bedste for at forenkle kodens levering, hvilket har reduceret tid og risici ved kontinuerlig levering. Og vi har ogs\u00e5 betydeligt forenklet opdatering af pakker, database-migreringer, test, versionsstyring, installation af afh\u00e6ngigheder, lighed mellem udviklings- og produktionsmilj\u00f8er og hurtige og sikre opgraderinger af sprogversioner.<\/p>\n<p><\/p>\n<p>Jeg svarer p\u00e5 sp\u00f8rgsm\u00e5l om dette p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/news.ycombinator.com\/item?id=20394166\">HackerNews<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>For at l\u00e6re mere om Dark, l\u00e6s <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">artiklen om Dark<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/darklang?source=post_page---------------------------\">f\u00f8lg os p\u00e5 Twitter<\/a><\/noindex> (eller p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/paulbiggar?source=post_page---------------------------\">mig<\/a><\/noindex>) eller <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/subscribe?source=post_page---------------------------\">tilmeld dig beta-versionen og modtag notifikationer om kommende indl\u00e6g<\/a><\/noindex>. Hvis du tager til StrangeLoop i september, <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/launch\">kom og bes\u00f8g os til lanceringen<\/a><\/noindex>.<\/p>\n<p>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/462027\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u0440\u043e\u0442\u0438\u0432 \u043d\u0430\u0441 \u2014 \u043d\u0430\u0448\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043c\u0435\u0448\u0430\u0442\u044c \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u0440\u043e\u0441\u0442\u043e\u044f\u043c \u0438 \u043f\u0435\u0440\u0435\u0440\u044b\u0432\u0430\u043c. \u0420\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0432 \u0442\u0430\u043a\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0430\u0436\u0435 \u0432 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27506,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36721","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Hvordan Dark deployer kode p\u00e5 50 ms | ProHoster","description":"Jo hurtigere udviklingsprocessen er, jo hurtigere.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster","og:description":"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.","og:url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:13:20+00:00","article:modified_time":"2019-10-31T19:13:20+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36721","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:34:22","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:40:22","updated":"2026-01-22 04:34:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/36721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=36721"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/36721\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/27506"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=36721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=36721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=36721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}