Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Discutiamo perché gli strumenti CI e CI siano davvero due cose diverse.

Quale problema il CI mira a risolvere, da dove è nata l'idea, quali sono le ultime conferme che funziona, come capire se avete davvero una pratica e non solo un Jenkins installato.

L'idea di fare una presentazione sul Continuous Integration è nata un anno fa, quando andavo a colloqui per cercare lavoro. Ho parlato con 10-15 aziende, e solo una è riuscita a rispondere chiaramente a cosa sia il CI e a spiegare come hanno capito di non averlo. Le altre dicevano delle sciocchezze incomprensibili su Jenkins 🙂 'Beh, abbiamo Jenkins, fa delle build, quindi è CI!' Nella presentazione cercherò di spiegare cosa sia davvero il Continuous Integration e perché Jenkins e strumenti simili hanno una relazione molto debole con questo.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Quindi, cosa viene normalmente in mente quando si parla di CI? La maggior parte delle persone penserà a Jenkins, Gitlab CI, Travis, ecc.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Anche se facciamo una ricerca su Google, ci verranno mostrati questi strumenti.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Se chiedi se sono familiari, subito dopo aver elencato gli strumenti ti diranno che il CI è quando in un Pull Request la build e i test vengono eseguiti su un commit.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

L'integrazione continua non riguarda gli strumenti, né le build con test nei branch! L'integrazione continua è una pratica di integrazione molto frequente del nuovo codice e non è affatto necessario costruire Jenkins, GitLab, ecc.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Prima di capire come appare un CI completo, immergiamoci nel contesto delle persone che lo hanno inventato e nelle difficoltà che cercavano di risolvere.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

E la difficoltà che volevano risolvere era la collaborazione all'interno del team!

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Diamo un'occhiata a esempi di quali difficoltà affrontano gli sviluppatori durante lo sviluppo in team. Abbiamo un progetto, un branch master in git e due sviluppatori.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

E iniziarono a lavorare come tutti sono abituati a fare. Prendono un compito in Jira, creano un branch di funzionalità e scrivono codice.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Uno ha completato la funzionalità più velocemente e ha fatto il merge nel master.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

L'altro ha impiegato più tempo, ha fatto il merge dopo e ha ottenuto un conflitto. Ora, invece di scrivere le funzionalità necessarie per il business, lo sviluppatore spende il suo tempo e le sue energie a risolvere conflitti.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Più è complicato integrare la tua funzione con il master generale, più tempo ci impieghiamo. E questo è solo un esempio piuttosto semplice. È un caso in cui ci sono solo 2 sviluppatori. E immagina se 10, 15 o 100 persone in un'azienda scrivono in un unico repository. Andresti fuori di testa a risolvere tutti questi conflitti.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

C'è un caso leggermente diverso. Abbiamo un master e diversi sviluppatori che stanno lavorando su qualcosa.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Hanno creato un branch ciascuno.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Uno si è fuso, tutto bene, ha completato il compito.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Nel frattempo, il secondo sviluppatore ha completato il suo compito. Supponiamo che lo abbia inviato per una revisione. In molte aziende c'è la pratica della revisione. Da un lato, è una buona e utile pratica, dall'altro, ci rallenta in molti aspetti. Non approfondiamo questo, ma ecco un ottimo esempio di come una storia complicata riguardo alla revisione possa portare a problemi. Hai inviato una pull request per la revisione. Lo sviluppatore non ha altro da fare. Cosa inizia a fare? Inizia a prendere altri compiti.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Nel frattempo, il secondo sviluppatore ha fatto qualcos'altro.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Il primo ha completato il terzo compito.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

E dopo un certo periodo di tempo, la sua revisione è stata provata e sta cercando di unirsi. E cosa succede? Incontra un enorme numero di conflitti. Perché? Perché mentre la sua pull request era in revisione, nel codice erano già avvenuti molti cambiamenti.

Oltre alla questione dei conflitti, c'è anche la questione della comunicazione. Mentre la vostra branch è in revisione, mentre aspetta qualcosa, mentre avete impiegato molto tempo a sviluppare una funzionalità, smettete di monitorare cosa sta cambiando nella base di codice del vostro servizio. È possibile che quello che state cercando di risolvere sia già stato risolto ieri, e potreste riprendere e riutilizzare qualche metodo. Ma non lo vedrete, perché state sempre lavorando con una branch obsoleta. E questa branch obsoleta porta sempre al fatto che dovrete risolvere conflitti di merging.

Quindi, se lavoriamo in team, cioè se non è una sola persona a lavorare nel repository, ma 5-10 persone, quanto più a lungo aspettiamo a aggiungere il nostro codice nel master, tanto più soffriamo nel dover unire qualcosa alla fine. E quanto più conflitti abbiamo, e con una versione più vecchia stiamo lavorando, tanto più problemi abbiamo.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Collaborare può essere doloroso! Ci intralciamo sempre a vicenda.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Questo problema è stato notato più di 20 anni fa. Il primo riferimento alla pratica della Continuous Integration l'ho trovato nell'Extreme Programming.

