giovedì 29 gennaio 2009

Best Practices: Thinking in C++ di Bruce Eckel


Tra le letture che consigliamo vi è Thinking in C++ di Bruce Eckel. La prima edizione è del 2000 ma i concetti espressi sono ancor oggi molto moderni. Vi sono elencate una serie di best practices fondamentali per chi scrive codice e ciò indipendentemente dalla piattaforma tecnologica utilizzata.
Di seguito una serie di spunti di riflessione tratti e tradotti (molto!) liberamente dal testo originale... e per non prenderci troppo sul serio lasceremo la parola a Dilbert, mitico personaggio di Scott Adams che tutti i developer per la loro sopravvivenza tecnica e non solo (altra lettura consigliata è The Career Programmer: Guerilla Tactics for an Imperfect World) dovrebbero tener in gran conto... forse ancor più di Bruce Eckel!!!


1. Prima fatelo funzionare, poi rendetelo veloce! Questo è vero anche se siete certi che un qualsiasi frammento di codice sia realmente importante e che diverrà esso il collo di bottiglia principale del vostro sistema. Non toccate quel frammento per ottimizzarlo. Prima di tutto cercate di ottenere un sistema funzionante con un progetto il più semplice possibile. Soltanto dopo, se non è abbastanza veloce, lo analizzerete. Quasi sempre scoprirete che il vero problema non è il "vostro" collo di bottiglia. Risparmiate tempo per le cose veramente utili.

2. L'eleganza nella scrittura del codice paga sempre. Non è un'attività frivola. Avrete in mano un programma non solo più facile da compilare e testare, ma anche più semplice da comprendere e da manutenere: ed è qui che si ritrova il valore economico del vostro lavoro. Potrebbe servire un po' di esperienza prima di comprendere questo dato, in quanto potrebbe apparire che, mentre cercate di rendere elegante un frammento di codice, non siete in realtà produttivi. La produttività emergerà poi quando il codice si integrerà perfettamente nel vostro sistema, ed ancor più quando il codice o il sistema verrà modificato.

3. Ricordatevi del principio "divide et impera". Se il problema che state affrontando è troppo complesso, cercate di immaginare quali potrebbero essere le operazioni basilari del programma. Magari immaginando un "qualcosa" che si occupi delle parti più difficili!
Questo qualcosa è un oggetto e quindi scrivete il codice che utilizza quell'oggetto. Successivamente analizzate l'oggetto ed incapsulate le sue parti complicate all'interno di altri oggetti, e così via.

4. Se avete un grosso blocco di codice che ha bisogno di modifiche, cominciate ad isolarne le parti che non verranno modificate, eventualmente inglobandole in una"classe API" come metodi statici. Successivamente, focalizzate la vostra attenzione sul codice che verrà modificato, ristrutturandolo in classi. In tal modo renderete agevoli le modifiche man mano che la vostra attività di manutenzione procederà.

5. Tenete ben distinti il creatore della classe dal suo utilizzatore (il programmatore client). Chi utilizza la classe è il "cliente", e non ha bisogno né vuole sapere cosa accade dietro le quinte. Chi crea la classe dev'essere l'esperto di progettazione di classi e deve scriverla in modo che possa essere usata anche dal più principiante dei programmatori, continuando a comportarsi in maniera robusta nell'applicazione. L'utilizzo di una qualsiasi libreria è semplice soltanto se è trasparente.

6. Quando create una classe, usate una nomenclatura il più chiara possibile. Il vostro obiettivo è quello di rendere l'interfaccia di programmazione concettualmente semplice. Cercate di rendere i vostri nomi talmente chiari da rendere superflui i commenti. A tal fine, sfruttate l'overloading delle funzioni e gli argomenti di default per creare un'interfaccia intuitiva e facile da usare.

7. Il controllo dell'accesso consente a voi (creatori della classe) di fare in futuro estese modifiche che saranno quindi possibili senza danneggiare il codice client nel quale la classe è utilizzata. In questa prospettiva, mantenete tutto il più private possibile, e rendete public solo l'interfaccia della classe, utilizzando sempre le funzioni anziché i dati. Rendete i dati public solo quando siete costretti. Se gli utilizzatori di una classe non hanno bisogno di richiamare una funzione, dichiaratela private. Se una parte della vostra classe deve restare visibile alle classi eventualmente ereditate come protected, fornite un'interfaccia a funzioni piuttosto che esporre direttamente i dati. In questo modo, le modifiche di implementazione avranno un impatto minimo sulle classi derivate.

