Il sottotitolo di questo blog

Per chi se lo chiedesse (e lo suppongo perchè alcuni me l’hanno già chiesto, ovviamente) il mio sottotitolo “sono sufficientemente….” è una citazione di Francesco Cirillo, precisamente dal suo seminario all’Italian Agile Day 2005.

I motivi del perchè l’ho scelta invece resteranno un mistero per i più. Confido che non gliene freghi niente a nessuno, nemmeno a quelli a cui l’ho spiegato.

Ma che bella notizia…

Giusto l’altro giorno leggevo che una nota società di consulenza internazionale, in particolare un suo VP di origine italiana, ha avuto la meravigliosa idea di aprire un “centro di sviluppo” a Napoli in cui assumerà 400 programmatori del sud e centro Italia.

Le mie informazioni sull’argomento si limitano a un articoletto di giornale e non vorrei criticare senza sapere, ma ci sono state un paio di frasi dell’intervistato, e un’interessante omissione, che mi hanno davvero fatto guardare di cattivo occhio la notizia.

Prima di tutto si parla di questo grande centro di sviluppo, ma non si dice qual’è l’applicativo/i o almeno il settore dei prodotti che intendono creare, quindi mi azzardo a dire che non saranno nuovi prodotti per far concorrenza alle grandi software house, quanto piuttosto la solita robetta. Ma allora perchè ammucchiare così tanta gente se sono piccole produzioni? La risposta giunge dall’affermazione dell’intervistato : pare che vogliano dimostrare di poter far concorrenza ai programmatori indiani in termini di costi per il mercato dell’outsourcing.

Questo l’ho trovato a dir poco agghiacciante. Ma hanno idea di quanto costi un programmatore esperto negli Stati Uniti? Eppure non è che tutti i programmatori americani siano migrati in India per trovare lavoro. Anzi, l’orizzonte della produzione software anglosassone è a dir poco prolifico, e gente come Thoughtworks, che ha una grossa sede in India, di certo non lo fa per pagare di meno la “manodopera” (li pagano come a Londra).

Non è all’India che dobbiamo fare concorrenza! Dovremmo mirare a fare concorrenza, almeno, all’Inghilterra.

Vogliamo far calare i costi di sviluppo? Iniziamo a coltivare l’eccellenza, non la manovalanza del codice. Nel campo dello sviluppo software 10 programmatori “tosti” creano un valore molto maggiore (un prodotto solido, facilmente estensibile) di 1000 programmatori che hanno sempre e solo fatto “manutenzione”. Vogliamo iniziare a pagare i nostri un centesimo di quelli americani? Mi sembra ottimo, così potranno scrivere milioni di linee di codice spaventosamente costoso e fallimentare mentre agognano solo a una cosa : diventare un giorno dei manager.

Quei quattrocento che dovranno fare concorrenza agli indiani di certo non li invidio, anche perchè in India, come al solito, stanno imparando in fretta, e presto la qualità del software in outsourcing sarà superiore a quello che sviluppiamo qui. Volesse solo il cielo che questo grande benefattore avesse detto : “Stiamo aprendo un grande centro di sviluppo dove svilupperemo applicazioni per ……., creeremo del grande software con un grande valore”. Sarei stato davvero felice di leggere una simile notizia.

A questo punto posso confidare solo nella superficialità dell’articolo e dunque d’aver capito male.

MDA, Molto Design Apriori

Definizione di model driven architecture per gli organizzatori del “first Italian MDA forum” :

“Basato sugli standard aperti stabiliti dall’ OMG®, l’approccio MDA® separa la logica di business dalla sottostante piattaforma tecnologica. E’ un approccio allo sviluppo del software che aiuta le imprese a sviluppare progetti complessi medio-grandi riducendo i costi di sviluppo e sopratutto di manutenzione, permettendo di incorporare rapidamente cambiamenti tecnologi e funzionali. MDA® inoltre favorisce la salvaguardia degli investimenti aziendali poiché permette il riuso continuo e trasparente dell’analisi e del codice.”