L'Extreme Programming è il primo framework agile. La pagina è apparsa nel 1996. L'idea era di utilizzare alcune pratiche di programmazione, pianificazione e altro, affinché lo sviluppo fosse il più flessibile possibile, così da poter reagire più rapidamente ai cambiamenti e alle richieste dei nostri clienti. E 24 anni fa hanno iniziato a riscontrare che se si fa qualcosa per molto tempo in modo isolato, si spende più tempo a causa dei conflitti.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Ora analizzeremo l'espressione 'Continuous Integration' parola per parola. Se tradotta letteralmente, si ottiene 'integrazione continua'. Ma non è chiaro quanto sia continua, è piuttosto intermittente. E quanto sia 'integrazione' non è molto ovvio.

Ecco perché vi mostro ora citazioni dall'Extreme Programming. Analizzeremo entrambe le parole separatamente.

Integrazione — Come ho già detto, puntiamo a far sì che ogni ingegnere lavori con l'ultima versione del codice, cercando di integrare il proprio codice nel branch principale il più frequentemente possibile, in modo che siano piccoli branch. Questo perché se sono grandi, possiamo facilmente rimanere bloccati per una settimana a causa di conflitti di merge. Soprattutto se abbiamo un lungo ciclo di sviluppo come il waterfall, dove un sviluppatore è assente per un mese a lavorare su una grande funzionalità. E nella fase di integrazione può rimanere bloccato a lungo.

L'integrazione è quando prendiamo il nostro branch e lo integriamo con il master, lo uniamo. C'è una versione ultimativa, quando siamo transbase developer, dove puntiamo a scrivere direttamente nel master senza rami superflui.

In generale, l'integrazione significa prendere il proprio codice e portarlo nel master.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Cosa si intende per «continuous» e cosa significa continuità? La pratica implica che lo sviluppatore cerca di integrare il proprio codice il prima possibile. Questo è il suo obiettivo in ogni attività: fare in modo che il suo codice arrivi nel master il più rapidamente possibile. In un mondo ideale, gli sviluppatori lo farebbero ogni poche ore. Cioè, prendi un piccolo compito e lo unisci al master. Tutto va alla grande. Questo è ciò a cui aspiri. E deve essere fatto in modo continuo. Non appena hai fatto qualcosa, la metti subito nel master.

E lo sviluppatore che fa qualcosa è responsabile di ciò che ha fatto affinché funzionasse e non rompesse nulla. Qui emerge solitamente la questione dei test. Vogliamo eseguire alcuni test sul nostro commit, sul nostro merge, per assicurarci che funzioni. E qui Jenkins può davvero aiutarti.

Ma con le storie: perché non facciamo cambiamenti piccoli? E perché non affrontiamo piccole sfide? E perché non portiamo subito una sfida nel master? Qui, nessun Jenkins può aiutarti. Perché Jenkins ti aiuterà solo a eseguire i test.

Puoi farne a meno. Non ti darà alcun fastidio. Perché l'obiettivo della pratica è quello di unirsi il più spesso possibile, per non perdere moltissimo tempo su eventuali conflitti in futuro.

Immagina che nel 2020 per qualche motivo non ci sia internet. E stiamo lavorando localmente. Non abbiamo Jenkins. Va bene. Puoi comunque creare un ramo locale. Hai scritto del codice in questo ramo. Hai completato una sfida in 3-4 ore. Sei tornato al master, hai eseguito un git pull e hai unito il tuo ramo lì. Fatto. Se lo fai spesso, congratulazioni, hai l'integrazione continua!

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Quali prove esistono oggi nel mondo moderno che giustifichino di investire energie in questo? Perché in generale è una cosa difficile. Se provi a lavorare in questo modo, capirai che dovrai affrontare una pianificazione, dovrai dedicare più tempo alla scomposizione delle attività. Se continui a lavorare come man..., non potrai fondere rapidamente e, di conseguenza, ti ritroverai nei guai. Non avrai più pratiche.

E questo sarà costoso. Non sarà possibile iniziare a lavorare con Continuous Integration da domani. Tutti voi impiegherete molto tempo ad abituarvi, molto tempo a imparare a scomporre le attività, e molto tempo a rivedere la pratica del review, se ne avete una. Perché il nostro obiettivo è di fonderlo oggi. Se passi tre giorni per fare la revisione, hai dei problemi e non riuscirai a implementare Continuous Integration.

Ma abbiamo alcune prove attuali ora stesso che ci dicono che investire in questa pratica ha senso?

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

La prima cosa che mi è venuta in mente è il State of DevOps. È uno studio che i ragazzi conducono da 7 anni. Adesso lo fanno come organizzazione indipendente, ma sotto Google.

E la loro ricerca nel 2018 ha mostrato una correlazione tra le aziende che cercano di utilizzare rami a breve termine, che si integrano rapidamente e frequentemente, e che presentano performance IT migliori.

