Ottimizza per l'opzionalità e costruisci verso checkpoint
In un episodio di Hackers Incorporated a tema project management, Adam Wathan ha introdotto la riduzione del rischio dei progetti con i save point. L'intero episodio vale sicuramente il tuo tempo, ma quel consiglio specifico ha cambiato il mio modo di lavorare come sviluppatore e di prendere decisioni come project manager.
In pratica, mi ha insegnato a ottimizzare per l'opzionalità, non per l'efficienza.
Il branch monolitico
Per illustrare cosa significa, costruiremo una sezione account utente come esempio. La nuova sezione account verrà rilasciata agli utenti con un unico grande lancio. Un utente può…
- Aggiornare le informazioni di base del proprio profilo
- Aggiungere il proprio indirizzo con l'autocompletamento di Google Maps
- Caricare un'immagine del profilo
- Collegare account di social login
- Reimpostare la password
Facciamo una stima:
| Attività | Stima |
|---|---|
| Informazioni di base | 6h |
| Autocompletamento indirizzo | 12h |
| Immagine del profilo | 4h |
| Social login | 8h |
| Reimpostazione password | 4h |
Facendo la somma: 6 + 12 + 4 + 4 + 8 = 34, ovvero una stima di 40 ore. (Bisogna aggiungere quel margine!) Faremo il checkout di un nuovo branch feature/user-account, implementeremo e rilasceremo. I log finali nel nostro time tracker:
| Attività | Stima | Effettivo |
|---|---|---|
| Informazioni di base | 6h | 3h |
| Autocompletamento indirizzo | 12h | 14h |
| Immagine del profilo | 4h | 6h |
| Social login | 8h | 18h |
| Reimpostazione password | 4h | 2h |
3 + 14 + 6 + 18 + 2 = 43. Non troppo lontano dalla nostra stima (gonfiata)! Alcune attività sono state più facili da implementare del previsto, altre hanno richiesto molto più tempo. Ma non abbiamo rilasciato dopo 43 ore lavorative, ci sono volute 4 settimane per arrivare in produzione. Perché?
- Ci siamo resi conto che la nostra applicazione doveva essere approvata dal nostro provider di social login, e questo ha richiesto una settimana. Dopodiché l'implementazione ha richiesto molto più tempo del previsto.
- Quando abbiamo iniziato a implementare il nuovo flusso di reimpostazione password, abbiamo trovato alcuni problemi nel design, quindi il team di design ha dovuto aggiornare il file Figma. L'implementazione è andata più liscia del previsto, ma abbiamo dovuto aspettare le modifiche.
- Naturalmente, i soliti bug e le piccole richieste di funzionalità che si insinuano nella nostra pianificazione hanno spostato ulteriormente questo progetto in avanti.
Che gli utenti abbiano dovuto aspettare più del previsto per la nuova funzionalità account non è un problema. Questo post non è un manifesto per rilasciare modifiche incrementali invece di lanci big bang: lascio quella decisione ai product manager. Buttare tutto in un unico branch è semplicemente facile. Dato che non avremmo rilasciato nulla individualmente, ci era permesso! Quello che mi interessa è come influisce su tutto il resto. Perché nel frattempo…
- Un altro sviluppatore aveva bisogno dell'autocompletamento dell'indirizzo nella pagina di spedizione. Ora abbiamo due implementazioni e dobbiamo buttarne una.
- Qualcun altro ha rifattorizzato il modello utente e il codice correlato, causando una serie di conflitti di merge durante le 4 settimane di sviluppo.
- Il design di un'altra funzionalità simile a una timeline si basa sulle immagini del profilo, ma volevamo aspettare che questo branch fosse unito per avere accesso ai componenti dell'immagine del profilo già configurati.
Checkpoint
Trattiamo ogni attività come un progetto individuale. Probabilmente richiederà più tempo, almeno sul nostro timesheet. Dobbiamo creare un branch separato per ogni attività e non possiamo implementare modifiche in blocco. Invece di un unico grande merge di feature/user-account, abbiamo creato, revisionato e unito una serie di branch più piccoli nel corso delle settimane.
feature/user-basic-information-views
refactor/share-google-maps-api-credentials
feature/google-maps-autocomplete
feature/profile-picture
refactor/user-authentication-changes
feature/social-login
fix/profile-picture-upload-bug
feature/reset-password-update
feature/reset-password-update-2
Ma cosa abbiamo guadagnato da questo approccio?
- Se l'autocompletamento dell'indirizzo fosse stato unito prima, non ci saremmo ritrovati con due implementazioni. Anche se la prima non fosse ancora stata rilasciata in produzione, sarebbe stato un componente utilizzabile nel codebase.
- Non avremmo speso altrettanto tempo sui conflitti di merge, perché i merge frequenti li mantengono piccoli o inesistenti.
- Avremmo potuto decidere di rimandare il social login se avessimo saputo che era un investimento così grande. Non l'abbiamo fatto perché era troppo intrecciato nel branch monolitico.
Lavorare per chunk unibili non dà solo allo sviluppatore più opzionalità, rende l'intera organizzazione più flessibile.
Col senno di poi è tutto più chiaro. Sarebbe potuta andare diversamente: magari lavorare nell'ombra per molto tempo non ha influenzato nessuno. Ma non puoi saperlo in anticipo. Le priorità cambiano e non hai il controllo dei fattori esterni che le impongono. Se fossi a metà del branch monolitico dell'account utente e un bug critico o un concorrente ti costringesse a cambiare rotta, tutto il tuo codice resterebbe ostaggio finché non ci torni su. Anche se non lo rilasci agli utenti, è più prezioso averlo nel branch principale.
Quando il codice è in un feature branch, non contribuisce al resto del codebase. Questo progetto da 40 ore è un esempio innocente. Spesso cadiamo nella stessa trappola per progetti da 250 ore. Si tratta di uno o due mesi di lavoro: uno o due mesi di codice work in progress che indugia. Il codice marcisce nel tempo. Il codice work in progress marcisce molto più rapidamente.
Per parafrasare Eliyahu M. Goldratt (sono un fan della teoria dei vincoli): grandi quantità di work in progress mascherano inefficienze e colli di bottiglia nel processo produttivo. Ridurre il work in progress può migliorare il flusso di cassa. Poiché il work in progress viene convertito in prodotti finiti e venduto più rapidamente, accelera il ciclo di conversione del contante. Nel nostro linguaggio: il codice diventa un asset solo dopo essere stato unito.
Punti d'azione
Per rendere actionable questo appello: tratta ogni chunk di lavoro come qualcosa che dovrebbe essere unito entro la fine della settimana. Ciò non significa che debba essere “finito” o disponibile per l'utente finale, ma che debba diventare un cittadino di The Codebase.
La parte difficile è trovare i tuoi checkpoint. Identifica il percorso critico. Cosa puoi togliere da una funzionalità mantenendola utile? Fai quello per ultimo. Fai un passo indietro ogni poche ore, chiediti quale sia la quantità minima di lavoro per rendere unibile ciò che stai facendo. Avere un ambiente di staging privo di bug dal primo giorno e mantienilo tale per assicurarti che i merge frequenti non influiscano sulla qualità (leggi la teoria delle finestre rotte).
Ci vuole un po' per abituarsi e all'inizio sarà scomodo. Ma se lo fai abbastanza, vedrai checkpoint ovunque. Lavorare in piccoli chunk significa che le singole attività potrebbero richiedere più tempo. Ma a lungo termine tu e il team nel suo insieme vedrete guadagni in flessibilità, opzionalità ed efficienza. Questi benefici superano ampiamente il tempo che guadagneresti da uno sconto di volume.
Un po' di saggezza del deserto per concludere:
Arrakis insegna l'atteggiamento del coltello: taglia ciò che è incompleto e dice: “Ora è completo perché è finito qui.”
Altri articoli recenti
Laravel AI 1.1 e 1.2: Agent Skills, Cohere e structured output più solidi
Le release 1.1.0 e 1.2.0 di laravel/ai portano gli Agent Skills, l'approvazione obbligatoria per i tool built-in e nuovi provider come Cohere e Laya self-hosted. Sul fronte qualità arrivano i fix allo structured output per Bedrock e il supporto alle provider options. Aggiornati anche i modelli di default, con Claude 4.7+ che ignora i sampling params.
Laravel 13.35.0: scheduler più controllabile, code più flessibili e response Markdown
Laravel 13.35.0 porta Schedule::alwaysOnOneServer(), il supporto a schedule:interrupt per i comandi di lunga durata, --memory in percentuale per queue:work e il nuovo metodo markdown() sulla response factory. Tante piccole migliorie anche a test, view compilate in parallelo e dischi local.
BashBox: un interprete Bash in sandbox per agenti AI in PHP
BashBox è un interprete bash scritto in puro PHP che permette di eseguire gli script generati dagli agenti AI senza mai ricorrere a proc_open, exec o shell_exec. Ogni comando è una classe PHP che lavora su un filesystem virtuale, con limiti di esecuzione, quote disco e accesso di rete configurabili. Ideale per chi sviluppa agenti con il Laravel AI SDK o altre librerie simili.