Questo approccio di sviluppo sembra davvero avere dei vantaggi eccezionali! Devo assolutamente apprenderlo… certo che se si tratta semplicemente di creare un modello nella propria applicazione (invece che, ad esempio, avere qualche centinaio di transaction scripts con migliaia di variabili globali), hanno scoperto l’acqua calda, non c’era bisogno di inventarsi un nuovo nome, si tratta semplicemente di object-oriented programming, ma vediamo più in dettaglio di cosa si tratta :

“MDA consider the existence of two models:

  • a PIM (Platform Independent Model), which is an abstract, high level model that specifies the application to be built (=what we want to do).
  • a PSM (Platform Specific Model), which is a concrete model that contains elements tied to a specific platform (=how we will do it).”

“Summarizing, a complete MDA application consists of a definitive PIM, plus one or more PSMs and complete implementations, one on each platform that the application developer decides to support.”

Hm… suona come un sacco di documentazione, io credevo che Model fosse il model di “model view controller”, cioè il cuore dell’applicazione, il dominio, dove si mette la logica di business.

Ma vediamo come sono fatti questi PIM e PSMs:

“For many specifications, these [PIM e PSM] will be defined in UML, making OMG’s standard modeling language a foundation of the MDA.”

Quindi questo metodo di sviluppo richiede :
1) Un documento di design UML, indipendente dalla tecnologia, -completo- di tutta l’applicazione.
2) Uno o più documenti di design UML estremamente dettagliati che tenga conto della tecnologia usata(PSM). Uno per ogni tecnologia su cui si implementerà.
3) Implementazione del PSM.

A conferma di questo ordine di esecuzione leggo questa frase da degli esperti di MDA :

“A functional model, or a business transaction, must at some point be translated into a executable code and a physical transaction”

Manco a dirlo tutti gli esperti di MDA che ho visitato su internet sono anche degli esperti di generazione automatica del codice a partire dall’UML.

Adoro in particolare quel “at some point”, che rivela tutta la diffidenza verso questa fase del lavoro, quasi a dire : “magari si potesse fare a meno dell’implementazione!”, risuona proprio come “implementation considered harmful”.

Tutto torna, è proprio lui… mr. Waterfall I presume.

Mi rimane solo un’ultima osservazione, ma perchè mascherare un processo di sviluppo (per altro già ben noto), dietro al nome “architecture”? Ah, già, perchè in questo “nuovo” paradigma i diagrammi UML (e MOF, e CWM*) non sono documentazione, sono -parte integrante- del sistema. Direi che è un ottimo approccio, almeno quando avremo finito di diagrammare tutto quanto e non ci sarà nulla di implementato, non solo potremo dire che il sistema esiste già, ma è anche perfettamente aderente al modello.

Il sistema, anzi, è il modello!

La prossima volta che il baraccone su cui lavoro (e il cui codice non posso toccare) non funziona farò un bel diagrammone di come invece dovrebbe essere per poter funzionare bene e poi lo spedirò ai sistemisti da installare. Sarà uno spettacolo.

[MOF sta per Meta-Object Facility, che, a quanto leggo, sarebbero le specifiche a cui aderire per far sì che un tipo di diagramma sia trasformabile in un altro diagramma MOF-based.
CWM sta per Common Warehouse Metamodel, a quanto pare si tratta di un meta-modello per definire i meta-modelli dei metadati che definiscono gli insiemi di dati.
Insomma, ho capito che quando ho bisogno di farmi un sacco di risate, devo solo visitare il sito dell’OMG]

Stairway to Hell

E’ da un po’ che penso all’insieme di tecniche, regole, principi e strumenti che conosco, e sempre più spesso mi rendo conto che, oltre al contesto tecnologico della loro applicazione, c’è un’altra proprietà molto interessante secondo cui catalogarle, quello che ho preso a chiamare “ordine”, come se si trattasse dei pezzi di un’approssimazione di MacLaurin.

L’ordine rappresenta l’immediatezza degli effetti di una pratica di sviluppo (sia questo il termine generico) sul risultato finale. Lo si può definire per differenza come “la complessità oltre la quale il mancato utilizzo della pratica porta all’esplosione dei costi e alla morte del progetto entro l’ordine seguente”. Proprio come nelle approssimazioni polinomiali, più si ci allontana dall’origine dell’approssimazione più bisogna introdurre le componenti di ordine superiore.