Quali sono queste metriche? Sono 4 metriche che raccolgono da tutte le aziende nei loro questionari: frequenza di distribuzione, tempo necessario per le modifiche, tempo per il ripristino del servizio, tasso di failure delle modifiche.

Innanzitutto, c'è questa correlazione: sappiamo che le aziende che effettuano merge frequentemente hanno queste metriche significativamente migliori. Inoltre, esiste una suddivisione delle aziende in diverse categorie: ci sono le aziende lente, quelle a performance media, le alte performer e l'élite. L'élite include Netflix e Amazon, che sono superveloci, fanno tutto in modo rapido, elegante e di qualità.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

La seconda storia è avvenuta solo un mese fa. Nel Technology Radar è apparso un interessante articolo su Gitflow. Gitflow si distingue da tutti gli altri perché i suoi rami vivono a lungo. Ci sono rami di rilascio che vivono a lungo e rami di funzionalità che vivono anch'essi a lungo. Questa pratica nel Technology Radar è stata spostata in HOLD. Perché? Perché le persone incontrano difficoltà nell'integrazione.

Se una tua branch rimane attiva a lungo, si inceppa, marcisce e iniziamo a spendere più tempo per apportare modifiche.

Di recente l'autore di Gitflow ha detto che se miri al Continuous Integration e vuoi rilasciare nuove versioni il più spesso possibile, allora Gitflow è una cattiva idea. Ha anche aggiunto in un articolo che, se hai un backend che ti permette di aspirare a questo, allora Gitflow è superfluo, perché ti rallenterà e ti creerà problemi di integrazione.

Questo non significa che Gitflow sia cattivo e che tu non debba usarlo. È utile in altri casi. Ad esempio, quando hai bisogno di supportare più versioni di un servizio o di un'applicazione, ovvero quando devi mantenere il supporto per un lungo periodo di tempo.

Ma se parli con persone che supportano questi servizi, sentirai molte lamentele riguardo al fatto che la versione 3.2 è stata rilasciata 4 mesi fa e che non includeva questa correzione, e ora, per apportarla, è necessario fare un sacco di modifiche. Così, di nuovo, si sono bloccati e ci stanno lavorando da una settimana per cercare di fondere una nuova funzionalità.

Come ha giustamente osservato Aleksandr Kovalev in chat, la correlazione non è la stessa cosa della causalità. È così. Cioè, non c'è una connessione diretta che se hai Continuous Integration, allora tutte le metriche saranno eccellenti. Ma c'è una correlazione positiva: se una cosa vale, è probabile che valga anche l'altra. Non è un dato certo, ma è probabile. Questa è solo una correlazione.

Continuous Integration come pratica, non Jenkins. Andrey Alexandrov

Sembra che stiamo già facendo qualcosa, sembra che stiamo già facendo merge, ma come possiamo capire se abbiamo veramente Continuous Integration e se facciamo merge con sufficiente frequenza?

Jez Humble è l'autore del Handbook, Accelerate, del sito Continuous Delivery e del libro "Continuous Delivery". Propone un test del genere:

  • Il codice dell'ingegnere viene inserito nel master ogni giorno.
  • Per ogni commit si eseguono i test unitari.
  • Se il build nel master fallisce, viene riparato in circa 10 minuti.

Propone di utilizzare questo test per assicurarsi che la pratica esista realmente nel tuo processo.

L'ultima parte mi sembra un po' controversa. Cioè, se puoi risolvere il problema in 10 minuti, significa che hai una Continuous Integration, il che suona un po' strano a mio avviso, ma ha un senso. Perché? Perché se fai merge frequentemente, significa che le tue modifiche sono piccole. Se un piccolo cambiamento causa un malfunzionamento della build principale, sarai in grado di trovare l'errore rapidamente, perché la modifica è piccola. Hai fatto un piccolo merge, dove hai cambiato 20-30 righe. E, di conseguenza, puoi rapidamente capire qual è stato il problema, poiché le modifiche sono minime e la tua area di ricerca è molto ristretta.

E anche se dopo il rilascio il nostro ambiente di produzione si rompe, se abbiamo la pratica della Continuous Integration, è molto più facile agire, perché le modifiche sono piccole. Sì, questo influenzerà la pianificazione. Sarà difficile. E probabilmente, la parte più difficile di questa pratica è abituarsi a suddividere i compiti, cioè come fare per prendere qualcosa e realizzarlo in poche ore e allo stesso tempo superare la revisione, se la hai. La revisione è un dolore a parte.

I test unitari sono solo un supporto che ti aiuta a capire se la tua integrazione è andata a buon fine e se non si è rotto nulla. A mio avviso, non è nemmeno un punto obbligatorio, perché il senso della pratica non è questo.

Questo è un breve riepilogo dell'Integrazione Continua. È tutto ciò che c'è in questa pratica. Sono pronto per le domande.