8. Prima di tutto e se possibile scrivete il codice di test. Ancor prima di scrivere la classe e poi tenetelo in evoluzione insieme alla classe. Rendete automatica l'esecuzione dei vostri test magari tramite un makefile oppure mediante uno strumento similare. In questo modo, qualunque modifica potrà essere controllata automaticamente lanciando il codice di test, e gli errori verranno immediatamente scoperti. Sapendo di avere la rete di sicurezza dell'ambiente di test, sarete più propensi ad effettuare modifiche consistenti quando ne sentirete il bisogno. Ricordate che i maggiori miglioramenti nei linguaggi di programmazione vengono dai controlli interni forniti da controllo del tipo, gestione delle eccezioni e così via, ma queste caratteristiche servono fino ad un certo punto. Dovete arrivare in fondo alla strada che porta alla creazione di sistemi robusti introducendo i test che verificano le caratteristiche specifiche della vostra classe o del vostro programma.

9. Ricordate una regola fondamentale dell'Ingegneria del Software: tutti i problemi di progetto del software possono essere semplificati introducendo un ulteriore livello di dereferenziamento concettuale. Quest'idea sta alla base dell'astrazione, la caratteristica primaria della programmazione orientata agli oggetti.

10. Rendete le classi le più atomiche possibile; in altri termini, date ad ogni classe un unico scopo chiaro. Se le vostre classi o il vostro progetto del sistema diventano troppo complicati, suddividete le classi complesse in classi più semplici. Il segnale più ovvio di questo fatto è proprio la stessa dimensione: se una classe è grande, c'è la possibilità che stia facendo troppo e che quindi è necessario scomporla.

11. Guardatevi dalle definizioni dei metodi lunghe. Una funzione lunga e complicata è difficile e costosa da mantenere, e probabilmente sta cercando di fare troppo da sola. Se vi trovate a maneggiare una funzione del genere, significa che, quanto meno, andrebbe suddivisa in alcune funzioni più piccole. Potrebbe anche suggerire la creazione di una nuova classe.

12. Guardatevi dalle liste di argomenti lunghe. Le chiamate di funzione diventano difficili da scrivere, leggere e manutenere. Piuttosto, cercate di spostare il metodo in una classe nella quale sia più adatto, e/o a passargli un oggetto come parametro.

13. Non ripetetevi. Se un pezzo di codice compare in molte funzioni nelle classi derivate, spostate quel codice in un'unica funzione nella classe base e chiamatelo dalle funzioni delle classi derivate. Non solo risparmierete spazio, ma consentirete un'agevole propagazione delle modifiche. Potete utilizzare una funzione inline perl'efficienza. Talvolta, la scoperta di questo codice comune porta considerevoli benefici alla funzionalità della vostra interfaccia.

14. Guardatevi dalle istruzioni switch o dagli if-else concatenati. Tipicamente, questo è un chiaro indicatore della programmazione di tipo type-check.
Programmazione type - check significa che state scegliendo quale codice eseguire in base ad un qualche genere di informazione sul tipo (il tipo esatto potrebbe non esservi immediatamente chiaro). Solitamente, potete rimpiazzare questo genere di codice sfruttando ereditarietà e polimorfismo; la chiamata ad una funzione polimorfica eseguirà il controllo di tipo per voi, e consentirà un estensibilità più affidabile e semplice. [N.d.T. - In realtà il controllo sui tipi è caratteristico del C++ che è un linguaggio fortemente tipizzato, ma il principio è comunque valido come punto di attenzione di ordine generale, nel senso che un eccesso di if-else nidificati è sicuramente indice di entropia elevata che state inserendo nel codice.]

15. Guardatevi dalle limitazioni nell'ereditarietà. I progetti più puliti aggiungono nuove funzionalità a quelle ereditate. Diffidate di un progetto che rimuove le vecchie funzionalità (mentre state ereditando) senza aggiungerne altre. Ma le regole sono fatte per essere infrante, e se state lavorando con una vecchia libreria di classi potrebbe essere più efficiente restringere una classe esistente nelle sue sottoclassi, piuttosto che ristrutturare la gerarchia in modo che la vostra nuova classe si vada ad inserire dove dovrebbe, al di sopra della vecchia classe.