Quindi il mancato utilizzo di una pratica di primo ordine porta alla morte del progetto (costi del tutto esplosi) mentre questo si avvicina a una complessità del secondo ordine.

Questo non vuol dire che tutti le pratiche che elencherò saranno quelle che reputo migliori per una certa complessità, sono solo quelle -strettamente necessarie per non morire-, alcune sono sostituite da altre che però appaiono in ordini più alti, ma la cui assenza, quando la complessità è bassa, non porta automaticamente alla morte.
Perchè le ordino quindi in questo modo, invece di concentrarmi semplicemente sulle “migliori” in assoluto? Non perchè io creda che le pratiche di ordine più basso siano più facili e veloci, e quindi adatte a sviluppi piccoli, in verità molte delle pratiche di ordine superiore hanno proprio la caratteristica di accelerare lo sviluppo e di aumentare il valore del prodotto a tutti i gradi di complessità. Proprio per questo sono critiche quando le linee sono tante. Il motivo effettivo di questa categorizzazione lo discuterò alla fine.

Per semplificare, come spesso si usa, conteggio la complessità con le linee di codice, in particolare linee di codice di un linguaggio moderno ad oggetti in un’applicazione in cui le linee di codice sono in qualche modo correlate a un numero crescente di features (insomma, non un mega algoritmo di ricerca, che fa molto bene una sola cosa, ma qualcosa di molto variegato nel range dei suoi compiti : una “storia” ogni mille linee). Ovviamente senza conteggiare le linee di librerie di terze parti, frameworks etc.

1° ordine : 100 linee, qualcosa di più di un hello world
2° ordine : 1.000 linee, la piccola componentuccola.
3° ordine : 10.000 linee, una applicazione di qualche utilità anche se presa da sola.
4° ordine : 100.000 linee, classica web application completa, multilayer.
5° ordine : 1.000.000 linee, grosso sistema, il classico “progettone” di una piccola società
6° ordine : 10.000.000+ linee, mega sistemone tuttologo integrato, mostro sviluppatosi in anni nella pancia di una grossa entità, con vari gruppi di sviluppo che si sono avvicendati nel tempo, magari appartenenti a un set di società terze.

Dunque, secondo la mia personale esperienza, catalogo le pratiche di sviluppo secondo il loro ordine :

1° ordine : 100
– Suddivisione delle procedure in sottoprocedure
l’alternativa è una singola enorme procedura, facendo così i costi esplodono quando superi le cento linee e la morte sopravviene intorno alle mille (secondo giorno di sviluppo).
– Nomi significativi
quando variabili e procedure hanno nomi oscuri bisogna sempre tenere a mente il loro significato, se sono davvero oscuri si inizia a far fatica sopra le cento e verso le mille nessuno ci capisce più niente.

2° ordine : 1K
– Strutture dati
se non si pensa in anticipo alle strutture dati, ad esempio, se non si usa una gerarchia di oggetti quando serve, si inizia ad impazzire sopra le mille linee e non riesci più a scrivere una sola procedura verso le diecimila, semplicemente perchè la struttura dei dati non rispecchia il problema.
– Uso di variabili d’istanza
se si procede tutto a metodi statici, per quanto vengano usate le pratiche del primo ordine, avvicinandosi alle 10K linee si inizia davvero a non capirci più nulla, si ha per le mani del codice puramente procedurale, con metodi con moltissimi parametri e un mucchio di variabili.

3° ordine : 10K
– Compilazione real-time (o con un click)
se il processo di compilazione è una fase a parte nel proprio processo di sviluppo, eseguita non continuamente, ogni compilazione rivelerà moltissimi errori di battitura e di svista, questi sono veloci da correggere, ma sarebbero stati ancora più veloci se fossero invece stati evidenziati dall’IDE, o dallo script di compilazione continua.
– Almeno un paio di tests di integrazione durante lo sviluppo
attendere l’ultimo momento per integrare il software significa non avere nessun feedback del comportamento di quanto si è scritto, se non quando è troppo tardi. Se il software sono 10.000 linee magari si avrà il tempo di debuggare in fretta e furia e si riuscirà a rilasciare qualcosa, ma verso le 100K questo sforzo frenetico è anche conosciuto come “allungarsi a dismisura dei tempi di sviluppo e conseguente morte del progetto”.
– Coinvolgimento del cliente
affidarsi a un elenco di features definite in partenza e mai approvate dal cliente se non alla fine di tutto, porta, da questo punto in poi, grane sempre maggiori, per il semplice fatto statistico che, più features ci sono, più ci sono ambiguità e dunque risultati che non rispettano l’idea del cliente. Da qui in poi le features richieste dal cliente sono almeno una dozzina.

