{"id":93885,"date":"2020-09-10T19:42:23","date_gmt":"2020-09-10T17:42:23","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov"},"modified":"2020-09-10T19:42:23","modified_gmt":"2020-09-10T17:42:23","slug":"continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov","status":"publish","type":"post","link":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov","title":{"rendered":"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/ed8a32ae63b8dccfc8b4893ab27f1527.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lad os diskutere, hvorfor CI-v\u00e6rkt\u00f8jer og CI er helt forskellige.<\/p>\n<p><\/p>\n<p>Hvilket problem CI er tilt\u00e6nkt at l\u00f8se, hvor id\u00e9en stammer fra, hvilke seneste beviser der er for, at det fungerer, og hvordan man kan forst\u00e5, at man har praksis og ikke bare en installeret Jenkins.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Id\u00e9en om at holde et foredrag om Continuous Integration opstod for et \u00e5r siden, da jeg var til samtaler for at finde et job. Jeg talte med 10-15 virksomheder, og kun \u00e9n kunne forst\u00e5eligt forklare, hvad CI er, og hvordan de inds\u00e5, at de ikke havde det. De andre sagde uforst\u00e5elige ting om Jenkins \ud83d\ude42 N\u00e5, vi har Jenkins, den laver builds, CI! I mit foredrag vil jeg fors\u00f8ge at forklare, hvad Continuous Integration faktisk er, og hvorfor Jenkins og lignende v\u00e6rkt\u00f8jer har en meget svag relation til det.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/a57813a652c0d788e5a927dc8a7130ba.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>S\u00e5 hvad kommer normalt i tankerne, n\u00e5r man h\u00f8rer ordet CI? For de fleste mennesker vil det v\u00e6re Jenkins, Gitlab CI, Travis osv.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/c9799c11ba7bb7bbdb2048c2f314b22a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Selv hvis vi googler, s\u00e5 vil vi f\u00e5 disse v\u00e6rkt\u00f8jer op.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/028ef088b28b73e7905b1666d9d53d1b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvis man sp\u00f8rger kendte, vil de straks efter at have n\u00e6vnt v\u00e6rkt\u00f8jerne fort\u00e6lle, at CI er, n\u00e5r der sker builds og testk\u00f8rsel i Pull Requests p\u00e5 commits.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/f37ba8f985c10900f669540e063c5e43.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Continuous Integration handler ikke om v\u00e6rkt\u00f8jer, ikke om builds med tests i grenen! Continuous Integration er en praksis med meget hyppig integration af ny kode, og for at anvende det er det slet ikke n\u00f8dvendigt at bygge Jenkins, GitLab osv.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/c3a12b4a875050550b42714607e787c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>F\u00f8r vi dykker ned i, hvordan en fuld CI ser ud, lad os f\u00f8rst se p\u00e5 konteksten af de mennesker, der fandt p\u00e5 det, og m\u00e6rke den smerte, de fors\u00f8gte at l\u00f8se.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/2ab9c0f4dba2887fed5744c8b021b424.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>De fors\u00f8gte at l\u00f8se smerterne ved samarbejde i et team!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/11a5f3b1075f8b8d0f169fe07adf6c91.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Lad os se p\u00e5 eksempler p\u00e5, hvilke problemer udviklere oplever ved teamudvikling. Her har vi et projekt, master-grenen i git og to udviklere.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/8138a52376e87239ff5f7b0af5cd8fee.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og de gik i gang med at arbejde ligesom alle efterh\u00e5nden er blevet vant til. De tog en opgave i JIRA, oprettede en feature-gren, og skrev kode.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/54720c40d9bbd9631b411a2a26c4083f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En af dem blev f\u00e6rdig med funktionen hurtigere og fusionerede den i master.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/4593dc3cf33a44bf3a4d8166be9bc5da.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Den anden brugte mere tid, fusionerede senere og fik en konflikt. Nu, i stedet for at skrive de n\u00f8dvendige funktioner til forretningen, bruger udvikleren sin tid og energi p\u00e5 at l\u00f8se konflikter.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/c947601fb1dd3b3dd64bac455dc6691a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jo mere komplekst det er at integrere din funktion med masteren, jo mere tid bruger vi p\u00e5 det. Og det er kun et ret simpelt eksempel. Dette eksempel involverer kun 2 udviklere. Forestil dig, hvis der er 10, 15 eller 100 personer i firmaet, der skriver i det samme repository. Du ville miste forstanden ved at l\u00f8se alle disse konflikter. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/16c6b8b51ae462f1e0acb966a93c0ae5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Der er en lidt anderledes situation. Vi har en master og flere udviklere, der laver noget.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/21b78ad8d0cb7cb5bded6ef9d49707c5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>De har oprettet hver deres gren.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/b85d8aa0080f08c1ad8ad83f3a9ab084.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c9n blev flettet ind, alt var godt, opgaven blev afleveret.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/e96d4fd52c39089e3377ed85adeeb591.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Den anden udvikler afleverede sin opgave imens. Antag, at han gav den til en gennemgang. I mange virksomheder er der en praksis \u2013 gennemgang. P\u00e5 den ene side er det en god og nyttig praksis, men p\u00e5 den anden side bremser det os ofte. Lad os ikke dykke dybere ned i det, men her er et glimrende eksempel p\u00e5, hvorledes en sk\u00e6v proces med gennemgang kan f\u00f8re til komplikationer. Du har sendt en pull request til gennemgang. Den udvikler, der skal se p\u00e5 det, har ikke noget andet at lave. Hvad g\u00f8r han? Han begynder at tage andre opgaver. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/7b8e121be99432606056acf11e20f518.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I mellemtiden har den anden udvikler ogs\u00e5 lavet noget. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/ceaa5ba5b3b5014fad527362f5794e94.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Den f\u00f8rste udf\u00f8rte den tredje opgave. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/9c27663e63bb9489ecffc5a1f73abb87.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og efter et stykke tid blev hans gennemgang lavet, og han pr\u00f8ver at flettes ind. Hvad sker der s\u00e5? Han st\u00e5r over for et stort antal konflikter. Hvorfor? Fordi mens hans pull request var til gennemgang, er der allerede sket mange \u00e6ndringer i koden. <\/p>\n<p><\/p>\n<p>Udover konflikten er der ogs\u00e5 kommunikationsproblemet. Mens din gren h\u00e6nger til gennemgang, mens du venter, mens du arbejder l\u00e6nge p\u00e5 en funktion, mister du overblikket over, hvad der ellers \u00e6ndrer sig i kodebasen for din service. Det er muligt, at det, du nu fors\u00f8ger at l\u00f8se, allerede blev l\u00f8st i g\u00e5r, og du kunne tage og genbruge en metode. Men du vil ikke se det, fordi du altid arbejder med en for\u00e6ldet gren. Og denne for\u00e6ldede gren f\u00f8rer altid til, at du skal h\u00e5ndtere en merge-konflikt. <\/p>\n<p><\/p>\n<p>S\u00e5 hvis vi arbejder i et team, dvs. ikke bare \u00e9n person roder rundt i repositoryet, men 5-10 personer, s\u00e5 jo l\u00e6ngere tid vi ikke tilf\u00f8jer vores kode til masteren, jo mere lider vi af, at vi til sidst skal flette noget. Jo flere konflikter vi har, og jo \u00e6ldre version vi arbejder med, desto flere problemer f\u00e5r vi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/55c070f65a4d3838fb8c02bb9684c76b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>At g\u00f8re noget sammen er smertefuldt! Vi forstyrrer altid hinanden. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/b914c50aad6f3c9f97edcad7e71ba627.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dette problem blev gjort opm\u00e6rksom p\u00e5 for over 20 \u00e5r siden. Jeg fandt den f\u00f8rste omtale af praksis for Continuous Integration i ekstrem programmering.<\/p>\n<p><\/p>\n<p>Ekstrem programmering er den f\u00f8rste agile ramme. Siden blev lanceret i 96, og ideen var at bruge nogle programmerings- og planl\u00e6gningspraksisser for at g\u00f8re udviklingen s\u00e5 fleksibel som muligt, s\u00e5 vi hurtigt kunne reagere p\u00e5 \u00e6ndringer og krav fra vores kunder. For 24 \u00e5r siden begyndte de at indse, at hvis man arbejder med noget meget l\u00e6nge og sidel\u00f8bende, bruger man mere tid, fordi der opst\u00e5r konflikter. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/93a80838bdb3b297557dbf2ac7587965.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nu vil vi analysere udtrykket 'Continuous Integration' ord for ord. Hvis man overs\u00e6tter direkte, f\u00e5r man kontinuerlig integration. Men hvor kontinuerlig den egentlig er, er ikke helt klart; den er faktisk meget afbrudt. Hvor meget den er integration, er heller ikke helt \u00e5benbart. <\/p>\n<p><\/p>\n<p>Derfor giver jeg dig nu citater fra ekstrem programmering. Vi vil analysere de to ord hver for sig. <\/p>\n<p><\/p>\n<p>Integration \u2014 Som jeg allerede har sagt, str\u00e6ber vi efter, at hver ingen\u00f8r arbejder med den nyeste version af koden, s\u00e5 han ofte tilf\u00f8jer sin kode til den f\u00e6lles gren, s\u00e5 det bliver sm\u00e5 grene. For hvis de er store, kan vi let sidde fast i en uge med merge-konflikter. Is\u00e6r hvis vi har en lang udviklingscyklus som vandfald, hvor udvikleren har v\u00e6ret v\u00e6k i en m\u00e5ned for at udvikle en k\u00e6mpestor funktion. Ved integrationsfasen kan han alts\u00e5 sidde fast i lang tid. <\/p>\n<p><\/p>\n<p>Integration \u2013 det er n\u00e5r vi tager vores gren og integrerer den med masteren, vi merge den. Der er en ultimativ mulighed, n\u00e5r vi transbase developer, hvor vi str\u00e6ber efter at skrive direkte i master uden yderligere grene.<\/p>\n<p><\/p>\n<p>Generelt er integration at tage sin kode og bringe den ind i master. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/8950103e6a59ed7132ec321ac6abe600.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvad menes der her med ordet \"continuous\", hvad kaldes kontinuitet? Praksis indeb\u00e6rer, at udvikleren str\u00e6ber efter at integrere sin kode s\u00e5 hurtigt som muligt. Det er hans m\u00e5l, n\u00e5r han udf\u00f8rer en hvilken som helst opgave \u2013 at f\u00e5 sin kode til at blive en del af masteren s\u00e5 hurtigt som muligt. I en ideel verden ville udviklerne g\u00f8re dette hvert par timer. Det vil sige, du tager en lille opgave og merger den ind i masteren. Alt er fantastisk. Du str\u00e6ber efter dette. Og det skal g\u00f8res kontinuerligt. S\u00e5 snart du har lavet noget, skal du straks f\u00e5 det ind i masteren. <\/p>\n<p><\/p>\n<p>Og udvikleren, der laver noget, er ansvarlig for det, han har lavet, s\u00e5 det fungerer og ikke \u00f8del\u00e6gger noget. Her dukker historien om tests normalt op. Vi \u00f8nsker at k\u00f8re nogle tests p\u00e5 vores commit, p\u00e5 vores merge, for at sikre, at det fungerer. Og her kan Jenkins faktisk hj\u00e6lpe dig.<\/p>\n<p><\/p>\n<p>Men med historierne: lad os s\u00f8rge for, at \u00e6ndringerne er sm\u00e5, lad os s\u00f8rge for, at opgaverne er sm\u00e5, og lad os lave opgaven og straks fors\u00f8ge at merge den ind i masteren \u2013 her vil ingen Jenkins kunne hj\u00e6lpe. For Jenkins kan udelukkende hj\u00e6lpe dig med at k\u00f8re tests. <\/p>\n<p><\/p>\n<p>Du kan klare dig uden dem. Det vil ikke skade dig. For m\u00e5let med praksis er at merge s\u00e5 ofte som muligt for ikke at bruge en stor m\u00e6ngde tid p\u00e5 konflikter i fremtiden. <\/p>\n<p><\/p>\n<p>Forestil dig, at vi i 2020 p\u00e5 en eller anden m\u00e5de lever uden internet. Og vi arbejder lokalt. Vi har ikke Jenkins. Det er fint. Du kan stadig tage og lave en lokal gren. Du har skrevet noget kode i den. Udf\u00f8rt opgaven p\u00e5 3-4 timer. Skiftet til master, lavet git pull, og merged din gren ind. Klar. Hvis du g\u00f8r dette ofte \u2013 tillykke, du har Continuous Integration!<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/1f2117b65994b940edb04e0e119f6e8a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hvilke beviser findes der i den moderne verden om, at det er v\u00e6rd at investere kr\u00e6fter i? Fordi det generelt er sv\u00e6rt. Hvis du pr\u00f8ver at arbejde p\u00e5 denne m\u00e5de, vil du indse, at du nu vil ber\u00f8re en slags planl\u00e6gning, og du m\u00e5 bruge mere tid p\u00e5 at dekomponere opgaver. For hvis du laver man\u2026, s\u00e5 vil du ikke kunne merge hurtigt og dermed havne i problemer. Du vil ikke l\u00e6ngere have praksis. <\/p>\n<p><\/p>\n<p>Og det vil blive dyrt. At begynde at arbejde med Continuous Integration fra i morgen vil ikke v\u00e6re muligt. I vil alle tage meget lang tid om at v\u00e6nne jer til det, meget lang tid om at l\u00e6re at nedbryde opgaver, meget lang tid om at v\u00e6nne jer til at \u00e6ndre review-praksis, hvis I har s\u00e5dan en. Fordi vores m\u00e5l er, at det skal merge i dag. Og hvis I bruger tre dage p\u00e5 review, s\u00e5 har I problemer, og s\u00e5 fungerer Continuous Integration ikke. <\/p>\n<p><\/p>\n<p>Men har vi nogle aktuelle beviser lige nu, der fort\u00e6ller os, at det giver mening at investere i denne praksis?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/2026a8f1d72fb05613511e7bab57e8ec.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Det f\u00f8rste, der kom til at t\u00e6nke p\u00e5, var State of DevOps. Dette er en unders\u00f8gelse, som folkene har udf\u00f8rt i 7 \u00e5r. Nu g\u00f8r de det som en uafh\u00e6ngig organisation, men under Google.<\/p>\n<p><\/p>\n<p>Og deres unders\u00f8gelse i 2018 viste en korrelation mellem virksomheder, der fors\u00f8ger at bruge kortlivede grene, som integreres hurtigt og ofte, de har bedre IT-ydeevnem\u00e5linger.<\/p>\n<p><\/p>\n<p>Hvad er disse m\u00e5linger? Det er 4 metrikker, som de indsamler fra alle selskaber i deres sp\u00f8rgeskemaer: deployment frequency, lead time for changes, time to restore service, change failure rate.<\/p>\n<p><\/p>\n<p>Og for det f\u00f8rste er der denne korrelation; vi ved, at virksomheder, der merger ofte, har disse metrikker meget bedre. Og de opdeler virksomhederne i flere kategorier: dette er langsomme virksomheder, der producerer noget langsomt, medium performer, high performer og elite. Eliten er Netflix, Amazon, som er superhurtige, g\u00f8r alt hurtigt, smukt og kvalitetsfuldt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/4fd98ef48a5cffdd6ae2ceea93dbb0bf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Den anden historie, der skete for bare en m\u00e5ned siden. I Technology Radar kom der en fantastisk note om Gitflow. Gitflow adskiller sig fra alle andre ved, at dets grene lever l\u00e6nge. Der er release-grene, der lever l\u00e6nge, og feature-grene, der ogs\u00e5 lever l\u00e6nge. Denne praksis i Technology Radar er blevet flyttet til HOLD. Hvorfor? Fordi folk oplever smerte i integrationen. <\/p>\n<p><\/p>\n<p>Hvis din gren lever meget l\u00e6nge, bliver den indviklet, for\u00e6ldes, og vi begynder at bruge mere tid p\u00e5 at foretage \u00e6ndringer i den. <\/p>\n<p><\/p>\n<p>Og for nylig sagde forfatteren til Gitflow, at hvis du str\u00e6ber efter Continuous Integration, hvis du \u00f8nsker at deploye s\u00e5 ofte som muligt, s\u00e5 er Gitflow en d\u00e5rlig id\u00e9. Han tilf\u00f8jede separat i artiklen, at hvis du har en backend, hvor du kan str\u00e6be efter dette, s\u00e5 er Gitflow overfl\u00f8digt for dig, fordi Gitflow vil bremse dig ned og skabe integrationsproblemer. <\/p>\n<p><\/p>\n<p>Det betyder ikke, at Gitflow er d\u00e5rligt, og at man ikke skal bruge det. Det er til andre situationer. For eksempel, n\u00e5r du skal underst\u00f8tte flere versioner af en service eller app, dvs. n\u00e5r du skal supportere i en l\u00e6ngere periode. <\/p>\n<p><\/p>\n<p>Men hvis du snakker med folk, der underst\u00f8tter s\u00e5danne tjenester, vil du h\u00f8re meget om, at denne version var 3.2, som blev udgivet for 4 m\u00e5neder siden, og at denne fix ikke kom med, og nu skal der laves en masse \u00e6ndringer for at f\u00e5 det ind. Og nu er de igen fanget, og de k\u00e6mper i en uge for at f\u00e5 smeltet en ny funktion sammen. <\/p>\n<p><\/p>\n<p>Som Alexander Kovalev korrekt bem\u00e6rkede i chatten, er korrelation ikke det samme som \u00e5rsagssammenh\u00e6ng. Det er korrekt. Det vil sige, der er ikke en direkte forbindelse, at hvis du har Continuous Integration, s\u00e5 vil alle metrics v\u00e6re fantastiske, nej. Men der er en positiv korrelation, at hvis det ene er tilf\u00e6ldet, s\u00e5 er det sandsynligvis tilf\u00e6ldet med det andet ogs\u00e5. Ikke et faktum, men sandsynligvis. Det er kun en korrelation. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov\" src=\"\/wp-content\/uploads\/2020\/09\/d5fc050550b0e9f86a1fdf85fff32fa5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Det virker som om, vi allerede laver noget, vi er allerede i gang med at merge, men hvordan kan vi forst\u00e5, at vi faktisk har Continuous Integration, at vi mergeer ofte nok?<\/p>\n<p><\/p>\n<p>Jez Humble er forfatter til Handbook, Accelerate, hjemmesiden Continuous Delivery og bogen \"Continuous Delivery\". Han foresl\u00e5r en test som denne:<\/p>\n<p><\/p>\n<ul>\n<li>Ingeni\u00f8rens kode g\u00e5r ind i master dagligt. <\/li>\n<li>For hver commit k\u00f8rer du unit-tests.<\/li>\n<li>Builden i master er faldet, og det blev fikset p\u00e5 cirka 10 minutter.<\/li>\n<\/ul>\n<p><\/p>\n<p>Han foresl\u00e5r at anvende denne test for at sikre, at du faktisk har denne praksis. <\/p>\n<p><\/p>\n<p>Det sidste finder jeg lidt tvivlsomt. Det vil sige, hvis du kan l\u00f8se det p\u00e5 10 minutter, s\u00e5 har du Continuous Integration, hvilket lyder lidt underligt, efter min mening, men der er mening i det. Hvorfor? Fordi, hvis du ofte laver merges, betyder det, at dine \u00e6ndringer er sm\u00e5. Hvis en lille \u00e6ndring f\u00f8rer til, at din master-build g\u00e5r i stykker, kan du hurtigt finde et eksempel, fordi \u00e6ndringen er lille. Du havde en lille merge, hvor 20-30 linjer blev \u00e6ndret. Og derfor kan du hurtigt forst\u00e5 \u00e5rsagen, fordi \u00e6ndringerne er meget sm\u00e5, og du har et meget lille s\u00f8geomr\u00e5de for problemet. <\/p>\n<p><\/p>\n<p>Og selv hvis vores prod g\u00e5r i stykker efter en release, s\u00e5 er det, hvis vi har praksis for Continuous Integration, meget lettere at handle, fordi \u00e6ndringerne er sm\u00e5. Ja, det vil ber\u00f8re planl\u00e6gningen. Det vil v\u00e6re smertefuldt. Og nok det sv\u00e6reste ved denne praksis er at v\u00e6nne sig til at opdele opgaver, det vil sige, hvordan man tager noget og g\u00f8r det p\u00e5 et par timer og samtidig gennemg\u00e5r en review, hvis det er noget, du har. Review er en s\u00e6rskilt smerte. <\/p>\n<p><\/p>\n<p>Unit-tests er bare en hj\u00e6lper, der hj\u00e6lper dig med at forst\u00e5 \u2013 om din integration er g\u00e5et godt, om der ikke er noget, der er g\u00e5et i stykker. Efter min mening er dette heller ikke en helt n\u00f8dvendig punkt, fordi essensen af praksis ikke ligger i dette. <\/p>\n<p><\/p>\n<p>Det er kort om Continuous Integration. Det er alt, hvad der er i denne praksis. Jeg er klar til sp\u00f8rgsm\u00e5l. <\/p>\n<p><\/p>\n<p>Kort opsummering:<\/p>\n<p><\/p>\n<ul>\n<li>Continuous Integration er ikke Jenkins, det er ikke Gitlab.<\/li>\n<li>Det er ikke et v\u00e6rkt\u00f8j, det er en praksis om, at vi s\u00e5 ofte som muligt merger vores kode ind i masteren. <\/li>\n<li>Vi g\u00f8r dette for at undg\u00e5 den enorme smerte, der opst\u00e5r med merges i fremtiden, det vil sige, vi oplever lille smerte nu for ikke at opleve stor smerte senere. Det er hele meningen. <\/li>\n<li>Fra siden sker kommunikationen gennem koden, men jeg ser det meget sj\u00e6ldent, men det var ogs\u00e5 intentionen.<\/li>\n<\/ul>\n<p><\/p>\n<p><strong>Sp\u00f8rgsm\u00e5l<\/strong><\/p>\n<p><\/p>\n<p><em>Hvad skal man g\u00f8re med uklare opgaver?<\/em><\/p>\n<p><\/p>\n<p>Decomponere. Hvad er problemet? Kan du give et eksempel p\u00e5, at der er en opgave, som ikke kan dekomponeres?<\/p>\n<p><\/p>\n<p><em>Der er s\u00e5danne opgaver, som slet ikke kan dekomponeres, for eksempel dem, der kr\u00e6ver meget dyb ekspertise og som virkelig kan tage en m\u00e5ned at n\u00e5 frem til et eller andet form\u00e5lstjenligt resultat.<\/em> <\/p>\n<p><\/p>\n<p>Hvis jeg forst\u00e5r dig rigtigt, s\u00e5 er der en stor og kompleks opgave, hvis resultat f\u00f8rst vil v\u00e6re synligt om en m\u00e5ned?<\/p>\n<p><\/p>\n<p><em>Ja, det er korrekt. Ja, resultatet kan f\u00f8rst vurderes om en m\u00e5ned.<\/em> <\/p>\n<p><\/p>\n<p>Okay. Generelt er det ikke et problem. Hvorfor? Fordi vi i dette tilf\u00e6lde, n\u00e5r vi taler om grene, ikke taler om en gren med en funktion. Funktioner kan v\u00e6re store og komplekse. De kan involvere mange komponenter. Og m\u00e5ske kan vi ikke g\u00f8re dem helt i \u00e9n gren. Det er helt i orden. Vi skal bare opdele denne historie. Hvis funktionen ikke er helt klar, betyder det ikke, at der ikke er dele af dens kode, der kan flettes. Du har f.eks. tilf\u00f8jet migration, og der er nogle trin inden for funktionen. Du har f.eks. et trin \u2013 at lave migration, tilf\u00f8je en ny metode. Og du kan allerede flette disse ting dagligt. <\/p>\n<p><\/p>\n<p><em>Okay. Hvad er s\u00e5 meningen med det?<\/em><\/p>\n<p><\/p>\n<p>Hvad er meningen med at flette sm\u00e5 ting dagligt?<\/p>\n<p><\/p>\n<p><em>Ja.<\/em><\/p>\n<p><\/p>\n<p>Hvis de \u00f8delagde noget for dig, ser du det straks. Du har et lille stykke, som \u00f8delagde noget, det er nemmere at rette. Meningen er, at det i h\u00f8jere grad er lettere at flette et lille stykke nu end at flette noget stort om nogle uger. Den tredje pointe er, at andre ingeni\u00f8rer vil arbejde med den nuv\u00e6rende version af koden. De vil se, at nogle migrationer er blevet tilf\u00f8jet her, og at der er en metode, som de m\u00e5ske ogs\u00e5 \u00f8nsker at bruge. Alle kan se, hvad der sker i din kode. M\u00e5let med disse tre ting er grundlaget for praksis. <\/p>\n<p><\/p>\n<p><em>Tak, sp\u00f8rgsm\u00e5let er afsluttet!<\/em><\/p>\n<p><\/p>\n<p><em>(Oleg Soroka) M\u00e5 jeg tilf\u00f8je noget? Du sagde det hele rigtigt, jeg vil kun tilf\u00f8je en s\u00e6tning.<\/em><\/p>\n<p><\/p>\n<p>S\u00e5dan.<\/p>\n<p><\/p>\n<p><em>Ved Continuous Integration fletter koden ikke i den samlede gren, n\u00e5r funktionen er helt klar, men n\u00e5r buildet ikke l\u00e6ngere fejler. Og I kan roligt commite i master s\u00e5 mange gange om dagen, I vil. Det andet aspekt \u2013 hvis I ikke kan dele en m\u00e5neds opgave op i opgaver p\u00e5 mindst tre dage, jeg n\u00e6vner ikke engang tre timer, s\u00e5 har I et k\u00e6mpe problem. Og det faktum, at I ikke har Continuous Integration \u2013 er det mindste af disse problemer. Det betyder, at I har problemer med arkitekturen og ingeni\u00f8rpraksisserne er p\u00e5 nul. Fordi selv hvis det er research, skal det stadig pr\u00e6senteres som hypoteser eller cyklus.<\/em> <\/p>\n<p><\/p>\n<p><em>Vi snakkede om 4 metrikker, der adskiller succesfulde virksomheder fra de mindre heldige. Det kr\u00e6ver tid at n\u00e5 disse 4 metrikker. Hvis en opgave tager en m\u00e5ned, ville jeg fokusere p\u00e5 at f\u00e5 den ned p\u00e5 3 dage f\u00f8rst. Efter det kan du begynde at t\u00e6nke p\u00e5 Continuous.<\/em><\/p>\n<p><\/p>\n<p>Forst\u00e5r jeg dig korrekt, at du mener, det ikke giver mening at investere i ingeni\u00f8rpraksis, hvis enhver opgave tager en m\u00e5ned?<\/p>\n<p><\/p>\n<p><em>Du har Continuous Integration. Og der er en ting med, at du enten retter en fejl p\u00e5 10 minutter eller ruller tilbage. Forestil dig, at du har udgivet det. Og du har endda continuous deployment, du har udgivet det til produktion og bem\u00e6rkede f\u00f8rst bagefter, at noget gik galt. Og nu skal du rulle det tilbage, men du har allerede gennemf\u00f8rt database-migrering. Din databaseskema er allerede i den n\u00e6ste version, desuden er der endda blevet udf\u00f8rt en backup, og der er blevet skrevet data ind.<\/em><\/p>\n<p><\/p>\n<p><em>Hvad er dit alternativ? Hvis du ruller koden tilbage, kan den ikke l\u00e6ngere fungere med denne opdaterede database.<\/em><\/p>\n<p><\/p>\n<p>Databasen bev\u00e6ger sig kun fremad, ja. <\/p>\n<p><\/p>\n<p><em>For folk med d\u00e5rlig ingeni\u00f8rpraksis har de sandsynligvis ikke engang l\u00e6st den tykke bog om ... Hvad g\u00f8r man med backup? Hvis du gendanner fra en backup, betyder det, at du mister de data, der er blevet indhentet i mellemtiden. For eksempel, hvis du har arbejdet i tre timer med den nye version af databasen, og brugerne har registreret sig. Du g\u00e5r tilbage til den gamle backup, fordi skemaet ikke fungerer med den nye version, hvilket betyder, at de brugere er mistet. Og de er utilfredse, de klager.<\/em><\/p>\n<p><\/p>\n<p><em>For mastering the full range of practices that support Continuous Integration and Continuous Delivery, it's not enough to just learn to write code. First of all, there can be a lot of them, which would be impractical. In addition, there are many other practices like Scientific. There's a practice that GitHub popularized for a time, where you can run both the old code and the new code simultaneously. This is when you implement an unfinished feature, but it can still return some value, either as a function or as a REST API. You run both the new code and the old code and compare the differences between them. If there's a difference, you log that event. This way you know that your new feature is ready to be rolled out over the old one if there have been no discrepancies between the two for a certain period of time.<\/em> <\/p>\n<p><\/p>\n<p><em>There are hundreds of such practices. I would suggest starting with transbase development. It\u2019s not 100% on Continuous Integration, but the practices are the same; one does not live well without the other.<\/em> <\/p>\n<p><\/p>\n<p>Did you mention transbase development as an example of where to look for practices, or are you suggesting that people should start using transbase development?<\/p>\n<p><\/p>\n<p><em>Look at it since they won\u2019t be able to use it. To use it, one needs to read a lot. And when the question arises, 'What to do with a feature that takes a month?', it means that they haven't read about transbase development. I wouldn\u2019t recommend it just yet. I would advise focusing solely on the topic of how to properly architecturally break down large tasks into smaller ones. That\u2019s the essence of decomposition.<\/em><\/p>\n<p><\/p>\n<p><em>Decomposition is one of the architect's tools. We first perform analysis, then decomposition, followed by synthesis and finally integration. This way everything comes together. One must grow towards Continuous Integration through decomposition. Questions arise at the first stage, and yet we are already talking about the fourth stage, meaning the more often integration is done, the better. It\u2019s still a bit premature to do it; it wouldn't hurt to first break down your monolith.<\/em> <\/p>\n<p><\/p>\n<p><em>Der skal tegnes nogle pile og firkanter p\u00e5 en eller anden skema. Du kan ikke sige, at jeg nu vil vise et arkitektonisk skema for den nye applikation og vise \u00e9n firkant, hvor der er en gr\u00f8n knap til applikationen. Under alle omst\u00e6ndigheder vil der v\u00e6re flere firkanter og pile. P\u00e5 ethvert skema, jeg har set, har der v\u00e6ret mere end \u00e9n. Og dekompositionen foretages allerede p\u00e5 niveauet for grafisk repr\u00e6sentation. Derfor kan firkanterne v\u00e6re uafh\u00e6ngige. Hvis ikke, s\u00e5 har jeg store sp\u00f8rgsm\u00e5l til arkitekten.<\/em> <\/p>\n<p><\/p>\n<p>Der er et sp\u00f8rgsm\u00e5l fra chatten: \"Hvis review er obligatorisk og tager lang tid, omkring en dag eller mere?\".<\/p>\n<p><\/p>\n<p>I har problemer med praksis. Review b\u00f8r ikke tage en dag eller mere. Det er den samme historie som det tidligere sp\u00f8rgsm\u00e5l, bare lidt bl\u00f8dere. Hvis review tager en dag, s\u00e5 betyder det sandsynligvis, at det er et meget stort \u00e6ndringsreview. S\u00e5 det skal g\u00f8res mindre. I transbase-udviklingen, som Oleg anbefalede, er der en historie, der kaldes kontinuerlig review. Id\u00e9en er, at vi laver s\u00e5 sm\u00e5 pull requests som muligt bevidst, fordi vi str\u00e6ber efter konstant at merge lidt ad gangen. Derfor \u00e6ndrer pull requesten kun \u00e9n abstraktion eller 10 linjer. Takket v\u00e6re dette tager vores review et par minutter. <\/p>\n<p><\/p>\n<p>Hvis review tager en dag eller mere, betyder det, at der er noget galt. For det f\u00f8rste kan det v\u00e6re, at I har problemer med arkitekturen. Enten er det et stort kodeafsnit p\u00e5 1.000 linjer, for eksempel. Eller jeres arkitektur er s\u00e5 kompleks, at personen ikke kan forst\u00e5 den. Det er et problem, men det m\u00e5 ogs\u00e5 l\u00f8ses. M\u00e5ske beh\u00f8ver I slet ikke at have review. Dette skal ogs\u00e5 overvejes. Review er der, der holder jer tilbage. Det har sine fordele generelt, men I skal forst\u00e5, hvorfor I g\u00f8r det. Er det en m\u00e5de at hurtigt overf\u00f8re information p\u00e5? Er det en m\u00e5de at etablere nogle standarder internt? Hvad er form\u00e5let? Fordi review skal enten v\u00e6re meget hurtig, eller helt annulleres. Det er ligesom transbase-udvikling - en meget smuk historie, men kun for modne folk. <\/p>\n<p><\/p>\n<p>Ang\u00e5ende de 4 metrikker, vil jeg anbefale at tage dem ned for at forst\u00e5, hvad det f\u00f8rer til. Se p\u00e5 tallene, se p\u00e5 billedet, hvor slemt det hele er. <\/p>\n<p><\/p>\n<p><em>(Dmitrij) Jeg er klar til at deltage i diskussionen om dette emne med dig. Tallene og m\u00e5lingerne er alle gode, praksis er ogs\u00e5 god. Men vi skal forst\u00e5, om dette er n\u00f8dvendigt for forretningen. Der er virksomheder, der ikke har brug for s\u00e5dan en hurtig \u00e6ndringshastighed. Jeg kender virksomheder, hvor man ikke kan foretage \u00e6ndringer hver 15. minut. Og ikke fordi de er d\u00e5rlige. Det er en del af livscyklussen. Og for at lave feature branches, feature toggles, kr\u00e6ver det dyb viden.<\/em> <\/p>\n<p><\/p>\n<p>Det er sv\u00e6rt. Hvis du vil l\u00e6se mere om historien bag feature toggles, anbefaler jeg st\u00e6rkt. <noindex><a rel=\"nofollow\" href=\"https:\/\/trunkbaseddevelopment.com\/\">https:\/\/trunkbaseddevelopment.com\/<\/a><\/noindex>. Og der er en fantastisk artikel af Martin Fowler om feature toggles: om de forskellige typer, livscykler osv. Feature toggle er komplekst. <\/p>\n<p><\/p>\n<p><em>Og du svarede stadig ikke p\u00e5 sp\u00f8rgsm\u00e5let: \"Er Jenkins n\u00f8dvendigt eller ej?\"<\/em><\/p>\n<p><\/p>\n<p>Jenkins er faktisk ikke n\u00f8dvendigt i nogen tilf\u00e6lde. Hvis jeg skal v\u00e6re alvorlig, s\u00e5 vil v\u00e6rkt\u00f8jerne: Jenkins, Gitlab give dig bekvemmelighed. Du vil kunne se, om bygningen lykkedes eller ej. De kan hj\u00e6lpe dig, men de vil ikke give dig praksis. De kan kun give dig en cirkel \u2013 Ok, ikke Ok. Og det, hvis du stadig skriver tests, for hvis der ikke er tests, er det stort set meningsl\u00f8st. S\u00e5 det er n\u00f8dvendigt, fordi det er mere praktisk, men generelt kan man klare sig uden det, du vil ikke miste meget. <\/p>\n<p><\/p>\n<p><em>Det vil sige, hvis du har praksis, s\u00e5 er det ikke n\u00f8dvendigt for dig?<\/em><\/p>\n<p><\/p>\n<p>Helt korrekt. Jeg anbefaler testen af Jez Humble. Jeg har en blandet f\u00f8lelse over for det sidste punkt. Men generelt, hvis du har tre ting, du merger konstant, du k\u00f8rer tests p\u00e5 commits i masteren, hurtigt reparerer builden i masteren, s\u00e5 er det muligt, at du ikke har brug for mere. <\/p>\n<p><\/p>\n<p><em>Mens vi venter p\u00e5 sp\u00f8rgsm\u00e5l fra deltagerne, har jeg et sp\u00f8rgsm\u00e5l. Vi har lige talt om produktionskoden. Har du brugt det til infrastrukturskode? Er det samme kode, med de samme principper og livscyklus, eller er der andre livscykler og principper? Normalt, n\u00e5r alle taler om Continuous Integration og Development, glemmer folk ofte, at der ogs\u00e5 er infrastrukturskode. Og i den seneste tid bliver det mere og mere vigtigt. B\u00f8r vi bringe alle disse regler derind?<\/em><\/p>\n<p><\/p>\n<p>Det er ikke bare, at vi b\u00f8r, det ville v\u00e6re fantastisk, fordi det helt sikkert ogs\u00e5 vil forenkle livet. S\u00e5 snart vi arbejder med kode, ikke med scripts i bash, men vi har normal kode.<\/p>\n<p><\/p>\n<p><em>Stop-stop, skripter i bash er ogs\u00e5 kode. Lad v\u00e6re med at r\u00f8re ved min gamle k\u00e6rlighed.<\/em> <\/p>\n<p><\/p>\n<p>Det er fint, jeg vil ikke tr\u00e6de ind i dine minder. Jeg har en personlig modvilje mod bash. Det g\u00e5r ofte galt p\u00e5 en grim og skr\u00e6mmende m\u00e5de. Og det g\u00e5r ofte uforudsigeligt galt, s\u00e5 jeg har ikke meget k\u00e6rlighed til det. Men ok, lad os antage, at du har kode i bash. M\u00e5ske forst\u00e5r jeg ikke det, og der findes gode testframeworks der. Jeg er bare ikke i det. Og vi f\u00e5r de samme fordele.<\/p>\n<p><\/p>\n<p>N\u00e5r vi arbejder med infrastruktur som kode, f\u00e5r vi de samme problemer som udviklere. For et par m\u00e5neder siden stod jeg i en situation, hvor en kollega sendte mig en pull request p\u00e5 1.000 linjer i bash. Og du sidder fast i gennemgangen i 4 timer. Problemerne er de samme. Det er stadig kode. Og det er stadig samarbejde. Vi sidder fast med pull requests og sidder fast med de samme merge-konflikter i bash, for eksempel. <\/p>\n<p><\/p>\n<p>Jeg ser i \u00f8jeblikket meget aktivt p\u00e5 at lave smuk infrastrukturprogrammering. Jeg har nu f\u00e5et Pulumi ind i infrastrukturen. Det er ren programmering. Det er endnu mere tiltalende, fordi jeg har alle mulighederne fra programmeringssproget, dvs. jeg har lavet smukke toggles med de samme if'er. Dvs. min \u00e6ndring er allerede i masteren. Alle kan se det. Andre ingeni\u00f8rer er opm\u00e6rksomme p\u00e5 det. Det har allerede haft indflydelse p\u00e5 noget. Men det er ikke sl\u00e5et til for al infrastruktur. Det er sl\u00e5et til for mine testmilj\u00f8er, for eksempel. S\u00e5 for at svare p\u00e5 dit sp\u00f8rgsm\u00e5l igen, ja, det er noget, der bestemt g\u00f8r vores liv lettere som ingeni\u00f8rer, der arbejder med kode. <\/p>\n<p><\/p>\n<p><em>Er der nogen sp\u00f8rgsm\u00e5l endnu?<\/em> <\/p>\n<p><\/p>\n<p>Jeg har et sp\u00f8rgsm\u00e5l. Jeg vil gerne forts\u00e6tte diskussionen med Oleg. Generelt mener jeg, at du har ret; hvis en opgave tager dig en m\u00e5ned, s\u00e5 har du et problem med arkitekturen, et problem med analysen, dekomponeringen, planl\u00e6gningen osv. Men jeg f\u00e5r det indtryk, at hvis du begynder at leve efter Continuous Integration, s\u00e5 vil du begynde at l\u00f8se problemerne med planl\u00e6gningen, fordi du ikke kan undg\u00e5 det. <\/p>\n<p><\/p>\n<p><em>(Oleg) Ja, det er korrekt. Med hensyn til arbejdsbyrden er denne praksis sammenlignelig med enhver anden alvorlig praksis, der \u00e6ndrer kulturen. Den sv\u00e6reste del ved at overvinde dette er vaner, is\u00e6r d\u00e5rlige vaner. Og hvis det kr\u00e6ver en betydelig \u00e6ndring af vanerne hos de omkringliggende: udviklere, ledelse, produktionschefer, s\u00e5 vil du m\u00f8de overraskelser.<\/em> <\/p>\n<p><\/p>\n<p><em>Hvilke overraskelser kan der v\u00e6re? Antag, at du har besluttet dig for at lave integration oftere. Og integrationen er knyttet til nogle andre ting, som for eksempel artefakter. Og i din virksomhed er der for eksempel en politik om, at hvert artefakt skal registreres p\u00e5 en eller anden m\u00e5de i et system til opbevaring af artefakter. Det tager noget tid. En person skal s\u00e6tte en markering for, at han som release manager har testet dette artefakt til klarhed til produktion. Hvis det tager 5-10-15 minutter, men du laver en udrulning \u00e9n gang om ugen, s\u00e5 er det ikke al for stor en skat at bruge en halv time p\u00e5 det en gang om ugen.<\/em> <\/p>\n<p><\/p>\n<p><em>Hvis du laver Continuous Integration 10 gange om dagen, skal du gange 10 med 30 minutter. Og det overstiger den arbejdsbyrde, som denne release manager har. Han bliver simpelthen tr\u00e6t af det. Der er faste omkostninger ved visse praksisser. Og det hele.<\/em> <\/p>\n<p><\/p>\n<p><em>Og du skal enten oph\u00e6ve denne regel, s\u00e5 du ikke besk\u00e6ftiger dig med s\u00e5dan noget fis, dvs. du tildeler ikke manuelt en grad af overensstemmelse fra noget til noget. Du stoler helt og holdent p\u00e5 et eller andet automatiseret testset til klarhed.<\/em> <\/p>\n<p><\/p>\n<p><em>Og hvis du har brug for nogen til at give dig et bevis, s\u00e5 chefen underskriver, og du ikke g\u00e5r ind i produktion uden at Vasja har sagt, at han giver tilladelse osv. \u2013 alt denne fis st\u00e5r i vejen for praksisser. Fordi hvis der er aktiviteter, der er forbundet som en skat, s\u00e5 bliver alt 100 gange sv\u00e6rere. Derfor vil et skift ofte ikke blive positivt modtaget af alle. Fordi det er sv\u00e6rt at \u00e6ndre folks vaner.<\/em> <\/p>\n<p><\/p>\n<p><em>N\u00e5r en person udf\u00f8rer sit s\u00e6dvanlige arbejde, g\u00f8r han det praktisk talt uden at t\u00e6nke over det. Den kognitive belastning er nul. Han arbejder blot p\u00e5 det f\u00e6rdige, han har allerede en tjekliste i hovedet, han har gjort dette tusind gange. Og s\u00e5 snart du kommer og siger til ham: \u00abLad os opsige denne praksis og fra mandag implementere en ny\u00bb, bliver det en stor kognitiv belastning for ham. Og denne belastning tr\u00e6der straks i kraft for alle.<\/em> <\/p>\n<p><\/p>\n<p><em>Derfor er det enkleste, men sandt, at ikke alle har r\u00e5d til denne luksus, men jeg g\u00f8r det altid s\u00e5dan. Hvis et nyt projekt starter, presses som regel alle uafpr\u00f8vede praksisser ind i dette projekt. Mens projektet stadig er ungt, risikerer vi ikke meget. Der er ingen produktion, der er ikke noget at \u00f8del\u00e6gge. S\u00e5 denne metode kan bruges som tr\u00e6ning. Denne tilgang virker. Men ikke alle virksomheder har mulighed for ofte at starte s\u00e5danne projekter. Selv om det ogs\u00e5 er lidt m\u00e6rkeligt, fordi der er masser af digital transformation lige nu, og alle b\u00f8r eksperimentere for at f\u00f8lge med konkurrenterne.<\/em> <\/p>\n<p><\/p>\n<p>Her st\u00f8der man p\u00e5 det faktum, at man f\u00f8rst skal have en forst\u00e5else af, hvad man skal g\u00f8re. Verden er ikke perfekt, produktion er heller ikke perfekt. <\/p>\n<p><\/p>\n<p><em>Ja, disse ting er indbyrdes forbundet.<\/em><\/p>\n<p><\/p>\n<p>Virksomheden har heller ikke altid en forst\u00e5else af, at de skal bev\u00e6ge sig i den retning. <\/p>\n<p><\/p>\n<p><em>Der er situationer, hvor ingen \u00e6ndringer er mulige overhovedet. Det er en situation, hvor teamet oplever st\u00f8rre pres. Teamet er allerede temmelig udbr\u00e6ndt. De har ikke noget overskud af tid til eksperimenter. De arbejder fra morgen til aften med at udvikle funktioner. Og ledelsen kr\u00e6ver stadig flere funktioner. Der kr\u00e6ves mere og mere. I en s\u00e5dan situation er der overhovedet ikke mulighed for nogen \u00e6ndringer. Teamet kan kun f\u00e5 besked p\u00e5, at i morgen skal vi g\u00f8re som i g\u00e5r, vi skal bare lave lidt flere funktioner. Ingen overgange til nogen praksisser er i denne forstand mulige. Det er en klassisk situation, hvor der ikke er tid til at slibe \u00f8ksen, man skal f\u00e6lde tr\u00e6er, og derfor f\u00e6lder man med en stump \u00f8kse. Her er der ingen nemme l\u00f8sninger.<\/em> <\/p>\n<p><\/p>\n<p><em>(Dmitry) Jeg vil l\u00e6se en pr\u00e6cisering fra chatten: \"Men der er behov for stor testd\u00e6kning p\u00e5 forskellige niveauer. Hvor meget tid bruges der p\u00e5 tests? Det virker lidt dyrt og tager meget tid.\"<\/em><\/p>\n<p><\/p>\n<p><em>(Oleg) Det er en klassisk misforst\u00e5else. Der skal v\u00e6re tilstr\u00e6kkeligt med tests, s\u00e5 du selv har tillid. Continuous Integration er ikke s\u00e5dan noget, hvor 100 % af tests skal v\u00e6re klar, f\u00f8r du begynder at anvende denne praksis. Continuous Integration reducerer din kognitive belastning, fordi hver \u00e6ndring, du kan se, er s\u00e5 \u00e5benlys, at du forst\u00e5r, om den vil bryde noget eller ej, selv uden tests. Du kan hurtigt teste det mentalt, fordi \u00e6ndringerne er sm\u00e5. Selv hvis du kun har manuelle testere, er det ogs\u00e5 lettere for dem. Du ruller det ud og siger: \"Tjek, er der noget, der er brudt?\" De tjekker og siger: \"Nej, der er ikke brudt noget.\" Fordi testeren ved, hvor de skal se. Du har \u00e9n commit, der er relateret til \u00e9t stykke kode. Og det eksploderer med en bestemt opf\u00f8rsel.<\/em><\/p>\n<p><\/p>\n<p>Her har du selvf\u00f8lgelig lidt pyntet p\u00e5 det. <\/p>\n<p><\/p>\n<p><em>(Dmitry) Her er jeg ikke enig. Der findes en praksis \u2013 testdrevet udvikling, som netop kan redde dig fra dette.<\/em> <\/p>\n<p><\/p>\n<p><em>(Oleg) Jeg er ikke n\u00e5et dertil endnu. Den f\u00f8rste illusion er, at man skal skrive 100 % tests eller slet ikke besk\u00e6ftige sig med Continuous Integration. Det er forkert. Det er to parallelle praksisser. Og de afh\u00e6nger ikke direkte af hinanden. Din testd\u00e6kning skal v\u00e6re optimal. Optimal betyder, at du selv er sikker p\u00e5, at den kvalitet, som din master har efter commit, giver dig tillid til at trykke p\u00e5 \"Deploy\"-knappen fredag aften, selv n\u00e5r du er p\u00e5virket. Hvordan n\u00e5r du dertil? Gennem review, gennem d\u00e6kning, gennem god overv\u00e5gning.<\/em> <\/p>\n<p><\/p>\n<p><em>God overv\u00e5gning er ikke til at skelne fra tests. Hvis du k\u00f8rer tests \u00e9n gang p\u00e5 pre prod, s\u00e5 tjekker de alle dine bruger-scenarier \u00e9n gang og s\u00e5 er det det. Men hvis du k\u00f8rer dem i en uendelig l\u00f8kke, er det dit udvidede overv\u00e5gningssystem, der konstant tester \u2013 om systemet er nede eller ej. I dette tilf\u00e6lde er forskellen kun i engangs- eller gentagne tests. Et meget godt s\u00e6t tests\u2026, der k\u00f8res uendeligt, er egentlig overv\u00e5gning. Og korrekt overv\u00e5gning skal v\u00e6re s\u00e5dan.<\/em> <\/p>\n<p><\/p>\n<p><em>Og derfor, hvordan du pr\u00e6cist n\u00e5r til den tilstand, hvor du deployer fredag aften og s\u00e5 g\u00e5r hjem, er et andet sp\u00f8rgsm\u00e5l. M\u00e5ske er du bare en modig skr\u00e6dder.<\/em> <\/p>\n<p><\/p>\n<p>Lad os g\u00e5 lidt tilbage til Continuous Integration. Vi er tr\u00e5dt ind i en anden kompleks praksis. <\/p>\n<p><\/p>\n<p><em>Og den anden illusion er, at MVP'en, det siges, skal laves hurtigt, og derfor er tests slet ikke n\u00f8dvendige. Det er ikke helt korrekt. N\u00e5r du skriver user stories til din MVP, kan du lave dem enten p\u00e5 en impulsiv m\u00e5de, dvs. h\u00f8re om en user story og straks begynde at kode den, eller arbejde efter TDD. Og if\u00f8lge erfaringerne fra TDD tager det ikke l\u00e6ngere tid, s\u00e5 tests er bare et biprodukt. TDC-praksis handler ikke om at teste. Selvom det kaldes Test Driven Development, omhandler det slet ikke tests. Det er snarere en arkitektonisk tilgang. Det handler om, hvordan man skriver det, der er n\u00f8dvendigt, og ikke skriver det, der ikke er n\u00f8dvendigt. Denne praksis fokuserer p\u00e5 den n\u00e6ste iteration af din tankegang i forhold til at skabe appens arkitektur.<\/em> <\/p>\n<p><\/p>\n<p><em>Derfor er det ikke s\u00e5 let at slippe af med disse illusioner. MVP og tests mods\u00e6tter ikke hinanden. Tv\u00e6rtimod, hvis du laver din MVP efter TDD-praksis, vil du g\u00f8re det bedre og hurtigere, end hvis du g\u00f8r det uden praksis, p\u00e5 impuls.<\/em><\/p>\n<p><\/p>\n<p>Det er en meget uheldig og kompleks tanke. N\u00e5r du h\u00f8rer, at jeg nu ogs\u00e5 skal skrive tests og alligevel vil g\u00f8re noget hurtigere, lyder det helt usandsynligt. <\/p>\n<p><\/p>\n<p><em>(Dmitry) Mange, n\u00e5r de taler om MVP, er bare for dovne til at skrive noget ordentligt. Og det er trods alt forskellige ting. Man skal ikke g\u00f8re MVP til noget d\u00e5rligt, der ikke fungerer.<\/em> <\/p>\n<p><\/p>\n<p>Ja, du har ret.<\/p>\n<p><\/p>\n<p><em>Og s\u00e5 pludselig MVP i produktion.<\/em><\/p>\n<p><\/p>\n<p>For altid. <\/p>\n<p><\/p>\n<p>Og TDD lyder meget uvant, n\u00e5r man h\u00f8rer, at du skriver tests, og tilsyneladende laver mere arbejde. Det lyder meget m\u00e6rkeligt, men i virkeligheden g\u00e5r det hurtigere og ser bedre ud. N\u00e5r du skriver en test, t\u00e6nker du allerede meget over, hvilken kode der skal bruges, hvordan den vil blive kaldt, og hvilken adf\u00e6rd vi forventer af den. Du siger ikke bare, at jeg har skrevet en funktion, og den g\u00f8r noget. Du overvejer f\u00f8rst, hvilke betingelser den har, og hvordan den vil blive kaldt. Du d\u00e6kker det med tests, og ud fra dette forst\u00e5r du, hvordan dine interfaces i koden vil se ud. Det har en stor indflydelse p\u00e5 arkitekturen. Din kode bliver automatisk mere modul\u00e6r, fordi du f\u00f8rst pr\u00f8ver at forst\u00e5, hvordan du vil teste den, og f\u00f8rst derefter skriver du den. <\/p>\n<p><\/p>\n<p>Jeg har haft det s\u00e5dan med TDD, at jeg p\u00e5 et tidspunkt hyrede en mentor til Ruby, da jeg stadig var Ruby-udvikler. Og han sagde: \u201eLad os g\u00f8re det med TDD.\u201d Jeg t\u00e6nkte: \u201e\u00c5h nej, skal jeg skrive noget ekstra.\u201d Vi blev enige om, at jeg i l\u00f8bet af to uger skulle skrive al min funktionelle kode p\u00e5 Python med TDD. Efter to uger inds\u00e5 jeg, at jeg ikke ville tilbage. Efter at have fors\u00f8gt at anvende det overalt i to uger, forst\u00e5r man, hvor meget lettere det er at t\u00e6nke klart. Men det er ikke indlysende, s\u00e5 jeg anbefaler alle, at hvis I f\u00f8ler, at TDD er kompliceret, tidskr\u00e6vende og un\u00f8dvendigt, s\u00e5 pr\u00f8v at holde fast i det i bare to uger. To uger var tilstr\u00e6kkeligt for mig.<\/p>\n<p><\/p>\n<p><em>(Dmitrij) Vi kan udfolde denne tanke fra et perspektiv af infrastrukturdrift. F\u00f8r vi starter noget nyt, udf\u00f8rer vi overv\u00e5gning og derefter lancerer vi. I dette tilf\u00e6lde bliver vores overv\u00e5gning en normal testning. Og der er udvikling gennem overv\u00e5gning. Men n\u00e6sten alle siger, at det er tidskr\u00e6vende, jeg orker ikke det, jeg lavede et midlertidigt udkast. Hvis vi udf\u00f8rer overv\u00e5gningen ordentligt, forst\u00e5r vi tilstanden af CI-systemet. Og der er meget overv\u00e5gning i CI-systemet. Vi forst\u00e5r systemets tilstand, vi forst\u00e5r, hvad der foreg\u00e5r inden i det. Og under udviklingen laver vi netop systemet, s\u00e5 det n\u00e5r den \u00f8nskede tilstand.<\/em> <\/p>\n<p><\/p>\n<p><em>Disse praksisser har v\u00e6ret kendt i lang tid. Vi diskuterede det for omkring 4 \u00e5r siden. Men p\u00e5 de 4 \u00e5r er der n\u00e6sten ikke sket nogen forandringer.<\/em> <\/p>\n<p><\/p>\n<p><em>Men p\u00e5 denne note vil jeg foresl\u00e5, at vi afslutter den officielle diskussion.<\/em><\/p>\n<p><\/p>\n<p>Video (indsat som et medieelement, men af en eller anden grund fungerer det ikke):<\/p>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/zZ3qXVN3Oic\">https:\/\/youtu.be\/zZ3qXVN3Oic<\/a><\/noindex><br \/>\n<br \/>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/518406\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041e\u0431\u0441\u0443\u0434\u0438\u043c \u043f\u043e\u0447\u0435\u043c\u0443 CI-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438 CI \u2013 \u044d\u0442\u043e \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u043e \u0440\u0430\u0437\u043d\u043e\u0435. \u041a\u0430\u043a\u0443\u044e \u0431\u043e\u043b\u044c CI \u043f\u0440\u0438\u0437\u0432\u0430\u043d\u043e \u0440\u0435\u0448\u0438\u0442\u044c, \u043e\u0442\u043a\u0443\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u0438\u0434\u0435\u044f, \u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0447\u0442\u043e \u043e\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u043f\u043e\u043d\u044f\u0442\u044c \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u0430 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 Jenkins. \u041c\u044b\u0441\u043b\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u043e\u043a\u043b\u0430\u0434 \u043f\u0440\u043e Continuous Integration \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0435\u0449\u0435 \u0433\u043e\u0434 \u043d\u0430\u0437\u0430\u0434, \u043a\u043e\u0433\u0434\u0430 \u044f \u0445\u043e\u0434\u0438\u043b \u043f\u043e \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u043c \u0438\u0441\u043a\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0443. \u041f\u043e\u043e\u0431\u0449\u0430\u043b\u0441\u044f [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":93886,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-93885","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=\"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\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov\" \/>\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\udd47Continuous Integration \u043a\u0430\u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u0430 \u043d\u0435 Jenkins. \u0410\u043d\u0434\u0440\u0435\u0439 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u043e\u0432 | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov\" \/>\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=\"2020-09-10T17:42:23+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-09-10T17:42:23+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\udd47Continuous Integration som praksis, ikke Jenkins. Andrey Alexandrov | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov","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\udd47Continuous Integration \u043a\u0430\u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u0430 \u043d\u0435 Jenkins. \u0410\u043d\u0434\u0440\u0435\u0439 \u0410\u043b\u0435\u043a\u0441\u0430\u043d\u0434\u0440\u043e\u0432 | ProHoster","og:url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/continuous-integration-kak-praktika-a-ne-jenkins-andrej-aleksandrov","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":"2020-09-10T17:42:23+00:00","article:modified_time":"2020-09-10T17:42:23+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"93885","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 11:37:31","updated":"2022-09-27 15:57:30","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\/93885","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=93885"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/93885\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/93886"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=93885"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=93885"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=93885"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}