Crescete e Parametrizzatevi

La settimana scorsa ho seguito un piccolo seminario aziendale tenuto da un collega come introduzione ai metodi agili.

Ci sono andato per fare il collaborazionista infiltrato tra il pubblico, ma sono stato riconosciuto e additato prima di sortire un vero effetto sulla massa.

Eppure mi ero fatto crescere ben bene la barba… mah!

Durante la fase di domande e risposte si discuteva di minimizzazione delle features inutilizzate e di sviluppo “just in time”, ed è venuta fuori una frase così :

“Facendo così il software non è professionale, non è configurabile secondo necessità semplicemente cambiando un file di configurazione”

Ho lasciato correre perchè non ero io il relatore, non toccava a me rispondere e l’ottima spalla del mio collega ha percepito la chicca e ha commentato su questa linea :

“Se si smettesse di pensare al codice come qualcosa difficile e pericoloso da modificare…”

Mi azzardo a interpretare il suo pensiero come fondamentalmente aderente al mio e parto da qui per raccontare qualcosa su cui rimugino da un po’.

Ma chi ha mai detto che un software, per essere “professionale”, debba essere configurabile tramite qualcosa che non sia il codice stesso?

L’approccio closed-source che ha caratterizzato la nascita del nostro settore ha imposto automaticamente l’idea di fornire dei punti di configurazione “esterni” al codice. I sorgenti non potevano essere a disposizione dell’utilizzatore e i files di configurazione erano l’unica apertura per cambiare qualcosa. In seguito poi, la complessità e carenza di design hanno a fatto in modo che questo paradigma venisse mantenuto anche là dove si lavora open-source o su prodotti custom dove chi sviluppa sarà anche chi configurerà il sistema finito, dove quindi il codice è a disposizione.

Io stesso se dico : “Rendiamolo configurabile” intendo con questo l’aggiungere un accesso a un qualche tipo di file o altro punto di configurazione che non sia la modifica dei sorgenti.

Questo, che secondo me è solo uno dei possibili approcci, è generalmente visto come un fatto inalienabile, una verità evidente di per sè stessa, un postulato che dice più o meno così : se vuoi rendere configurabile del software devi aggiungere un file di configurazione e caricare i suoi valori al runtime là dove prima avevi il valore cablato nei sorgenti.
Ovviamente c’è anche il corollario : il software, perchè abbia un valore, deve essere configurabile secondo le esigenze dell’utente.

Il corollario lo condivido, il postulato no. Anzi, il corollario, parafrasato, dovrebbe prenderne il posto :
Il software deve essere adatto e adattabile alle esigenze dell’utente.

Detto questo, dove sta scritto che un file di configurazione sia il modo più semplice?

  1. Un file di configurazione richiede l’apprendimento di un dialetto : è comunemente scritto secondo una sintassi particolare, non standard. Per ogni prodotto c’è un formato, a volte c’è un formato e una semantica diversi per ogni file di un medesimo prodotto!
  2. Un file di configurazione richiede una sovrastruttura di “linking” nel software stesso che, quanto più è potente, tanto più è complessa da costruire. Spring, che io per inciso considero ottimo, non è di certo stato scritto in un giorno.
  3. Un file di configurazione è un costrutto i cui errori vengono riscontrati al terzo grado di feedback : non nel momento in cui viene scritto, non quando si compila, ma quando viene eseguito. Strano a dirsi, ma i files di configurazione sono entità che si “manifestano” solo al runtime.
  4. I files di configurazione non sono parte integrante del codice : è banale, ma questo significa che tutti gli strumenti di navigazione del codice resi possibili dal suo essere un linguaggio formale e univoco, sono sostituiti alla meno peggio dall’approssimativa ricerca testuale.

Tutto questo potrebbe sembrare accademia, vista l’apparente semplicità di un file di configurazione rispetto alla complessità del sistema che lo usa.

Ma i files di configurazione rimangono davvero una parte minimale dello sforzo di sviluppo e di manutenzione di un sistema?
Nella mia esperienza no. Per niente.

La piattaforma su cui lavoro al momento è una bestia che ha forse più di 200 files di configurazione su ogni singolo anello della catena.

Questi files richiedono commenti, esattamente come il codice, ma a differenza del codice non possiamo definire dei sottogruppi funzionali con un nome significativo, come facciamo con le funzioni, dobbiamo per forza commentare “a parole”.

Capire come funzionerà (o semplicemente che cosa sta facendo in questo stesso momento) l’intera macchina richiede, invece che una navigazione attraverso il codice, un saltellare continuo tra le configurazioni che leggo sulla macchina e i sorgenti.

La definizione del comportamento della macchina non è centralizzata in un solo punto, il codice. Non è nemmeno definita tutta secondo la medesima sintassi : un po’ è Java, un po’ sono delle accoppiate chiave valore con un uguale in mezzo, è un po’ sono degli alberi di proprietà scritti in XML con semantiche variegate.