4° ordine : 100K
– Design Patterns
un bel design, con tanti patterns, e un sacco di diagrammi UML è quello che ci vuole per superare con comodo le cinquencento classi.
– Programmare sull’interfaccia
se i tipi delle variabili, dei return e dei parametri non sono classi astratte, tutti i nostri metodi e le nostre classi saranno estremamente poco polimorfici. La perdita di polimorfismo porterà a duplicazione del codice.
– Pochi parametri per metodo
se le responsabilità delle classi sono sballate a tal punto da avere delle procedure piene di parametri si sono in verità utilizzati gli oggetti solo per raggruppare dei metodi, e si ci trova un sistema puramente procedurale ben organizzato. Il milione di linee probabilmente ucciderà tutto questo.
– SRP
avere delle classi che fanno troppo inizia a questo punto a portare all’esplosione combinatoria delle estensioni. Prima si notava meno, perchè il numero delle classi era basso. A questo punto, un’architettura cresciuta sui dati, invece che sui comportamenti, ha ammonticchiato tipicamente una dozzina di metodi significativi per ogni classe, e ogni nuova feature sicuramente ne porta almeno due a divergenza; una divergenza che non viene gestita con la composition deve essere gestita con l’ereditarietà, e quindi avremo sia mancanza di chiusura che duplicazione massiccia del codice.
– Don’t Repeat Yourself
la sincronizzazione di dati duplicati, sopra questo numero di linee, tende a far impazzire la complessità degli algoritmi e a moltiplicare il numero dei parametri dei metodi, per il semplice fatto che, per mantenere la coerenza dei dati, bisogna avere sotto mano, sempre, tutti i punti in cui si trovano, prima magari erano solo due, ma da qui in poi tendono a essere tre, quattro o più.
– Test unitari automatizzati
senza unit tests, quando le classi iniziano a essere più di 500, si perde traccia delle responsabilità di ognuna, la documentazione inizia a essere irrimediabilmente obsoleta e i tests ai morsetti non forniscono i dettagli necessari a mantenere coerente l’uso e l’estensione del codice esistente. “Guardare cosa fa il sistema” non è più sufficiente per capire dove mettere le mani. Il trasferimento di conoscenza, allo stesso modo, diventa troppo costoso se non è appoggiato da micro casi d’uso.
– Automatizzazione del deployment
il deployment automatizzato è prerequisito dell’integrazione continua, sopra questo ordine di grandezza del progetto si deve poter integrare tutto frequentemente, e quindi automaticamente. Incidentalmente il feedback end-to-end frequente copre i punti che sfuggono ai tests unitari.