Ricapitolo brevemente:

  • L'Integrazione Continua non è Jenkins, non è Gitlab.
  • Non è uno strumento, è una pratica che implica unire il nostro codice nel master il più spesso possibile.
  • Lo facciamo per evitare il grande dolore che si verifica con le fusioni in futuro, cioè proviamo un piccolo dolore ora per evitare un grande dolore in seguito. Questo è il senso.
  • Dalla parte si verifica comunicazione attraverso il codice, ma lo vedo molto raramente, ma è stato anche ideato per questo.

Domande

Cosa fare con i compiti non decostruiti?

Decostruirli. Qual è il problema? Puoi fare un esempio, che c'è un compito e non si decostruisce?

Ci sono compiti che non possono essere decomposti, come quelli che richiedono una profonda expertise e possono richiedere mesi prima di raggiungere un risultato accettabile.

Se ho capito bene, c'è un compito grande e complesso il cui risultato sarà visibile solo fra un mese?

Sì, corretto. Il risultato potrà essere valutato non prima di un mese.

Va bene. In generale non è un problema. Perché? Perché in questo caso, quando parliamo di rami, non ci riferiamo a un ramo con una funzionalità. Le funzionalità possono essere grandi e complesse. Possono coinvolgere molti componenti. Ed è possibile che non possiamo completarle in un solo ramo. Va bene così. Dobbiamo semplicemente scomporre questa storia. Se la funzionalità non è completamente pronta, questo non significa che alcuni pezzi del suo codice non possano essere uniti. Hai aggiunto, ad esempio, una migrazione e all'interno della funzionalità ci sono alcuni passaggi. Hai, ad esempio, un passaggio: fare la migrazione, aggiungere un nuovo metodo. E puoi già unire queste cose quotidianamente.

Va bene. Qual è dunque il senso di tutto ciò?

Qual è il senso di unire piccole parti ogni giorno?

Sì.

Se hanno rotto qualcosa, lo vedi subito. Hai un piccolo pezzo che ha causato un problema, quindi è più facile da risolvere. Il senso è che unire un piccolo pezzo ora è molto più semplice che unire qualcosa di grande tra qualche settimana. E un terzo motivo è che altri ingegneri lavoreranno già con la versione attuale del codice. Vedranno che ci sono alcune migrazioni aggiunte e che è apparso un metodo che potrebbero voler utilizzare. Tutti vedranno cosa sta succedendo nel tuo codice. È proprio per queste tre cose che si fa questa pratica.

Grazie, la questione è chiusa!

(Oleg Soroka) Posso aggiungere qualcosa? Hai detto tutto giustamente, voglio solo aggiungere una frase.

Va bene.

Con Continuous Integration, il codice viene inserito nel ramo principale non quando una caratteristica è completamente pronta, ma quando il build smette di rompersi. Puoi fare commit nel master quante volte vuoi al giorno. Il secondo aspetto è che se per qualche motivo non riesci a dividere un compito mensile in attività di almeno tre giorni, senza parlare di tre ore, allora hai un enorme problema. Il fatto che non hai Continuous Integration è il minore di questi problemi. Significa che hai problemi con l'architettura e le pratiche ingegneristiche sono ai minimi storici. Anche se si tratta di ricerca, in ogni caso deve essere formulato sotto forma di ipotesi o cicli.

Abbiamo parlato di 4 metriche che distinguono le aziende di successo da quelle in ritardo. Prima di arrivare a queste 4 metriche, bisogna sopravvivere. Se una tua attività richiede un mese, mi concentrei prima su questa metrica. La ridurrei a 3 giorni. Solo allora inizierei a pensare al Continuous.

Ho capito correttamente che pensi che non abbia senso investire in pratiche ingegneristiche se qualsiasi attività richiede un mese?

Hai a disposizione l'integrazione continua. C'è un aspetto per cui in 10 minuti puoi riparare un problema oppure fare il rollback. Immagina di averlo rilasciato. In più hai anche il continuous deployment, l'hai rilasciato in produzione e solo dopo ti rendi conto che qualcosa è andato storto. Devi fare il rollback, ma a quel punto hai già eseguito la migrazione del database. Hai già la struttura del database della versione successiva, e inoltre è passato anche un backup, e sono stati registrati dei dati.

Qual è la tua alternativa? Se fai il rollback del codice, non può più funzionare con questo database aggiornato.

Il database avanza solo in avanti, sì.

Le persone con una scarsa pratica ingegneristica probabilmente non hanno nemmeno letto un grosso libro su ... Cosa fare con il backup? Se ti ripristini da un backup, significa che perdi i dati accumulati nel frattempo. Ad esempio, hai lavorato per tre ore con la nuova versione del database e gli utenti si sono registrati. Torni a un vecchio backup perché con la nuova versione la struttura non funziona, quindi hai perso quegli utenti. E loro sono scontenti, si lamentano.

