Ogni sviluppatore ha quella cartella. Quella chiamata utils o helpers che copi da un repo all'altro. La incolli, passi venti minuti a cancellare i riferimenti ai vecchi schemi del database, a rimuovere i controlli di autenticazione che non servono e a rinominare le variabili affinché il nuovo linter smetta di urlare. Lo facevo con un sistema di tematizzazione che avevo costruito, il Dynamic Theme Kit. Era nato come una funzionalità all'interno di un'applicazione e, per mesi, l'ho trattato come uno strumento portatile. Mi sbagliavo. Copiare il codice non significa riutilizzarlo. È duplicazione con passaggi extra.
La trappola della mentalità focalizzata sul singolo progetto
Quando costruisci una funzionalità all'interno di un progetto, fai centinaia di assunzioni invisibili. La palette di colori potrebbe presupporre una determinata configurazione CSS-in-JS. La scala di spaziatura potrebbe fare riferimento a un design token della guida di stile del tuo brand aziendale. Il passaggio tra modalità chiara e scura potrebbe chiamare un endpoint per le preferenze dell'utente unico per il backend di quell'app. Queste dipendenze sembrano innocue perché, all'interno del progetto, lo sono. Appartengono a quel contesto.
Il problema inizia quando provi a estrarre quel codice. Scopri che il componente "riutilizzabile" è in realtà una ragnatela di stringhe nascoste che lo collegano a quel singolo codebase. L'ho imparato con DTK. Generava variabili di tema, sì. Ma si aspettava anche una specifica struttura di cartelle. Importava una definizione di tipo da qualche parte profonda nella directory types dell'app originale. Presupponeva la presenza di un oggetto di configurazione globale che esisteva solo in quel repository. Non me ne ero mai accorto perché, all'interno di quel progetto, tutto era sempre presente.
Trasformare DTK in un pacchetto standalone ha significato fare chirurgia, non espansione. Non avevo bisogno di più funzionalità. Avevo bisogno di meno connessioni.
Estrarre il Dynamic Theme Kit
Il lavoro più difficile è stato sedersi davanti al codebase e chiedersi, per ogni funzione e ogni export: questo serve la logica di tematizzazione o serve il progetto? Ho rimosso i preset di stile. Ho eliminato l'assunzione che il consumatore dovesse essere un'applicazione React. Ho cancellato completamente le palette di colori predefinite. Il progetto originale aveva un'estetica aziendale blu navy e ardesia integrata nei valori predefiniti. Quella doveva sparire. Un pacchetto non può includere i colori del tuo brand.
Il nuovo kit avrebbe fatto esattamente una cosa. Prende un oggetto di configurazione — alcuni valori di colore, alcuni numeri di spaziatura, alcune scale tipografiche — e genera proprietà CSS personalizzate. Tutto qui. Non le applica. Non decide dove posizionarle nel DOM. Non gli importa se usi Tailwind, Styled Components o semplice HTML. Fornisce le variabili alla tua applicazione, e il tuo progetto sceglie come usarle.
Quel vincolo sembrava limitante all'inizio. Si è rivelato liberatorio.
Cosa si rompe quando provi davvero a riutilizzarlo
Prima di pubblicare qualsiasi cosa, avevo bisogno della prova che l'astrazione reggesse davvero. Ho tirato fuori tre piccoli progetti personali dal mio archivio: uno strumento di anteprima markdown, un tracker di abitudini e una landing page per un evento. Nessuno di essi condivideva un framework o una struttura di cartelle. Ho installato DTK localmente in ognuno e ho provato a applicarvi un tema.
Il primo tentativo è fallito immediatamente. I nomi delle variabili generati da DTK erano troppo specifici. Produceva token come --primary-action e --background-overlay che implicavano un certo layout dell'interfaccia utente. Nell'anteprima markdown, quei nomi non avevano senso. Non c'era un pulsante di azione. Non c'era un overlay. Ho rinominato la logica di generazione per produrre nomi strutturali e neutri che descrivessero il valore piuttosto che il widget.
Ho anche scoperto che i miei valori predefiniti erano troppo aggressivi. Quando un utente passava una configurazione incompleta, DTK riempiva le lacune con valori che sembravano corretti in una dashboard densa, ma che rompevano una landing page essenziale. Sono passato a valori predefiniti trasparenti, in cui i token mancanti non venivano semplicemente renderizzati, lasciando che il progetto che li utilizzava definisse i propri fallback.
Poi c'era la documentazione. Ciò che sembrava ovvio per me — "passa semplicemente un oggetto di configurazione" — era vago per chi leggeva il README a mezzanotte. L'ho riscritta con oggetti reali, percorsi di file reali e spiegazioni chiare di cosa accade quando chiami la funzione rispetto a ciò che la tua applicazione deve fare successivamente.
Questi piccoli progetti personali hanno fatto da banco di prova. Non c'era molto in gioco, ma hanno messo in luce difetti reali che non avrei colto fissando il codice sorgente in isolamento.
La vera prova: la produzione in Web Weavers World
I progetti personali sono dei sandbox. Non hanno scadenze, stakeholder o CSS legacy che preceda il tuo pacchetto. La vera prova è arrivata quando ho integrato DTK in Web Weavers World, il mio sito aziendale. Si trattava di un sito live con stili esistenti, aspettative del cliente e analisi da considerare. Se il pacchetto avesse rotto qualcosa, non avrei potuto semplicemente eliminare il repo e ricominciare da capo.
Ho aggiunto DTK alla pipeline di build, l'ho puntato verso una nuova configurazione di colori e l'ho lasciato generare un nuovo set di variabili CSS. L'integrazione ha richiesto un pomeriggio, non una settimana. Quello è stato il segnale. In precedenza, aggiungere un nuovo tema significava scrivere nuovo CSS, rintracciare valori esadecimali hardcoded in venti file e sperare di non aver saltato un caso limite. Ora aggiungo una palette al file di configurazione, DTK genera le variabili e il resto del sito le utilizza. La logica del tema è passata dall'essere un processo manuale fragile a qualcosa di cui mi fido abbastanza da delegare ai collaboratori.
Tre domande che hanno cambiato il mio modo di costruire
Attraverso questo processo sono stato costretto a formalizzare una checklist mentale che ora utilizzo prima di astrarre qualsiasi cosa:
- Questa variabile è davvero generica? Se il nome o la logica fanno riferimento a un concetto di dominio del progetto originale, deve rimanere indietro.
- Questo appartiene al pacchetto o all'applicazione? Le regole di business, l'identità del brand e le assunzioni sul layout risiedono nell'app. L'infrastruttura che genera output standardizzati risiede nel pacchetto.
- Sto risolvendo un problema riutilizzabile o uno specifico per il progetto? Questa è la domanda più difficile a cui rispondere onestamente. Ci piace pensare che le nostre soluzioni siano universali. Di solito sono locali.
Rispondere a queste domande mi ha costretto a semplificare il mio design, spesso rimuovendo codice piuttosto che aggiungendone. DTK mi ha insegnato che il riutilizzo non è un regalo che fai a te stesso. È una disciplina che si pratica dicendo di no alla comodità.
Un modo diverso di pensare al refactoring
Un tempo misuravo i refactoring in base a quanto accorciavano il codice. Meno righe sembravano un progresso. Ora li misuro in base a quante porte aprono. Il Dynamic Theme Kit non è elegante perché è conciso. È utile perché è sopravvissuto a tre progetti personali non correlati e a un sito aziendale in produzione senza dover cambiare la sua struttura interna.
Questa è la metrica che conta. Il codice che funziona una volta è un costo. Il codice che funziona ripetutamente è un asset. Ora, prima di iniziare qualsiasi nuova funzionalità, mi fermo. Mi chiedo se sto costruendo qualcosa di cui avrò di nuovo bisogno. Se la risposta è sì, lo costruisco in modo diverso fin dalla prima riga. Isolo gli input. Definisco gli output. Elimino le assunzioni.
Il miglior refactoring non rende il tuo codice più breve. Lo rende capace di funzionare in posti che non hai ancora immaginato.