5° ordine : 1M
– Liskov
con alcune migliaia di classi in gioco e probabilmente una configurazione estremamente dinamica e distribuita su più macchine, la non aderenza a Liskov inizia a costare molto, cosa usare, e dove, deve essere una caratteristica built-in nella definizione dei tipi del sistema, che deve assicurare la sostituibilità e non qualcosa di inaffidabile e da documentarsi caso per caso.
– Avoid singletons
quanto più il sistema è vasto tanto più si sente di avere bisogno a disposizione una quantità di informazioni, la tentazione di usare il singleton per raggiungere queste informazioni ha probabilmente portato a un centinaio di questi simpatici oggettini, conosco almeno un paio di sistemi che stanno esplodendo nei costi di manutenzione ed estensione perchè tutti questi singletons sono di fatto non-sostituibili e quindi non permettono la chiusura verso il cambiamento. Shotgun surgery anyone?
– Legge di Demeter
strisciante come è Demeter, la sua mancanza ci danneggiava già da tempo, ma da qui in poi i trenini di getters, con il loro bagagli di dipendenze efferenti, ci impediscono di seguire la pratica seguente.
– Evitare le ciclicità nelle unità di rilascio
riutilizzare singolarmente le classi bastava quando ne avevamo cento, ora che ne abbiamo qualche migliaio è il caso di riutilizzarle a grossi gruppi, per farlo dobbiamo essere in grado di definire dei gruppi, ma se ci sono due gruppi, A dipende da B e B dipende da A, non abbiamo due gruppi, ne abbiamo uno solo. Punto.
– Isolamento delle interfacce
il polimorfismo dato dalle astrazioni è una gran bella cosa, il passo seguente è riutilizzare queste astrazioni in diversi contesti, più un’interfaccia è carica di metodi, più definisce delle unità di riuso ampie, più sono ampie le unità di riuso, meno si trova un contesto dove riusarle… per chi non l’avesse ancora capito, questo post è la fiera delle banalità.
– Tests di acceptance automatizzati
con varie centinaia di features nel sistema il cliente non è in grado di controllarle “a mano”, la sua presenza e coinvolgimento non bastano più, deve essere messo in grado di definirle in modo univoco e controllabile automaticamente.
– Refactoring sistematico
personalmente ritengo che il limite tecnico dove il big design up front cessa di essere solo un metodo presuntuoso e inefficiente di definire l’architettura di un sistema e inizia invece a essere la diretta causa del fallimento di un progetto, il punto cioè, dove nessuno è più in grado, anche con i migliori sforzi, di far aderire l’implementazione a un design fatto a tavolino 10 mesi prima, sia localizzato da queste parti.
– Mocking e stubbing selvaggio
uno dei vantaggi di una copertura di tests unitari è che quando qualcosa si rompe, durante lo sviluppo di nuove features, il difetto viene immediatamente notato. Questo però non è più sufficiente quando si hanno alcune centinaia, se non migliaia, di tests, semplicemente per una questione di numeri : se prima rompevo qualcosa tre tests diventavano rossi, io li guardavo, e capivo in 40 secondi qual’era il problema, ora se rompo qualcosa i tests che diventano rossi sono trenta, e ci metto almeno 10 minuti a identificare qual’è effettivamente la classe che sta causando il fallimento. Se invece si mocka quasi tutto ciò che non è direttamente la classe sotto test, ci sarà, in ogni test, solo una classe che possa cambiare, il resto saranno tutti mocks e stubs quasi privi di pericoli di regressione, a questo punto il rapporto è uno ad uno, e quindi, quando io rompo qualcosa, si rompe solo un test, quello che effettivamente è responsabile di testare la classe dove c’è il problema.

6° ordine : 10M
– Test driven development
nella mia esperienza il rateo dei difetti quando il codice è sviluppato in TDD è circa un quarto di quello che ho quando sviluppo vecchia maniera e scrivo i tests dopo. Inoltre, strano a dirsi, ciò che ottengo col TDD richiede meno rifattorizzazione per mantenere la qualità del software, e a questi livelli il debito di design sappiamo avere degli interessi enormi. E’ un’ipotesi, perchè non ne ho esperienza diretta, ma sono convinto che l’approccio “feature-driven” sia l’unico che permetta di ottenere il design potente e eppure semplice che è necessario per non iniziare a morire lentamente una volta superate le 5000 features.
– Gestione automatizzata di tutti gli artefatti
non avere uno strumento che gestisce la complessità di decine di prodotti deployati in modo indipendente, ma sviluppati con una grande quantità di moduli comuni e continuamente riutilizzati (prerequisito per arrivare vivi fino a qui) trasforma lo sforzo di sviluppo in uno sforzo di gestione. Malevola, come sempre, torna la viscosità ambientale.

C’è dell’altro, ma non saprei mai elencare a memoria ogni singola tecnica che trovo vitale, devo trovarmi ad usarle o farmi dell’auto-brain-storming per qualche ora con un foglietto dove scrivere tutto, e non ne ho proprio voglia. Magari aggiungerò, con il loro ordine, altre tecniche, quando mi troverò ad usarle nei prossimi giorni, ma per adesso mi fermo qui.

Perchè questa categorizzazione dunque.