Per padroneggiare l'intera gamma di pratiche che supportano il Continuous Integration e il Continuous Delivery, non basta imparare a scrivere semplicemente... Innanzitutto, potrebbero diventare troppe, risultando così poco pratiche. Inoltre, ci sono molte altre pratiche come Scientific. Ce n'è una che GitHub ha popolarizzato un po' di tempo fa. È un approccio in cui il vecchio codice e il nuovo codice vengono eseguiti contemporaneamente. Significa che realizzi una funzionalità incompleta, ma che può restituire un valore: sia come funzione, sia come Rest API. Esegui sia il nuovo che il vecchio codice, e confronti la differenza tra di essi. Se c'è una differenza, la registri come evento. In questo modo, sai che la tua nuova funzionalità è pronta per essere implementata sopra la vecchia, a patto che non ci siano stati scostamenti tra questi due nel corso di un determinato periodo di tempo.

Ci sono centinaia di tali pratiche. Ti suggerirei di iniziare con lo sviluppo transbase. Non è al 100% su Continuous Integration, ma le pratiche sono le stesse; uno vive male senza l'altro.

Hai citato lo sviluppo transbase come esempio per dove si possono vedere le pratiche, o stai suggerendo alle persone di iniziare a utilizzare lo sviluppo transbase?

Guarda, poiché non riusciranno a utilizzarli. Per poterli utilizzare, è necessario leggere molto. E quando una persona si chiede: «Cosa fare con una funzionalità che richiede un mese?», significa che non ha letto nulla riguardo allo sviluppo di transbase. Non lo consiglierei ancora. Suggerirei di concentrarsi esclusivamente sul tema di come suddividere architettonicamente compiti complessi in compiti più piccoli. Questa è l'essenza della decomposizione.

La decomposizione è uno degli strumenti dell'architetto. Prima facciamo un'analisi, poi la decomposizione, quindi la sintesi, e infine l'integrazione. In questo modo, tutto si compone. E per arrivare alla Continuous Integration, dobbiamo prima passare attraverso la decomposizione. Durante la prima fase sorgono domande, e noi già parliamo della quarta fase, cioè, più frequentemente facciamo integrazioni, meglio è. È ancora presto per farlo; sarebbe opportuno prima migliorare il proprio monolite.

È necessario disegnare alcune frecce e quadrati su un diagramma. Non puoi dire che ora mostrerò lo schema architettonico della nuova applicazione e far vedere solo un quadrato con all'interno un pulsante verde per l'app. In ogni caso, ci saranno più quadrati e frecce. In qualsiasi schema io abbia visto, ce ne erano più di uno. E la decomposizione, anche a livello di rappresentazione grafica, è già in atto. Pertanto, i quadrati possono essere indipendenti. Se non lo sono, ho molte domande per l'architetto.

C'è una domanda dalla chat: «Se la revisione è obbligatoria e richiede tempo, quindi un giorno o più?».

Hai problemi con la pratica. Non dovrebbe passare un giorno o più per una revisione. È la stessa storia della domanda precedente, solo un po' più morbida. Se la revisione dura un giorno, significa che probabilmente si tratta di una revisione di un cambiamento molto grande. Dobbiamo quindi ridurlo. Nel transbase development, che Oleg ha raccomandato, c'è un concetto chiamato revisione continua. L'idea è che facciamo pull request così piccoli intenzionalmente, perché puntiamo a fondere costantemente e poco alla volta. E quindi il pull request cambia una sola astrazione o 10 righe. Grazie a questo, la revisione ci richiede solo qualche minuto.

Se una revisione richiede un giorno o più, significa che c'è qualcosa che non va. Innanzitutto, potrebbe esserci un problema con l'architettura. Potrebbe anche essere un grande blocco di codice, per esempio, di 1.000 righe. Oppure hai un'architettura così complessa che nessuno riesce a comprenderla. Questo è un problema secondario, ma anche quello dovrà essere affrontato. Forse non è neanche necessaria una revisione. È qualcosa su cui riflettere. La revisione è un freno. Porta dei benefici nel complesso, ma bisogna capire perché la stai facendo. È un modo per trasferire informazioni rapidamente? È un modo per stabilire degli standard interni? Perché hai bisogno di farla? Poiché la revisione deve essere fatta molto rapidamente o addirittura annullata. È un po' come lo sviluppo di transbase: una storia molto bella, ma adatta solo per chi ha già esperienza.

Per quanto riguarda le 4 metriche, consiglierei di ottenerle per capire a cosa portano. Dare un'occhiata ai numeri, vedere l'immagine, quanto sia critica la situazione.

(Dmitry) Sono pronto a discutere questo argomento con te. Le cifre e le metriche sono tutte fantastiche, le pratiche sono fantastiche. Ma dobbiamo capire se questo è necessario per il business. Ci sono aziende che non hanno bisogno di un cambiamento così rapido. Conosco aziende in cui non è possibile apportare modifiche ogni 15 minuti. E non perché siano cattive. È solo un ciclo di vita. Per realizzare funzionalità come branches e toggle, sono necessarie conoscenze approfondite.

È complicato. Se vuoi leggere di più sulla storia del toggle delle funzionalità, te lo consiglio vivamente. https://trunkbaseddevelopment.com/. E c'è un ottimo articolo di Martin Fowler sul toggle delle funzionalità: sui diversi tipi, i cicli di vita, ecc. Il toggle delle funzionalità è complesso.

