La crescita di microservice adozione ha causato un ritorno di popolarità di alcuni precedentemente trascurato software design patterns. Molti di questi modelli sono stati estratti dal Domain Driven Design di Eric Evans, un libro che parla tanto della struttura del team quanto dell’architettura del software.
E di questi modelli, il Contesto Limitato è forse il più importante da capire. Come ingegneri, siamo arrivati a considerare il Contesto limitato come un modello di progettazione dell’architettura software. Ma questo perché abbiamo cooptato un po ‘ dal suo utilizzo originale. Come usato da Evans, il contesto Delimitato è tanto un modello organizzativo quanto tecnico.
Ecco perché sono venuto a vedere il modello di contesto limitato come un perno nella comprensione dei microservizi. Non solo come costruirli, ma in realtà perché li costruiamo in primo luogo, e come possono rendere le nostre organizzazioni più successo. Se comprendiamo quali sono i contesti limitati-se adottiamo la mentalità del contesto limitato sia tecnicamente che organizzativamente — allora possiamo davvero avere successo nella costruzione della nostra architettura di microservizi.
Perché passare ai microservizi?
Per iniziare, eseguiamo un piccolo esercizio. Poniti questa domanda: Perché costruiamo microservizi in primo luogo?
Prenditi un momento per pensarci. Quali sono i vantaggi che prima vengono in mente? Quali sono i principali problemi che dovremmo sperare di risolvere? Annota alcune risposte, solo per essere onesto.
…
Hai la tua risposta? Bene. Leggilo a te stesso. Hai raggiunto i vantaggi tecnici standard? Consegna continua, scalabilità, ambienti poliglotti, contenitori e cloud e tutta quella roba buona? Grande.
Ma la tua risposta principale includeva qualcosa sull’abilitazione della tua organizzazione a operare in modo più efficiente? Dovrebbe. Perché costruire microservizi non significa realizzare benefici tecnici. Davvero, si tratta di ottenere benefici organizzativi. Tutto il resto è un dettaglio di implementazione.
Monoliths = coupled code and coupled teams
Man mano che i nostri monoliti diventano sempre più grandi, la produttività inizia a diminuire. Ci sono almeno due ragioni principali per questo.
Mettere i freni sulla nostra velocità
In primo luogo, ogni team di ingegneri sta contribuendo a una base di codice gigante. Come tale, i team affrontano una probabilità sempre crescente che il loro codice sia in conflitto con il codice degli altri. Per contribuire a mitigare i potenziali problemi che ciò potrebbe causare, istituiamo procedure: blocco del codice, periodi di test QA, rilascio di treni, ecc. – che sono letteralmente progettati per rallentare la nostra produttività.
Naturalmente, queste procedure impediscono l’implementazione tempestiva di funzionalità e miglioramenti. Inoltre devastano la capacità degli ingegneri di concentrarsi sulle priorità dei loro team. Se un bug viene trovato durante un periodo di test, il team responsabile deve contestualizzare e concentrarsi sulla risoluzione di quel bug. Se si trova un bug grave in produzione, il team deve non solo correggere il bug, ma anche saltare attraverso i cerchi per farlo distribuire dal prossimo treno di rilascio.
Il servizio di guardia diventa un boondoggle. Se qualcosa va storto con il nostro monolite, qualcuno deve essere disponibile-giorno o notte-per risolvere il problema. Ma chi? Le grandi organizzazioni con monoliti di grandi dimensioni si trovano generalmente di fronte a due scelte:
- Un team di gestione degli incidenti il cui unico, triste, triste lavoro all’interno dell’organizzazione è quello di rispondere ai problemi causati dal codice di altri ingegneri e capire come risolverli.
- Un programma a chiamata rotante, in cui ogni settimana a qualche ingegnere arbitrario viene assegnato il triste, triste lavoro di diventare responsabile della risoluzione di problemi che sono probabilmente causati dal codice scritto da qualche altro ingegnere, in qualche altro team di ingegneri.
(Mis)organizzare i nostri team
Monoliti pasticciare con le nostre organizzazioni in un altro modo. La nostra intera organizzazione sta lavorando sullo stesso, grande prodotto. Ma abbiamo ancora bisogno di rompere l’organizzazione in squadre gestibili. Quindi tendiamo a guardare ai ruoli funzionali per trovare i confini del team:
Purtroppo, questo tipo di struttura organizzativa limiti di collaborazione. Piuttosto che lavorare insieme per risolvere il vero problema a portata di mano (ad esempio, come progettiamo, costruiamo e manteniamo la funzione X?) i membri delle diverse aree funzionali si concentrano semplicemente sulla propria parte, metaforicamente gettando il loro lavoro oltre la recinzione quando hanno finito. Il potenziale di collaborazione e sinergia — dove la qualità combinata dello sforzo del team è molto più della somma dei singoli membri del team — viene perso.
È anche pieno di colli di bottiglia. Quando organizziamo i nostri team per area funzionale, avremo naturalmente disallineamenti nelle priorità. Diciamo che il team di gestione del prodotto ha deciso che il processo di checkout del nostro monolite deve essere rinnovato. Pianificheranno il tempo con il team di progettazione per mettere insieme alcune prese in giro. Ad un certo punto, le prese in giro saranno finite e consegnate al team di frontend per l’implementazione. Naturalmente, il team di frontend avrà bisogno di API da implementare dal team di back-end, quindi verranno bloccate fino al completamento. Una volta che il team di backend dà la priorità al suo lavoro sui nuovi servizi di checkout, scopre che ha bisogno di aiuto dal team di amministrazione del database (DBA). Che, ovviamente, ha le sue priorità. Quindi il team di backend verrà bloccato fino a quando un DBA non verrà liberato.
In un modo, questa struttura organizzativa sembra un po ‘ come un mal progettata, troppo accoppiato architettura software… non è vero?
Microservices = codice disaccoppiato, team disaccoppiati
Al contrario, un’architettura di microservizi consente l’autonomia del team. Diventa molto più semplice formare team autonomi, che lavorano insieme in modo efficiente e che non sono costantemente bloccati dalle dipendenze di altri team.
I team possono assumere la piena proprietà del proprio lavoro, dalla progettazione allo sviluppo fino alla distribuzione. Ogni membro condivide la responsabilità di raggiungere l’obiettivo della propria squadra, in modo da essere incentivato a partecipare a più di una semplice “loro parte”. Ho lavorato con team in cui product manager, designer, front-end, back-end e ingegneri mobili si sono riuniti per progettare le caratteristiche del prodotto, ottenendo risultati molto migliori di quelli che avrebbero potuto essere raggiunti da una sola persona.
Il team acquisisce la responsabilità per i propri artefatti una volta che vengono distribuiti in produzione. Questo in genere porta a codice di qualità superiore che è più facile da risolvere. Perche ‘ mai? A differenza di un monolite, le squadre tendono ad avere una visione olistica dei microservizi che possiedono. Quindi è molto più facile per il team anticipare i problemi, aggiungere una buona registrazione e metriche per risolvere i problemi quando si verificano e utilizzare correttamente i modelli di resilienza (ad esempio tentativi, interruttori automatici e fallback, ecc.)
Inoltre, poiché i team hanno un pieno senso di proprietà sul loro lavoro, mantenere i loro servizi sani e funzionanti in produzione diventa meno un programma di rilascio da incubo e più su come coltivare la loro creazione.
Infine, i team stanno lavorando verso lo stesso obiettivo, sulla stessa timeline. Ciò significa che non più bloccare una persona mentre aspettano che qualcuno in un’altra area funzionale si liberi.
Dobbiamo essere intenzionali sull’autonomia
Ma non otteniamo questi benefici gratuitamente semplicemente rompendo il nostro monolite in microservizi. Diamo un’occhiata alla prima, ingenua visione di un microservices architettura:
Se non siamo come la maggior parte degli ingegneri, la nostra idea iniziale di un microservice architettura è, beh, un sacco di microservices. Ognuno espone una sorta di API (ReST, forse) per consentire a qualsiasi altro servizio di leggere da esso e scrivere su di esso.
Acquisendo esperienza, apprendiamo che non tutti i microservizi hanno lo stesso scopo — o, almeno, non dovrebbero. E quindi, proprio come il nostro monolite erano stati disposti in strati, in modo che possiamo organizzare il nostro microservices:
A questo punto, abbiamo definito i diversi tipi di microservices e le applicazioni che vogliamo costruire. Grande. Ma non abbiamo ancora fatto molti progressi in termini di autonomia della squadra. Ogni microservizio dovrà essere di proprietà di qualche team. E quindi sorge la domanda: quali squadre possederanno quali microservizi?
Cross functional team
il primo, ingenuo approccio potrebbe essere quello di organizzare le nostre squadre imitando il nostro monolite struttura organizzativa:
Qui, vediamo squadre (in viola) organizzato dalla funzione di: UX design, frontend di ingegneria, backend di ingegneria, dati tecnici, amministratori di database, controllo qualità, etc.
Questo potrebbe sembrare giusto, almeno inizialmente. Ma facciamo un passo indietro e guardiamo il valore che stiamo cercando di offrire ai nostri clienti. È il nostro obiettivo costruire cose come le seguenti per i nostri clienti?
- Un gruppo di schemi di database
- Un gruppo di mockup di interfaccia utente
- Un gruppo di microservizi che possono parlare con un database MySQL?
Non proprio. Questi sono solo gli strumenti con cui utilizziamo per creare valore per i nostri clienti. Il valore effettivo che forniamo ai nostri clienti / utenti si presenta sotto forma di funzionalità e funzionalità come:
- Un catalogo prodotti per cercare
- Un meccanismo per inserire gli articoli in un carrello e successivamente acquistarli
- Un sistema di notifica per avvisare i clienti dello stato dei loro acquisti
Allo stesso modo, non vogliamo organizzare il nostro team per area funzionale. Piuttosto, dovremmo definire i nostri team in base al valore che creano per i clienti; cioè, tra le funzioni, nei team interfunzionali (giustamente denominati).
Con i team cross functional, tutti lavorano insieme per costruire un prodotto o una funzionalità specifica, dall’inizio alla fine. Tutti nel team hanno gli stessi obiettivi e priorità, quindi nessuna area funzionale è bloccata da un’altra. Il nuovo servizio API backend richiede un lavoro di progettazione del database? Bene; l’ingegnere di back-end del team e il DBA possono entrambi dare la priorità al loro lavoro insieme.
Al loro meglio, i team interfunzionali incoraggiano i membri a collaborare in ogni fase del progetto. Ogni membro del team contribuisce alla progettazione complessiva della funzione. Frontend, backend e ingegneri mobili definiscono congiuntamente i contratti API. Tutti i test. E tutti iniziano a diventare ben versati nel loro particolare dominio.
E così, il nostro team strutture potrebbero iniziare a cercare qualcosa di simile a questo:
Che è meglio. Ma c’e ‘ ancora qualcosa che non va.
Certo, abbiamo formato squadre che probabilmente saranno più efficaci nel possedere prodotti. Ma abbiamo ancora adottato un approccio top-down per identificare la topologia dei microservizi che la nostra organizzazione intende costruire. Siamo rimasti con una vasta collezione di microservizi interdipendenti, la maggior parte dei quali sono accoppiati insieme. Li abbiamo semplicemente assegnati a diversi team da costruire.
Questo porta a preoccupazioni come:
- Come possiamo creare API in grado di soddisfare tutte le esigenze attuali e future che qualsiasi client potrebbe avere? Possiamo incapsulare i nostri dati quando uno qualsiasi dei nostri servizi potrebbe essere chiamato dai servizi di qualsiasi altro team?
- Quanto tempo perderemo in attesa che altri team implementino le nostre dipendenze?
- Quali guasti dei nostri sistemi potrebbero essere causati da guasti in altri sistemi (guasti a cascata)?
- Possiamo controllare il numero di chiamate in cui i nostri servizi potrebbero essere coinvolti? Possiamo garantire che la nostra organizzazione non finisca per creare chiamate sincrone illimitate tra i servizi, portando a tempi di risposta astronomici, o peggio (e sì, ho visto accadere) chiamate infinitamente ricorsive tra i servizi?
- Cosa succede se la caratteristica specifica del nostro team o lo spazio problematico non sono adatti per la topologia di microservizi pre-pianificata?
Abbiamo ancora bisogno di un modo diverso di pensare. Forse esiste già un modello da seguire?
Immettere il contesto limitato
Il contesto limitato è un modello di progettazione chiave a carico di domain driven design, o DDD. Comprendere il contesto limitato ci aiuta a formare team autonomi e, per estensione, architetture di microservizi autonome.
DDD stesso descrive una metodologia di sviluppo software in cui gli individui all’interno di un’organizzazione lavorano insieme per definire un linguaggio comune. Nel suo libro Domain Driven Design, Eric Evans descrive spesso gli ingegneri che lavorano con i proprietari di prodotti per stabilire un vocabolario concordato per descrivere cose come prodotti, componenti dei prodotti, azioni che un prodotto può eseguire (o può essere eseguito sul prodotto), parti di flussi di lavoro, ecc. Questo vocabolario comprende il dominio dell’organizzazione.
In molte grandi organizzazioni, tuttavia, la definizione di un vocabolario unico e coerente diventa irrealizzabile. In questi casi, suddividiamo il nostro dominio in sottodomini. Esempi di sottodomini potrebbero includere:
- gestione dell’Inventario
- l’individuazione del Prodotto
- gestione Ordini
- carrelli della spesa e di pagamento
Come progettisti, ingegneri, responsabili di prodotto, ecc, insieme per creare un sottodominio, formano il loro modo di pensare e di parlare del sottodominio e dei suoi componenti.
È qui che DDD incontra la struttura del team interfunzionale. Anche se i membri del team provengono da diverse aree funzionali, sono responsabili per il proprio sottodominio, alla fine diventano esperti residenti. Inoltre, il team è responsabile di determinare quali artefatti-microservizi, applicazioni Web, app mobili, database e infrastrutture correlate — sono necessari per dare vita al sottodominio e ai clienti dell’organizzazione.
Possiamo pensare alla squadra e ai suoi artefatti come comprendenti un Contesto Limitato.
Definizione del contesto limitato
Mentre Evans discute frequentemente i contesti limitati nel suo libro, in realtà non definisce esplicitamente il modello. Quindi tenterò di farlo qui:
Contesto limitato:
Un sistema internamente coerente con confini accuratamente progettati che mediano ciò che può entrare nel sistema e ciò che può uscirne.
In altre parole, un Contesto limitato rappresenta un contesto — essenzialmente, un sistema che incapsula componenti cooperativi — con confini chiaramente definiti che governano ciò che può entrare nel sistema e ciò che può uscirne.
Celle (quelle piccole cose che insieme costituiscono tutti gli esseri viventi) offrire un’analogia. All’interno di una cellula sono tutti i tipi di componenti (il nucleo, ribosomi, citoplasma, citoscheletri, ecc) che sono tutti incapsulati all’interno della cellula stessa. Circonda ogni cellula, tuttavia, è una membrana, che funge da barriera tra interni della cellula e il resto dell’organismo. La membrana protegge la cellula dal suo ambiente, consente a nutrienti specifici di entrarvi e consente a vari sottoprodotti di andarsene.
Allo stesso modo, un Contesto limitato consiste in una varietà di componenti (microservizi, applicazioni web, app mobili, database, code di messaggi, ecc.). Serve anche come una barriera logica che incapsula tali componenti. Internamente, i componenti possono essere accoppiati e possono passare liberamente i dati l’uno all’altro. Ma il Contesto Limitato aiuta a far rispettare l’accoppiamento allentato esternamente, definendo punti espliciti in cui:
- i dati esterni possono entrare (forse tramite il consumatore iscritto a un argomento Kafka)
- i dati interni possono uscire (forse tramite un altro argomento Kafka, o tramite un’API GET ben progettata, accuratamente creata per nascondere i dettagli del sistema interno)
Un contesto limitato rappresenta anche il suo team interfunzionale. Il team è composto da vari membri del team (designer, frontend/backend/ingegneri mobili, product manager, data engineers e QA engineers, ecc.). Internamente, questi membri lavorano in modo cooperativo verso gli stessi obiettivi coerenti. Inoltre, questi membri del team sono (o dovrebbero essere) incapsulati in modo che abbiano dipendenze minime da altri team.
Quindi, piuttosto che iniziare a livello organizzativo e definire tutte le applicazioni e i microservizi che ci aspettiamo di costruire, costruiamo team attorno ai nostri sottodomini, consentendo a quei team di crescere i loro sottodomini e definire ciò che deve essere costruito. Fatto correttamente, tendiamo a vedere vari contesti delimitati nell’organizzazione come in crescita organica, piuttosto che come strutture rigide e predefinite.
Implicazioni sulla rottura del monolite
La legge di Conway ci dice che le organizzazioni progettano sistemi software che imitano la struttura di comunicazione della loro organizzazione. Questo spesso si rivela vero, quindi dovremmo essere riflessivi su come strutturiamo la nostra organizzazione mentre iniziamo a costruire microservizi.
In effetti, ormai, un’immagine dovrebbe emergere nella tua mente. Mentre passiamo dal monolite ai microservizi, dovremmo iniziare a pensare verticalmente (dividendo il monolite per i suoi sottodomini) invece che orizzontalmente (dividendo il monolite per i suoi strati funzionali).
In altre parole, non dovremmo iniziare sostituendo il monolite del livello di accesso ai dati con i dati microservices. Piuttosto, dovremmo iniziare dividendo un’intera funzionalità (come il processo di checkout o forse la ricerca del prodotto). Ogni caratteristica rappresenterà un contesto Limitato. E ciascuno sarà diviso da un team interfunzionale dedicato.
Inoltre, quel team dovrebbe concentrarsi sul proprio compito, ovvero:
- replicare fedelmente le funzionalità esistenti,
- o (meglio) costruire un’esperienza completamente nuova e migliorata per i propri clienti.
Come parte del processo, il team dovrebbe progettare il sistema più adatto per lo sforzo.
Ad esempio, potremmo decidere di rimuovere la nostra funzionalità di ricerca del prodotto dal nostro monolite. Il team di ricerca del prodotto potrebbe infine progettare un sistema che include:
- Kafka consumatori che ascoltano una serie di argomenti Kafka esterni per aggiornare il proprio sistema interno di record (SoR) per i prodotti.
- un Kafka editore che spinge modifiche alla sua SoR su un interno Kafka argomento
- un altro Kafka consumatore che ascolta interni argomento e aggiornamenti Elastico indice di Ricerca
- un GraphQL endpoint per freeform ricerche query Elastico di Ricerca
- un endpoint ReST che recupera singoli prodotti da ID
- una nuova applicazione web che utilizza gli stessi terminali per permettere che i clienti a cercare prodotti e di esplorare i dettagli del prodotto
- una simile serie di schermate che nel nostro mobile che utilizzano tali endpoint
- Un Kafka editore che spinge i messaggi, rappresentano distinte query eseguite dai clienti, per un esterno di Kafka argomento, utilizzato da qualsiasi altro contesto delimitata (per dire, analytics) che potrebbero essere interessati
Come iniziare peeling off più e più parti verticali del nostro monolite, altre squadre di costruire il loro Contesti Delimitati. Questi contesti delimitati potrebbero finire per apparire molto diversi l’uno dall’altro.
si Noti che i componenti all’interno di un determinato Contesto Delimitata potrebbe essere strettamente collegati; tuttavia, siamo talmente semplice mantenere aggiornati i nostri Contesti Delimitati disaccoppiato dall’altro. Nel nostro esempio, qualsiasi comunicazione tra Contesti Delimitati avviene passando messaggi tramite una coda di messaggi Kafka. È importante sottolineare che stiamo evitando le chiamate di richiesta/risposta sincrone tra contesti delimitati.
Questo vale anche per ciò che rimane del monolite. Certamente non vogliamo un accoppiamento stretto tra i nostri nuovi microservizi e il nostro monolite legacy. Quindi, mentre rimuoviamo parti del monolite, sfruttiamo il passaggio dei messaggi per consentire alle parti rimanenti di comunicare con i nostri nuovi Contesti Delimitati.
Controllo di realtà su tutto questo disaccoppiamento
A questo punto, potremmo chiederci se sia davvero possibile mantenere disaccoppiati i nostri Contesti Delimitati.
Nel mondo reale, possiamo davvero mantenere i nostri team protetti dalle dipendenze esterne? Non ci saranno mai casi in cui una squadra deve essere bloccata da un’altra squadra per portare a termine il proprio lavoro?
E possiamo effettivamente creare architetture di servizio per i nostri sottodomini che sono completamente disaccoppiati da altri sottodomini? Non c’è davvero bisogno che un’applicazione in un contesto limitato chiami mai in modo sincrono un servizio in un altro?
In realtà, potrebbe essere impossibile mantenere i nostri Contesti delimitati al 100% disaccoppiati. Ma possiamo avvicinarci, molto più di quanto la maggior parte di noi possa pensare.
Architetture reali
Iniziamo osservando le architetture disaccoppiate. Spesso compriamo nell’errore che qualsiasi dato tipo di dati dovrebbe vivere esattamente in una posizione e che qualsiasi altro sistema deve chiamare direttamente in quella posizione per accedere ai dati.
Ci riferiamo a questo come assegnazione di una singola fonte di verità (SSoT) ai nostri dati. Ma come descritto in questo articolo che analizza l’idea di SSoTs, quella stessa nozione è, in generale, un anti-pattern. Invece, la maggior parte dei contesti delimitati dovrebbe memorizzare la propria copia locale di tutti i dati che devono utilizzare.
Questo è esemplificato dal nostro Contesto limitato alla ricerca di prodotti dalla sezione precedente. Questo contesto limitato, ovviamente, si basa molto sui dati del catalogo prodotti della nostra organizzazione. Ma le probabilità sono che i dati vengano generati in un contesto delimitato diverso (lo chiameremo Contesto delimitato dalla voce del prodotto).
Il nostro primo approccio (ingenuo) potrebbe essere quello di esporre un’API ReST dal contesto limitato alla voce del prodotto e forzare i servizi all’interno del contesto limitato alla ricerca del prodotto a chiamare quell’API. Ma possiamo fare di meglio. Possiamo invece mantenere i sistemi disaccoppiati pubblicando le modifiche apportate dai servizi di inserimento del prodotto su Kafka. Il nostro prodotto-Ricerca Kafka consumatori quindi raccogliere quei messaggi e aggiornare i database di ricerca del prodotto.
si noti che questi due Contesti Delimitati sono alla fine coerente. Ciò significa che ci saranno brevi periodi di tempo in cui un dato dato potrebbe essere incoerente tra l’inserimento del prodotto e la ricerca del prodotto. Ad esempio, se il prezzo dei widget Wombat bianchi viene aumentato da $1,99 a $2.49, ci sarà un breve periodo di tempo (spesso una questione di secondi se non di millisecondi) in cui vi è una differenza di 50¢ nel prezzo del widget Wombat bianco tra i due contesti Delimitati.
Questo porta ai casi del mondo reale in cui non abbiamo alternativa se non quella di accoppiare Contesti delimitati. In alcuni casi, la coerenza finale non è accettabile. Ad esempio, prima che un cliente possa completare l’acquisto online, potrebbe essere necessario assicurarsi che ogni articolo nel carrello sia effettivamente disponibile in quel momento. Anche allora, spesso possiamo ridurre al minimo l’accoppiamento tra i due Contesti delimitati.
Le nostre interazioni potrebbero essere simili a queste:
- Poiché il cliente utilizza l’interfaccia utente Product-Search per trovare i prodotti, i database Product-Search vengono utilizzati per recuperare informazioni (come stili, recensioni dei clienti, prezzi, ecc.) sui prodotti
- Anche quando il cliente inizia il processo di checkout, utilizziamo ancora i database di ricerca del prodotto per recuperare le informazioni che devono essere visualizzate.
- Infine, quando il cliente fa clic sul pulsante finale “Completa acquisto”, effettuiamo una singola chiamata sincrona al Contesto delimitato dalla voce del prodotto per convalidare la disponibilità degli articoli prima di completare l’acquisto.
Un altro esempio comune che richiede coerenza immediata relativa all’autorizzazione. In molti sistemi, i token di sicurezza devono essere recuperati o convalidati su ogni richiesta. In questi casi, probabilmente dobbiamo consentire ai nostri contesti limitati di chiamare un altro contesto limitato orientato alla sicurezza.
Strutture organizzative reali
Che ne dici di team autonomi e interfunzionali? Quanto sono possibili nel mondo reale?
In realtà, è un processo di movimento continuo verso squadre completamente autosufficienti. Raramente raggiungeremo mai il 100% di autonomia con i nostri team. Ma se iniziamo organizzando i nostri team in modo intelligente e riconosciamo e rispondiamo ai colli di bottiglia che si presentano, possiamo avvicinarci.
Per cominciare, dovremmo massimizzare i nostri team verticali e interfunzionali e ridurre al minimo il numero di team orizzontali e monofunzionali. Ciò significa resistere all’impulso di formare i cosiddetti team “core”-la cui missione è costruire servizi dati comuni che vengono utilizzati da altri team orientati al prodotto — e invece formare i nostri team attorno al valore aziendale che forniranno.
Molte organizzazioni in punta di piedi verso questo obiettivo, prima formando team orientati al dominio di product manager e ingegneri front-end e back-end. E ‘ un inizio. Ma chi altri dovrebbero includere queste squadre? L’appartenenza esatta potrebbe differire tra diversi team con esigenze diverse. Ma dovremmo considerare cose come:
- Se il nostro team ha ingegneri front-end, allora le probabilità sono che dovrebbero lavorare a stretto contatto con un graphic designer che è dedicato al dominio.
- Gli ingegneri mobili — spesso sequestrati nella propria area dell’organizzazione — dovrebbero essere inclusi per i domini con un componente mobile.
- Nel suo illuminante articolo sulle mesh di dati, Zhamak Dehghani lamenta che gli ingegneri dei dati sono spesso esclusi dai team interfunzionali, a scapito degli ingegneri dei dati e dei team interfunzionali stessi.
Una volta che abbiamo determinato l’appartenenza dei nostri team, dovremmo fare attenzione ai colli di bottiglia. Ci sono altri team che bloccano abitualmente la produttività dei nostri team interfunzionali?
Ad esempio, molte organizzazioni dispongono di un team di sicurezza dedicato. Questa è una buona pratica, naturalmente; le organizzazioni hanno bisogno di una strategia di sicurezza coesa, e un modo per garantire la governance su tale strategia. Tuttavia, è anche comune che i team interrompano il loro lavoro in varie fasi per consentire revisioni di sicurezza del loro lavoro. Anche nella migliore delle situazioni, questo stabilisce blocchi stradali per i nostri team come una routine una pratica aziendale. Inoltre, spesso porterà i team a dover scartare tutto o parte del loro lavoro e ricominciare da capo, in quanto scoprono requisiti di sicurezza che non erano stati soddisfatti.
Questo è chiaramente un cattivo odore. Ma, come possiamo far rispettare gli standard di sicurezza della nostra organizzazione, consentendo ai team di rimanere autonomi e produttivi?
Possiamo farlo aggiungendo ingegneri della sicurezza ai nostri team interfunzionali. Ci sono tre approcci che possiamo prendere:
- Se abbiamo la fortuna di avere un team di sicurezza relativamente grande, possiamo assegnare a ciascun team interfunzionale un tecnico di sicurezza a tempo pieno (SE).
- Con team di sicurezza più piccoli, ogni SE può essere assegnato a un numero di team interfunzionali in modo part-time. Ciò consentirebbe comunque al SEs di comprendere gli obiettivi e i progetti dei team e di lavorare con il team per aderire agli standard di sicurezza dell’organizzazione durante tutto il processo.
- Se non abbiamo abbastanza risorse di sicurezza per entrambi possiamo muoverci nella direzione opposta. Invece di portare i membri del team di sicurezza nei nostri team interfunzionali, possiamo portare i membri dei team interfunzionali al team di sicurezza. Ogni squadra interfunzionale dovrebbe designare uno o due rappresentanti della sicurezza. I rappresentanti, periodicamente, si incontrerebbero con la sicurezza e sarebbero tenuti al passo con i requisiti e gli standard di sicurezza dell’organizzazione. Essi non possono essere esperti di sicurezza stessi. Ma saranno in grado di svolgere il ruolo di un ingegnere della sicurezza, assicurando che i loro team aderiscano alle pratiche di sicurezza dell’organizzazione.
Gilde
Questo si inserisce in un altro schema organizzativo che sta prendendo piede: le gilde. Il modello di gilda è nato dal modello di squadra cross-funzionale. Per loro natura, queste squadre sono popolate da membri specializzati in diverse funzioni. Ancora, spesso ha senso per le persone che si specializzano in una funzione specifica per incontrarsi insieme pure; per esempio, a:
- Affinare le loro abilità e imparare gli uni dagli altri
- Scoprire e stabilire le migliori pratiche per la loro particolare funzione
- a Seconda della funzione, creare standard e requisiti
la Nostra ultima soluzione di sicurezza efficace formata una “sicurezza di gilda”. I membri del team lavoravano principalmente con i loro team verticali; ma periodicamente, alcuni di loro si incontravano con la “gilda” di sicurezza per discutere le pratiche e gli standard di sicurezza dell’organizzazione.
Il modello di gilda funziona particolarmente bene anche quando si tratta di architettura software. In particolare con un’architettura di microservizi, è necessario un certo livello di governance tecnica a livello di organizzazione. Tuttavia, avere un gruppo di architetti seduti in una metaforica torre d’avorio, distribuendo regole alle squadre, è generalmente controproducente. Invece, gli ingegneri senior / lead dei nostri team interfunzionali possono incontrarsi periodicamente in una gilda di architettura. Lì, possono sollevare problemi dai loro team, elaborare soluzioni e stabilire pattens e standard.
Gilde possono anche essere estesa a quasi tutte le altre funzioni. Dopo tutto, vogliamo che i progettisti sviluppino e lavorino da una guida di stile dell’interfaccia utente comune. Vogliamo che i nostri ingegneri di frontend utilizzino gli stessi elementi dell’interfaccia utente. Gli ingegneri di QA dovrebbero essere allineati con il modo in cui i test vengono eseguiti nelle nostre organizzazioni. E i product manager dovrebbero essere in sintonia con la roadmap complessiva del prodotto dell’organizzazione.
Portare tutto insieme
Passare ai microservizi può migliorare notevolmente la produttività dei nostri team. Ma dobbiamo capire come sfruttare un’architettura di microservizi per arrivarci. Di tutti i modelli di progettazione e concetti che si riferiscono ai microservizi, il Contesto limitato è probabilmente il più importante per darci quella comprensione.
Con una solida comprensione del contesto limitato, comprendiamo che:
- La nostra struttura organizzativa e la nostra architettura tecnica vanno di pari passo
- I nostri team orientati al prodotto dovrebbero avere dipendenze minime da altri team, proprio come i sistemi che costruiscono dovrebbero essere disaccoppiati da altri sistemi
In generale, abbracciare il Contesto limitato mette nella mentalità che dobbiamo avere successo con la nostra architettura di microservizi. Assicurati di aver compreso questo modello importante prima di intraprendere il tuo viaggio microservices!