Il motivo è molto pratico : si impara solo sbagliando. Sfortunatamente molti errori tendono a essere evidenti solo da un certo punto in poi, esattamente come il debito di design non si fa sentire immediatamente, pratiche che si credevano eccellenti si dimostrano fallimentari solo a mesi o anni di distanza (superata una certa complessità) e si scopre quindi che erano sufficienti solo fino a un certo punto.

Appurato che l’educazione accademica fornisce solo a pochissimi una preparazione tecnica che includa anche solo alcune delle pratiche che ho elencato sopra, per non parlare di design OO, l’unico caso in cui queste verranno effettivamente apprese, è dopo essere stati testimoni (e fautori) della morte, o dell’agonia, di uno o più progetti software dell’ordine di grandezza necessario perchè una certa problematica risulti evidente.

Ma se l’industria locale supera raramente le 100K linee di codice per singolo progetto (e per questo ringrazio anche i frameworks) il numero di persone esposte alle dure lezioni dello sviluppo di sistemi complessi è estremamente ridotto. Detto questo, non mi stupisce che il programmatore in Italia non sia visto come il professionista che è nel mondo anglosassone. In effetti anche un neolaureato ha la preparazione per arrivare vivo alle 10K linee, peccato che difficilmente avrà mai la responsabilità di scriverne molte più di così, e quindi non crescerà, come invece crescono molti dei programmatori di US e UK.

Quindi questi “ordini” sono un’indicazione di quale sia il potenziale di crescita tecnica per un individuo che inizia a programmare nell’industria. Meno si affrontano ordini elevati, più è breve la carriera tecnica, perchè breve è il periodo di apprendimento e quindi, in finis, il valore della propria professione. Mentre sappiamo benissimo quali cose grandiose siano in grado di ottenere professionisti con 20 anni di carriera tecnica alle spalle. Per avere 20 anni di apprendimento (e dopo 20 anni averne ancora da imparare) bisogna però affrontare problemi di ordine molto più elevato di quelli che si vedono in giro (almeno, dalle mie parti), altrimenti ogni azienda nel settore avrà solo “ragazzi” e, non a caso, si terrà ben lontana da progetti di dimensioni elevate, perchè, chissà poi come, quelli tendono a esplodere in mano. E’ un circolo vizioso che produce un sacco di manovali, pochi prodotti di livello internazionale, quindi ben poche occasioni per essere obbligati ad apprendere cose che arricchiscano le professionalità e così via.

Meeting di Ottobre del Jug Torino

<p> Non so che cosa sia successo, ma la settimana scorsa e quella precedente il mio blog è stato visitato una quantità spropositata di volte rispetto ai mesi precedenti. In 15 giorni ci sono state tante visite quante ce n’erano state in assoluto fino ad allora. Ora, visto che io nelle ultime settimane di certo non sono andato in tv a pubblicizzare il mio blog, la mia ipotesi è che un qualche tipo di bot (fatto male, visto che è entrato nel counter) abbia scorrazzato amabilmente sulle mie pagine qualche migliaio di volte.</p><p>Per questo motivo dico al o ai misteriosi bots visitatori : “Venite al meeting di ottobre del Java User Group di Torino! Si parlerà di vostri cugini!”</p><p>Di seguito scopiazzo e italianizzo la entry del blog della guida spirituale del gruppo.</p><p>Il meeting di ottobre del <a href=”http://www.jugtorino.it/”>Java User Group Torino </a>si terrà il 26 con il seguente programma :</p><ul><ul><ul><ul><li> 18.30: Check-in!</li><li>18.45: <strong>Quickie: “Starting with Robocode!”</strong> by Domenico Ventura (JUG Torino)</li><li>19.00: <strong>Seminar: “The Multimedia Home Platform (MHP)”</strong> by Domenico Barbieri (Sun Italy)</li><li>20.00: EOF (magari una grande pizza tutti assieme!)</li></ul></ul></ul></ul><p><a href=”http://www.jugtorino.it/vqwiki/jsp/Wiki?MeetingOttobre2006″>Qui trovate più dettagli</a></p>

I getters portano al peccato

Io credo profondamente nella debolezza umana, in particolare sono un convinto assertore della debolezza del programmatore, e mi piace essere debole. Se avessi una gran forza di volontà potrei creare tutti i getters che voglio e semplicemente “decidere di non usarli”. Sarebbe un po’ ridicolo forse, quindi penso che, debole o forte che uno sia, è il caso di non scrivere mai un getter.