E comunque non hai risposto alla domanda: «Jenkins è necessario o non è necessario?»

Jenkins non è realmente necessario in alcun caso. Seriamente, strumenti come Jenkins e GitLab vi offriranno comodità. Potete vedere se la build è andata a buon fine o meno. Possono esservi utili, ma non vi forniranno vere pratiche. Possono solo darvi un pallino – Ok o Non Ok. E questo, se scrivete ancora dei test, perché se non ci sono test, è quasi senza senso. Quindi è utile, perché è più comodo, ma in generale si può anche vivere senza, non perderete molto.

Cioè, se avete pratiche, significa che non vi serve?

Esatto. Raccomando il test di Jez Humble. Ho un atteggiamento ambivalente riguardo all'ultimo punto. Ma in generale, se avete queste tre cose, vi mergeate costantemente, eseguite test sui commit nel master e riparate rapidamente la build nel master, allora forse non avete bisogno di altro.

Mentre aspettiamo le domande dei partecipanti, ho una domanda. Abbiamo appena parlato di codice di prodotto. Ma hai utilizzato il codice infrastrutturale? È lo stesso tipo di codice, ha gli stessi principi e lo stesso ciclo di vita, oppure ci sono cicli di vita e principi diversi? Di solito, quando si parla di Continuous Integration e Development, si dimentica che c'è anche il codice infrastrutturale. E ultimamente, sta diventando sempre più rilevante. Dobbiamo quindi applicare tutte queste regole anche a quello?

Non è tanto che dobbiamo, sarebbe fantastico, perché semplificherebbe sicuramente le cose. Una volta che lavoriamo con il codice, non con script bash, ma con un codice solido.

Aspetta un attimo, lo script bash è anche questo un codice. Non toccare il mio vecchio amore.

Va bene, non calpesterò i tuoi ricordi. Io ho una certa avversione per bash. Si rompe in modo brutto e orrendo continuamente. E si guasta spesso in modo imprevedibile, per questo non lo amo molto. Ma va bene, supponiamo che tu abbia codice in bash. Forse non ne capisco abbastanza e ci sono dei buoni framework per il testing. Non sono aggiornato. E otteniamo gli stessi vantaggi.

Quando trattiamo l'infrastruttura come codice, ci troviamo di fronte agli stessi problemi degli sviluppatori. Qualche mese fa, mi sono trovato in una situazione in cui un collega mi ha inviato una pull request di 1.000 righe in bash. E ti fermi a fare la revisione per 4 ore. I problemi sono gli stessi. È sempre codice. E sempre collaborazione. Ci troviamo bloccati con la pull request e incontriamo gli stessi conflitti di merge dello stesso bash, per esempio.

Attualmente sto monitorando molto attivamente tutto questo per massimizzare la bellezza della programmazione dell'infrastruttura. Ho appena integrato Pulumi nella mia infrastruttura. È programmazione pura. È ancora più affascinante perché ho accesso a tutte le funzionalità del linguaggio di programmazione, cioè ho creato toggle belli nello stesso modo con le istruzioni if. Pertanto, la mia modifica è già nel master. Tutti la vedono. Gli altri ingegneri ne sono a conoscenza. Ha già avuto qualche impatto. Tuttavia, non è stato attivato per tutte le infrastrutture. È attivo solo per i miei ambienti di test, per esempio. Quindi, rispondendo di nuovo alla tua domanda, è necessario. Ci semplifica sicuramente la vita come ingegneri che lavorano con il codice.

Ci sono altre domande?

Ho una domanda. Voglio continuare la discussione con Oleg. In generale, penso che tu abbia ragione nel dire che se un compito richiede un mese, hai un problema con l'architettura, con l'analisi, la decomposizione, la pianificazione, ecc. Tuttavia, ho la sensazione che se inizi a vivere secondo il Continuous Integration, comincerai a risolvere i problemi di pianificazione, perché non potrai evitarli.

(Oleg) Sì, è tutto corretto. In termini di lavoro, questa pratica è paragonabile a qualsiasi altra seria pratica che modifica la cultura. La parte più difficile da superare sono le abitudini, specialmente quelle sbagliate. E se per implementare questa pratica è necessario un cambiamento significativo nelle abitudini degli altri: sviluppatori, management, responsabile della produzione, allora ti aspettano delle sorprese.

Quali sorprese potrebbero esserci? Supponiamo che tu abbia deciso di effettuare integrazioni più frequentemente. E queste integrazioni sono legate ad altre cose, ad esempio, artefatti. E nella tua azienda, ad esempio, esiste una politica secondo cui ogni artefatto deve essere in qualche modo registrato in un sistema di archiviazione degli artefatti. E questo richiede un certo tempo. La persona deve contrassegnare che, come release manager, ha testato questo artefatto per la sua prontezza per il deployment in produzione. Se questo richiede 5-10-15 minuti, ma effettui il deployment una volta alla settimana, allora investire mezz'ora una volta a settimana è un piccolo dazio.