16. Non estendete le funzionalità fondamentali nelle sottoclassi. Se un elemento dell'interfaccia è fondamentale per una classe si dovrebbe trovare nella classe base, e non essere aggiunto nel corso delle derivazioni. Se state aggiungendo dei metodi tramite l'ereditarietà, forse dovreste ripensare il progetto.

17. Meno è più. Iniziate da un'interfaccia minimale per la classe, semplice e piccola quanto basta per risolvere il vostro problema corrente, ma non cercate di anticipare tutti i modi nei quali la vostra classe potrebbe essere usata. Al momento del suo utilizzo, scoprirete il modo nel quale dovrete espandere l'interfaccia. Comunque, una volta che la classe è in uso, non potete modificarne l'interfaccia senza disturbare il codice client. Se avete bisogno di aggiungere più funzioni, va bene; non creerà problemi al codice, se non la necessità di una ricompilazione. Ma anche se i nuovi metodi rimpiazzano le funzionalità di quelle vecchie, lasciate da sola l'interfaccia già esistente (se volete, potete combinare le funzionalità nell'implementazione sottostante). Se avete bisogno di espandere l'interfaccia di una funzione esistente aggiungendo nuovi argomenti, lasciate gli argomenti già esistenti nel loro ordine, ed assegnate dei valori di default a tutti quelli nuovi; in questo modo, non creerete problemi a nessuna chiamata già esistente a quella funzione.

18. L'overloading degli operatori è soltanto "zucchero sintattico": un modo diverso per chiamare una funzione. Se l'overloading di un operatore non rende l'interfaccia della classe più chiara e semplice da usare, non fatelo. Per una classe create solo un operatore per la conversione automatica di tipo.

19. Non preoccupatevi di un'ottimizzazione prematura. È pura follia. In particolare, non preoccupatevi di forzare il codice ad essere efficiente quando state appena costruendo il sistema. Il vostro scopo principale è di verificare il progetto, a meno che lo stesso richieda una certa efficienza.

20. Mantenete gli scope più piccoli possibile, in modo che la visibilità e la vita dei vostri oggetti siano le più ridotte possibile. In questo modo, si diminuisce la possibilità di utilizzare un oggetto in un contesto sbagliato e di nascondere un bug difficile da trovare.

21. Evitate, evitate, evitate il più possibile... non ci stancheremo mai di ribadirlo, le variabili globali. Cercate sempre di inserire i dati all'interno delle classi. È più probabile imbattersi in funzioni globali piuttosto che in variabili globali, sebbene potreste rendervi conto in seguito che una funzione globale troverebbe una collocazione più consona come metodo static di una classe.

22. Sfruttate a vostro vantaggio il controllo degli errori effettuato dal compilatore. Compilate il vostro codice abilitando tutti i warning, e correggete il vostro codice inmodo da eliminarli tutti. Scrivete codice che utilizza gli errori ed i warning al momento della compilazione, piuttosto che codice che provochi errori di runtime. Utilizzate assert per il debug, ma a runtime usate le eccezioni.

23. Preferite gli errori di compilazione agli errori di runtime. Cercate di gestire un errore il più vicino possibile al punto in cui si è verificato. È preferibile gestire l’errore in quel punto piuttosto che lanciare un eccezione. Catturate le eccezioni nel gestore più vicino che abbia informazioni sufficienti per gestirle. Fate il possibile con l’eccezione al livello corrente; se in questo modo non risolvete il problema, rilanciatela nuovamente.

24. Non create una vostra notazione “personalizzata” per i nomi delle variabili membro (underscore, prefissi, variazioni fantasiose della notazione ungherese e così via), a meno che non abbiate una gran quantità di variabili globali preesistenti; se così non è, lasciate che le classi ed i namespace svolgano il lavoro per voi.

martedì 27 gennaio 2009

Architects: John Von Neumann, l'Architetto Supremo

E' difficile, molto difficile, scrivere di John Von Neumann... In realtà dovrebbe esserci tanto materiale in rete su questo mito dell'informatica da rendere pressochè inutile aggiungere nulla. E nulla di ulteriore...
Ci si immagina che, essendo John Von Neumann l'Architetto Supremo, colui che ha reso di fatto possibile tutto ciò che possiamo definire come "mondo digitale", Internet compresa, niente debba essere aggiunto.
Ed invece la Rete non omaggia per niente il suo Creatore ...
Vi è pochissimo materiale, per di più assai disorganico, per chiunque voglia approfondire l'argomento. Ma forse non è solo colpa della Rete in verità.
Ho un ricordo personale di quando ebbi uno dei miei primo incontro con il mondo della programmazione e dei calcolatori.
Università, corso di Programmazione dei Calcolatori Elettronici. Von Neumann fu solo una citazione, al volo ed assai superficiale in verità, da parte del professore di turno.
Un sintetico accenno al diagramma (capolavoro di astrazione e semplicità) sull'architettura della MAG (Macchina Astratta Generalizzata), qualche cenno storico sull'ENIAC (il primo elaboratore così come noi oggi lo intendiamo) e via, subito avanti con il corso di programmazione... Fortran 77 ed UNIVAC 1100 (schede perforate!) come elaboratore del Laboratorio di Informatica.
Si dice che Von Neumann disegnò lo schema della MAG in pochi minuti, dopo aver compreso immediatamente che i progettisti di ciò che divenne poi l'ENIAC brancolavano nel buio ... nel buio fitto dell'Assenza dell'Intuizione.

Oggi, quasi sempre, quando si parla di Von Neumann e del suo Supremo Eclettismo (è stato anche uno dei più grandi matematici dell'era moderna), non sono pochi, purtroppo, i professionisti del settore IT che frugano alla rinfusa nella propria memoria.

E stiamo parlando, quando parliamo di Von Neumann, di colui che postulò e rese possibile l'applicazione del bit come unità di misura elementare dell'informazione.

Von Neumann è stato, comunque, senz'altro un genio e come spesso accade per le personalità eccezionali, di certo anche un genio del male.

A lui dobbiamo, infatti, anche la prima sistematica e non disinteressata collaborazione della scienza con l'industria degli armamenti. Ciò tramite un'organizzazione, la Rand Corporation, di cui egli fu uno dei massimi esponenti ed anche, forse, azionista occulto.

Insieme al suo amico, il fisico nucleare Edward Teller, scomparso peraltro di recente, rappresentò l'altra faccia della scienza, quella che negli Stati Uniti proponeva ad ogni riunione strategica presso il Gabinetto Presidenziale, l'esigenza di garantirsi il "primo colpo" durante la cosiddetta Guerra Fredda. In piena aderenza ai principi della Teoria dei Giochi.

I loro avversari, di Teller e Von Neumann, erano i Fermi, gli Oppheneimer, Einstein ed il paradosso era che tutti loro insieme, gli avversari di Von Neumann, che dopo la fine della seconda guerra mondiale assunsero il ruolo di colombe pacifiste, in realtà avevano loro stessi contribuito in maniera decisiva alla creazione del Nucleare Militare.

Molto più dello stesso Von Neumann che vediamo in una foto storica qui di seguito insieme ad Oppheneimer ed all'ENIAC.


Fermi aveva dimostrato la possibilità della reazione atomica di fissione, e sapeva bene, quando replicò l'esperimento negli Stati Uniti, a cosa sarebbe servito.
Einstein aveva addirittura scritto una lettera di preghiera al presidente Roosvelt affinchè si dotasse il progetto Mahnattan dei finanziamenti necessari. Ed Einstein argomentava la richiesta motivandola con la terribile necessità di sconfiggere ad ogni costo il mostro nazista.
Per Von Neumann il mostro da sconfiggere a qualsiasi prezzo sarebbe stato quello comunista.

Oppenheimer, last but not the least, fu lo scienziato dotato di capacità organizzative eccezionali che rese possibile arrivare alla Bomba in pochissimi anni. Il responsabile operativo dell'organizzazione del Progetto Mahnattan. Uno dei pìù grandi Organizzatori della storia, forse in quel periodo secondo solo ad Albert Speer, il Ministro degli Armamenti di Hitler, un altro Architetto. Architeto di Organizzazioni.
Tutti colombe comunque, Einstein e quelli della sua cerchia, dopo il lancio della Bomba...

L'unico demone ufficiale per così dire, però, è rimasto Von Neumann ... dimenticato o meglio omesso. Conosciuto solo dagli specialisti del settore, dai matematici e del tutto ignoto ai più.
Il creatore della Teoria dei Giochi, altro caposaldo fondamentale tra innumerevoli discipline scientifiche, insieme a Nash ... ma questa è ancora un'altra storia...

lunedì 26 gennaio 2009

Enterprise Web 2.0 Agenda del 2009 – Dion Hinchcliffe Predictions

Il guru del Web 2.0, Dion Hinchcliffe, ha di recente pubblicato un abstract delle sue predizioni relative al 2009. Previsioni e trend attese da tutta la comunità mondiale dell'enterprise Web 2.0.
Ovvia premessa … anche Hinchcliffe prende atto della grave situazione economica mondiale, ma con lo spirito tipico degli americani (e l’elezione di Obama, interprete di un auspicato New Deal è significativa in tal senso) anche il guru indiscusso del Web 2.0 mondiale ritiene che, dal punto di vista dell’IT, si sia di fronte ad una singolare chance.

Chance è un termine che esiste sia nel vocabolario francese sia in quello anglosassone.

Per i francesi ha più il significato di destino, fato.

Per gli anglosassoni significa prevalentemente sfida, opportunità.

… e da come sta reagendo il Vecchio Continente alla crisi mondiale si comprende la netta differenza tra i Due Mondi …
L’Europa sta attendendo il suo destino in una sostanziale inazione, aspettando che, per così dire, passi la bufera…
L’America sta cercando invece attivamente la sua chanche, sfida…

Ed il Web 2.0, per gli statunitensi, rappresenta una delle opportunità più chiare, certe e definite in ambito di web technologies.

Opportunità peraltro estremamente pragmatica e concreta.
Lo schema precedente di Hinchcliffe è chiaro ed immediato.
Solo due note ci interessa quindi sottolineare del suo articolo (che può essere visionato integralmente al link http://blogs.zdnet.com/Hinchcliffe).

Le piattaforme di Social Network, secondo Hinchcliffe, conviene estenderle e dispiegarle soprattutto:

  • verso ed in integrazione con i sistemi CRM, che già hanno necessità vitale di espandere la qualità dell’interazione con i Clienti (gestire in sostanza quello che i Call Center non sono stati in grado di gestire in questi anni)

  • per la condivisione della conoscenza interna alle aziende (le piattaforme di collaborazione lavorano più efficacemente in modalità Wiki e su sistemi basati su criteri di social networking in integrazione e collaborazione con il mondo esterno – vedi caso del R&D della Procter & Gamble esternalizzato in modalità Wiki).

In questa ottica sono purtroppo assai sintomatici gli atteggiamenti di chiusura (blocco delle porte Internet, per i loro dipendenti, verso tutte le piattaforme Web 2.0 come Twitter, Facebook, You Tube, Instant Messanging come Microsoft Messenger…) che molte aziende europee stanno attuando in maniera sistematica nei confronti del Web 2.0 che dilaga ormai su Internet.

Dilagano e si espandono le piattaforme Web 2.0 e come tutte le novità tecnologiche fanno anche un po’ paura!!!

Vi è di certo un equivoco su cosa sia il Web 2.0 e di come siano acceleratori virali e catalizzatori di conoscenza (Internal Knowledge) le reti sociali e non si comprende quindi la chiusura anche dei mass media (vedi sempre le campagne aggressive di denigrazione di Facebook sui media tradizionali - stampa e televisione soprattutto - anche se in quel caso forse si è dinanzi ad una battaglia tra competitor!) verso tali tecnologie.

In fondo, però, tale atteggiamento di chiusura era lo stesso che le aziende e non solo loro avevano anni fa verso tutto il mondo Internet nella fase iniziale della sua espansione.
Il paradosso estremo poi è che spesso le aziende che bloccano e chiudono piattaforme come Facebook o Messenger sono le stesse che stanno magari progettando di vendere o fornire, ai loro stessi Clienti, piattaforme di collaborazione Web 2.0!!!
E’ evidente la contraddizione e quindi si è fiduciosi, insieme a Dion Hinchcliffe, che tali comportamenti, se vogliamo in fondo anche schizofrenici, prima o poi saranno riconsiderati…

 
Extension Factory Builder