Ma perchè non dovrei usare i getters? Se il mio obiettivo è mantenere un’architettura agile (quindi con le chiusure giuste) non c’è niente di peggio dell’infrazione del criterio di Demeter. Demeter è subdolo, se lo infrangi puoi pensare di passarla liscia per un po’, ma alla fine non solo ti troverai con del pessimo design, ma anche con una tale rete di relazioni che qualsiasi tentativo di identificare delle astrazioni sarebbe futile. In quel caso io penso che l’unica soluzione sia fregarsene del design, puntare solo a rimuovere tutte le chiamate che infrangono Demeter, e poi da lì partire con la rifattorizzazione verso i principi di design.

Quindi, qual’è il modo migliore per infrangere la legge di Demeter?

Tipicamente un programmatore che lavori in un linguaggio ad oggetti ha ben chiara soprattutto una cosa, perchè gli è stata detta alla prima lezione di “programmazione ad oggetti” : gli oggetti incapsulano i dati, non si dovrebbe accedere mai direttamente ai dati.

Questa, ovviamente nella mia umilissima opinione, è una scemata galattica, perchè gli oggetti non incapsulano i dati per mestiere, questo è incidentale, gli oggetti rappresentano del comportamento nella sua interezza, e quindi posseggono le procedure, più tutto ciò che serve alle procedure, che possono essere dati, o altri oggetti, o nient’altro, è del tutto secondario.

Detto questo, il suddetto assioma insegna al programmatore (chiamiamolo ingenuo) qualcosa che si può applicare meccanicamente : tutti i campi di un oggetto devono essere privati. Essendo meccanico costa poca fatica mentale, ma dà tanta soddisfazione, ti fa sentire un grande designer.

Quindi, pensando al caso peggiore, del programmatore più ingenuo, dovremmo* almeno poter dare per assunto che metterà tutti i campi privati, irraggiungibili per virtù della sintassi. E questo, incidentalmente, ci protegge da infrangere Demeter. Quando il nostro programmatore si troverà a dover implementare una nuova feature si sentirà a disagio a rendere non-privati i campi che gli servono, e quindi abbiamo una piccola protezione.

*[Questo non è sempre vero, il vero caso peggiore scrive tutto public e tutto static, ma lasciamo da parte i freaks]

Creare dei getters, metodi non-privati che espongono un campo dell’oggetto è il modo migliore per cancellare anche questa piccola protezione : il nostro programmatore non ha ricevuto nessun condizionamento riguardo al livello di accesso dei metodi. Il getter, in quanto metodo, e quindi non tabu, lo mette in grado di fare quello che voleva fare sin dall’inizio : accedere a quello che gli serve per scrivere questa dannata feature; senza avere alcun senso di colpa.

I getters rendono dolce l’errore… una combinazione letale.

Io i getters li uso, ma non ho mai trovato un’occasione in cui questi fossero veramente necessari, c’è sempre un’alternativa che mi permetta di rispettare Demeter, non la seguo sempre, perchè, come dicevo all’inizio, sono debole, ma chissà perchè quando ho dei getters (comunque mai in un’interfaccia, sarebbe davvero troppo per il mio fegato) scopro sempre di avere :
a) troppe responsabilità in ogni classe
b) accoppiamento altissimo
c) poca astrazione
d) un sacco di mocks nei miei tests

In effetti, perchè mai i getters, a differenza dei campi pubblici, dovrebbero assicurare l’information hiding? Non nascondono un bel niente! E quindi come posso attendermi di avere uno qualsiasi dei benefici del design OO?

In verità, se proprio uno dovesse.. forse sarebbe meglio mettere un campo pubblico, almeno non ti viene voglia di farlo finire in un’interfaccia… ho già menzionato che vedere dei getters o dei setters in un’interfaccia mi fa venire le convulsioni?

P.S. un getter che in sè rappresenta la responsabilità di una classe (cioè non è un semplice passacarte ma contiene della logica)… tipo questo :

getSize(){return a*5/2}

non è un getter, è il metodo principale di SizeCalculator.