Se stai facendo Continuous Integration 10 volte al giorno, allora devi moltiplicare 10 per 30 minuti. E questo supera il tempo lavorativo di quel release manager. Si stanca semplicemente a farlo. Ci sono costi fissi per alcune pratiche. E basta.

E devi o annullare questa regola, così non ti occupi più di queste cose illogiche, cioè non assegni manualmente il livello di conformità di qualcosa a qualcos'altro. Ti affidi completamente a un insieme automatizzato di test di prontezza.

E se hai bisogno di un'approvazione per far firmare il principale, e non entri in produzione senza che qualcuno ti dica che va bene, tutto questo ostacola le pratiche. Perché se ci sono attività legate a tasse, tutto si amplifica di cento volte. Quindi il cambiamento non sarà spesso accolto con gioia da tutti. È difficile cambiare le abitudini delle persone.

Quando una persona svolge un lavoro abituale, lo fa praticamente senza pensarci. Il suo carico cognitivo è pari a zero. Lavora seguendo un modello già pronto, ha una checklist nella mente, l'ha fatto mille volte. E non appena arrivi e gli dici: 'Annulliamo questa pratica e da lunedì implementiamo una nuova', per lui diventa un pesante carico cognitivo. E questo colpisce subito tutti.

Quindi la cosa più semplice, anzi, non tutti possono permettersi questo lusso, ma io faccio sempre esattamente così, ed ecco perché. Quando inizia un nuovo progetto, generalmente si inseriscono immediatamente in questo progetto tutte le pratiche non testate. Finché il progetto è giovane, non rischiamo molto. Non c'è ancora un ambiente di produzione, quindi non c'è nulla da rovinare. Pertanto, può essere usato come allenamento. Questo approccio funziona. Ma non tutte le aziende hanno la possibilità di avviare progetti del genere frequentemente. Anche se è un po' strano, perché adesso siamo in una continua trasformazione digitale e tutte devono avviare esperimenti per tenere il passo con i concorrenti.

Qui ti trovi di fronte al fatto che devi prima avere una comprensione di ciò che devi fare. Il mondo non è perfetto, nemmeno l'ambiente di produzione è perfetto.

Sì, queste cose sono collegate.

Le aziende non hanno sempre chiara l'idea che debbano andare da qualche parte.

Esiste una situazione in cui non è possibile apportare alcuna modifica. È una situazione in cui la pressione sul team è maggiore. Il team è già piuttosto bruciato. Non ha alcun margine di tempo per esperimenti. Lavorano dalla mattina alla sera su nuove funzionalità. E il management sembra non essere mai soddisfatto delle funzionalità. Serve sempre di più. In una tale situazione, non è possibile effettuare alcun cambiamento. Al team possono solo dire di continuare a lavorare come ieri, ma con un numero leggermente maggiore di funzionalità. Non è possibile passare a pratiche diverse in questo senso. È una situazione classica in cui non c'è tempo per affilare l'ascia, bisogna abbattere gli alberi, di conseguenza si abbattono con un'ascia smussata. Qui non ci sono consigli facili.

(Dmitriy) Leggerò un chiarimento dal chat: «Ma è necessario avere una buona copertura di test a diversi livelli. Quanto tempo viene dedicato ai test? È piuttosto costoso e richiede molto tempo».

(Oleg) È un comune errore. Devono esserci abbastanza test affinché tu stesso sia sicuro. L'integrazione continua non è qualcosa dove prima fai il 100% dei test e poi inizi a mettere in pratica. L'integrazione continua riduce il tuo carico cognitivo poiché ogni cambiamento che vedi è talmente ovvio che capisci se romperà qualcosa o meno, anche senza test. Puoi testarlo rapidamente nella tua testa perché le modifiche sono piccole. Anche se hai solo tester manuali, per loro è più semplice. Hai fatto il deployment e hai detto: «Guarda, non si è rotto niente?». Loro controllano e dicono: «No, non si è rotto niente». Perché il tester sa dove guardare. Hai un commit legato a un singolo frammento di codice. E questo esplode in un comportamento specifico.

Qui hai, ovviamente, un po' esagerato.

(Dmitry) Su questo non sono d'accordo. Esiste una pratica – lo sviluppo attraverso il testing, che ti salverà proprio da questo.

(Oleg) Non ci sono ancora arrivato. La prima illusione è che bisogna scrivere il 100% dei test o non occuparsi affatto dell'Integrazione Continua. Non è vero. Sono due pratiche parallele e non dipendono direttamente l'una dall'altra. La copertura dei test dovrebbe essere ottimale. Ottimale significa che siete certi che la qualità del master, rimasta dopo il vostro commit, vi permetta di cliccare con fiducia sul pulsante 'Deploy' venerdì sera, anche se siete un po' brilli. Come si ottiene tutto ciò? Attraverso le recensioni, la copertura, e un buon monitoraggio.