Parte della definizione della mia macchina, addirittura, è scritta in SQL! Ebbene sì… perchè viene usato questo splendido strumento, che si chiama Castor, che, a partire da uno statement SQL genera delle classi Java compilate. Perchè si usa Castor? Dichiaratamente per evitare di scrivere e mantenere del codice Java di accesso al DB. E’ così che si astrae lo strato di persistenza? Evviva.

Aldilà di tutto, resta il fatto che in questo modo la navigazione nel pensiero della macchina richiede delle continue ricerche testuali, cambi di contesto e ambiguità.

A questo punto si raggiunge il ridicolo, come sempre accade : visto che i files di configurazione sono troppi e troppo complessi che cosa facciamo? Ovviamente li parametriziamo! Definiamo dei “super” files che contengono solo i valori significativi per il nostro uso attuale della macchina, e mettiamo un tag dentro al file di configurazione stesso che punti al super file.

Colta l’ironia della cosa? Prima abbiamo parametrizzato il codice in modo da poterne modificare il comportamento con dei files esterni, poi, visto che non ci sono dei veri strumenti per gestire la complessità di un’accozzaglia di files definiti senza un vero formalismo d’insieme, parametrizziamo i parametri stessi.

Ovviamente, proprio come abbiamo dovuto aggiungere una sovrastruttura che leggesse e linkasse al runtime i valori contenuti nei files di configurazione, ora bisogna ideare uno strumento che faccia la sostituzione dei tag che abbiamo inserito nei vari files di configurazione con i valori contenuti nei super files.

Il giorno che si vorranno parametrizzare gli SQL che servono per definire le classi che vengono generate da Castor giuro che me ne vado…

Ma parliamo dell’alternativa a tutto questo.

Cosa avverrebbe se noi non dovessimo aggiungere quella sovrastruttura? Se non decidessimo di spostare parte dei dati e della logica che definiscono il nostro prodotto in un posto dove sono slegati dal resto del sistema e invece lasciassimo tutto lì?

E se tutto ciò che vogliamo che sia facilmente configurabile, invece di spostarlo fuori dal codice, lo spostassimo fuori dalla complessità, ma esprimendolo sempre nel medesimo linguaggio del resto del sistema?

Perchè non posso concentrare tutta la mia configurazione in una classe Java che inizializza il sistema e che è a disposizione anche dei non programmatori?

Usando il nostro solito IDE otterremmo in un solo colpo il controllo di coerenza con la sintassi (è Java no? Eclipse controlla, Ant pure), la navigabilità ci permetterebbe di seguire linee di estensione, invocazioni e dichiarazioni in modo indipendente ed estremamente affidabile. Sapremmo subito se posso scrivere un numero o una stringa in quel campo, se quella classe è permessa o meno.

Insomma, si mantengono tutte quelle cose che uno implicitamente (ma dolorosamente) lascia andare quando parametrizza verso un file di testo o altro.

Ci vuole uno sforzo di design, bisogna rifattorizzare verso quell’obiettivo. La compilazione deve essere resa facile per tutti, non solo per gli sviluppatori, ma almeno, se ho messo il valore o l’oggetto sbagliati me ne accorgo alla compilazione, non dopo due giorni che gira il sistema : i files di configurazione sono quasi sempre, se non intrinsecamente, fail-slow.

Posso automatizzare il testing delle mie configurazioni con la stessa facilità con cui automatizzo i tests per la logica (se scritta bene, ovvio), invece di lasciarli sempre, inevitabilmente, fuori dal processo di testing ripetendomi “tanto sono solo dei .properties”.

Se metto tutte le classi “di configurazione” a parte poi, e faccio bene il mio lavoro, non avranno dipendenze efferenti e quindi isolandole in una o più unità di rilascio, si potrà configurare tutto senza bisogno di ricompilare niente altro.

Il linking sarebbe automatico, caratteristica stessa della compilazione/interpretazione e si potrebbero sfruttare i tools di rifattorizzazione dell’IDE per mantenere la coerenza al cambio della strategia di parametrizzazione. Capita spesso di non cambiare il nome di un file di configurazione solo perchè sappiamo che da qualche parte è usato e quindi dovremmo andare a cercare nel codice là dove quel nome spunta.

Parlo dal lato dello sviluppatore, ma costerebbe davvero tanto, una volta ottenute delle classi che sono di fatto solo degli elenchi di variabili di classe, dare in mano ai profani un Eclipse con solo quelle come sorgenti a disposizione, il resto come libreria e uno script di ANT che compili e butti sù il jar di configurazione?

Da questo punto di vista i linguaggi interpretati sono ancora meglio : di fatto puoi editarli con qualsiasi cosa, proprio come faresti con un file di configurazione, senza curarti di doverli compilare… sono convinto che, se ben impostata la cosa, chiunque sappia configurare un macchinone a furia di XML saprà farlo con dei .java (assieme a un IDE/Ant + librerie) e senza bisogno di niente se si tratta di ruby o altro linguaggio interpretato.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s