Premessa: onde evitare equivoci, per assunzioni non intendo l’effetto dell assumere qualcuno per un dato lavoro, ma le intendo in senso “logico”.
Di solito si dice che fissare ed inserire nel codice dei parametri di configurazione per un programma sia qualcosa di brutto e da evitare: un antipattern.
Da Wikipedia:
“Hard coding (also, hard-coding or hardcoding) refers to the software development practice of embedding input or configuration data directly into the source code of a program or other executable object, or fixed formatting of the data, instead of obtaining that data from external sources or generating data or formatting in the program itself with the given input.”
Ma di “hard coded” non esiste solamente il codice…
Soluzioni
Che un programma rappresenti una soluzione ad uno specifico problema non ci sono dubbi: particolare il problema, particolare la soluzione implementata.
Quello su cui vorrei puntare lo sguardo in questo caso sono le assunzioni. Wikipedia le definisce così:
“In logic, more specifically in the context of natural deduction systems, an assumption is a proposition that may be used to prove further propositions, in the expectation that the assumption will be discharged in due course by proving it via a separate argument.”
Viste in senso lato (e improprio) sono ragionamenti, decisioni, convinzioni, idee, … che stanno alla base e permeano i progetti, spesso senza mai essere messi in discussione.
…e poi finiscono nei programmi, talvolta esplicitamente (codice hard-coded), talvolta come qualcosa di nascosto, legato al comportamento e al funzionamento del programma.
Checchè ne dicano i guru della raccolta e analisi dei requisiti, una soluzione si basa in parte su ciò che si ritiene il cliente desideri (diverso da “ciò che vuole”, perchè spesso nemmeno lui lo sa definire in modo compiuto) e in parte sulle assunzioni implicite che si fanno.
Dal generico “le cose si fanno sempre così perchè si è sempre rivelato un buon modo di procedere” (il “99% delle volte” non è il 100% e non c’è scaramanzia che tenga!) fino ad arrivare alle minuzie che non si discutono col cliente per svariati motivi e, anzi, spesso si danno per scontate (“hosting rigorosamente fatto così, server fatti così, …”).
Il problema connesso con le assunzioni è che spesso esse rappresentano un tirare a indovinare, uno scommettere su come sarà la realtà a progetto avviato o concluso, spesso sulla base di qualcosa successo in passato e non sempre sulla base di dati oggettivi: “basterà?”
Di conseguenza, meno assunzioni implicite equivale a più controllo su un progetto…
Assunzioni come dipendenze nascoste
Da qualche giorno l’amico Stefano sta pubblicando usa serie di bei post sul tema “gestire l’interfaccia touch“, fornendo ottimi spunti, suggerimenti e trucchi su come farlo al meglio.
Riflettendo sul fatto che ogni dispositivo “touch” disponga un sensore di tocco di differente qualità, temo sia un attimo progettare qualcosa apparentemente multipiattaforma (“questa cosa la gestisce il sistema operativo per me”) ma in realtà intrinsecamente legato al/ai dispositivo usati per le prove.
Il risultato è che un programma, anche se formalmente non contiene codice hard-coded, ha comunque qualche velata dipendenza, qualche modo di operare che implicitamente richiama ciò che è stato usato per svilupparlo e testarlo.
E’ un po’ come sviluppare i giochi in Java per i cellulari e testarli su svariati modelli salvo poi scoprire che su alcuni modelli in commercio, simili ma non-testati (escono cellulari nuovi ogni giorno!), alcuni piccoli cambiamenti hw/sw introdotti dai produttori non permettono di giocare in modo altrettanto ottimale, o almeno non come in precedenza.
Spesso è colpa di chi cambia le cose senza avvertire debitamente, ma qualche volta è colpa di chi mette paletti, talvolta senza nemmeno accorgersene…
I costi di mantenere le assunzioni passate
Altre volte la dipendenza causata dalle assunzioni è esplicita e si paga in qualche modo nel tempo.
Un esempio famoso è l’ormai obsoleto “arithmetic if” del Fortran.
Sempre da Wikipedia:
“This was the only conditional control statement in the original implementation of Fortran on the IBM 704 computer. On that computer it could be implemented quite efficiently using instructions such as ‘Branch if accumulator negative’.”
Considerando che il linguaggio era di IBM, le macchine su cui giravano erano della IBM, apparentemente non era un’eresia ammetterlo nel “proprio linguaggio”. Specie se la cosa forniva dei vantaggi in termini di prestazioni su quei computer.
Tuttavia l’introduzione di questa feature, legata in qualche modo ad uno specifico computer, ha comportato anche la sua introduzione e la sua permanenza negli standard Fortran per lungo tempo.
Una assunzione fatta partendo da un numero limitato di macchine, si è trasformata in qualcosa da continuare a supportare nel tempo.
Pare che solo col Fortran90 questa feature sia stata finalmente dichiarata obsolescente (il linguaggio, è bene ricordarlo, è nato nel 1954).
Assunzioni forzate
Poi ci sono le costrizioni: nel caso dei dispositivi embedded, a fianco dei requisiti obbligatori imposti dalla piattaforma, certe assunzioni implicite diventano per motivi di forza dei dogmi: ad esempio, per quanto il codice finale possa anche essere vagamente portabile su più piattaforme, il funzionamento potrebbe essere (troppo) intrinsecamente legato al contesto e all’ambiente in cui il programma opererà. Questo per ragioni di prestazioni oltre che di risorse e costi.
Che ne pensate?
Bell’argomento, che potrebbe portare ad una marea di approfondimenti.
Io credo molto nel buon senso e nel compromesso, e credo anche che il giusto livello di assunzioni in un progetto non sia poi così facile da trovare e dipenda da tanti fattori, non solo tecnici.
Sicuramente una libreria, un linguaggio, un database o una piattaforma dovrebbe fare meno assunzioni possibili per consentire agli sviluppatori la maggior libertà di movimento.
Ma una applicazione che gira su uno specifico hardware ?
Al costo di ridurre la portabilità, aumentare le assunzioni serve a ridurre i tempi di sviluppo ma anche ad aumentare in un certo senso la qualità del prodotto. Penso alle app per iPhone, ad esempio, dove un ambiente molto standardizzato e con poche varianti ha reso possibile la realizzazione di applicazioni in media molto più usabili di quelle realizzate per un Windows Mobile dove bisogna fare i conti con molte più varianti.
… eppure …
… eppure …
… chi non ha fatto l’assunzione della risoluzione dello schermo su iPhone si è già preparato per iPad. Chi può sapere cosa riserva il futuro ?
Vero! Anche se un’applicazione gira su un hardware specifico questo non implica che non ci possano essere prima o poi variazioni, modifiche, novità su quell’hardware per cui è sempre bene non cablare in modo troppo risoluto valori e comportamenti nel codice. Non si sa mai…
Grazie di essere passato. Ciau! ^^