Un buon monitoraggio è indistinguibile dai test. Se eseguite i test una sola volta in pre-prod, essi controllano tutti i vostri casi d'uso una sola volta e basta. Ma se li eseguite in un ciclo infinito, allora questo diventa il vostro sistema di monitoraggio attivo che testa continuamente – se è andato giù o meno. In questo caso, la differenza sta solo nella singolarità o molteplicità. Un insieme di test molto buono ..., eseguito all'infinito, è monitoraggio. E il monitoraggio corretto dovrebbe essere proprio così.

E quindi, come esattamente raggiungerai questo stato, quando venerdì sera ti deployi e vai a casa, è un'altra questione. Forse sei semplicemente un audace trasgressore.

Torniamo un attimo indietro all'Integrazione Continua. Ci siamo allontanati verso un'altra pratica complicata.

E la seconda illusione è che il MVP, dicono, deve essere fatto in fretta, quindi non servono affatto test. Non è proprio così. Il fatto è che quando scrivi una user story per il MVP, puoi svilupparla in modo casuale, cioè ascoltare che c'è una user story e correre subito a codificarla, oppure lavorare secondo il TDD. E con il TDD, come dimostra la pratica, non ci si impiega di più, quindi i test sono un effetto collaterale. La pratica del TDD non riguarda il testare. Nonostante si chiami Sviluppo Guidato dai Test, qui non si parla affatto di test. È piuttosto un approccio architettonico. È un metodo per scrivere precisamente ciò di cui hai bisogno e non scrivere ciò che non ti serve. Questa pratica si concentra sulla prossima iterazione del tuo pensiero in termini di creazione dell'architettura dell'applicazione.

Quindi non è così facile liberarsi di queste illusioni. MVP e i test non si escludono a vicenda. Anzi, piuttosto il contrario: se realizzi un MVP seguendo la pratica TDD, lo farai meglio e più velocemente che farlo senza alcuna pratica, e a casaccio.

È un pensiero molto sottile e complesso. Quando senti dire che ora scriverò più test e nello stesso tempo farò qualcosa più velocemente, sembra assolutamente inadeguato.

(Dmitrij) Qui molti, quando parlano di MVP, sono semplicemente troppo pigri per scrivere qualcosa di decente. E queste sono comunque cose diverse. Non bisogna trasformare l'MVP in una cosa brutta che non funziona.

Sì-sì, hai ragione.

E poi, improvvisamente, MVP in prod.

Per sempre.

Il TDD può sembrare insolito quando ascolti che stai scrivendo test e apparentemente stai facendo più lavoro. Sembra strano, ma in realtà consente di ottenere risultati più rapidi e ordinati. Quando scrivi un test, nella tua mente stai già pensando molto su quale codice e come verrà chiamato, nonché quale comportamento ci aspettiamo da esso. Non stai solo dicendo che hai scritto una funzione e che fa qualcosa. Prima pensi che ha tali condizioni e che verrà chiamata in un certo modo. Copri tutto questo con i test e di conseguenza comprendi come appariranno le interfacce all'interno del tuo codice. Questo influisce notevolmente sull'architettura. Il tuo codice diventa automaticamente più modulare, perché cerchi prima di capire come lo testerai, e solo dopo lo scrivi.

Con TDD ho avuto un'esperienza in cui, a un certo punto, ho assunto un mentore per Ruby, mentre ero ancora un programmatore Ruby. E lui dice: «Facciamo che tu faccia tutto con TDD». E io pensavo: «Cavolo, adesso devo scrivere qualcosa di aggiuntivo». Così abbiamo concordato che per due settimane scriverei tutto il codice funzionale in Python seguendo TDD. Dopo due settimane ho capito che non volevo tornare indietro. Dopo aver cercato di applicarlo ovunque per due settimane, ho realizzato quanto fosse più semplice anche solo pensare. Ma non è ovvio, quindi consiglio a tutti che, se avete la sensazione che TDD sia complicato, lungo e superfluo, provate a seguirlo per sole due settimane. A me sono bastate due per capirlo.

(Dmitry) Possiamo sviluppare questo concetto dal punto di vista dell'operatività dell'infrastruttura. Prima di lanciare qualcosa di nuovo, effettuamo un monitoraggio, per poi avviarlo. In questo caso, il monitoraggio diventa un test normale. E c'è uno sviluppo attraverso il monitoraggio. Ma quasi tutti dicono che è lungo, mi scoccia, ho fatto un bozzetto temporaneo. Se facciamo un monitoraggio corretto, capiamo lo stato del sistema CI. E nel sistema CI c'è molto monitoraggio. Comprendiamo lo stato del sistema, capiamo cosa c'è all'interno. E durante lo sviluppo, stiamo proprio creando un sistema che raggiunga lo stato desiderato.

Queste pratiche sono conosciute da tempo. Ne abbiamo parlato circa 4 anni fa. Ma in 4 anni praticamente non è cambiato nulla.

Ma su questa nota propongo di concludere la discussione ufficiale.

Video (inserito come elemento multimediale, ma chissà per quale motivo non funziona):

https://youtu.be/zZ3qXVN3Oic

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster