lunedì 29 settembre 2008

Architettura IT e Architettura Civile

Mia moglie fa l'architetto - quello vero! - e spesso mi fa vedere libri illustrati sulle opere architettoniche dei nostri tempi. Io solitamente non ci capisco molto, né riesco ad emozionarmi come fa lei. Una cosa però intuisco: che le architetture edilizie, rispetto alle architetture IT sono sostanzialmente più evolute.

Si capisce molto bene, vedendo un'opera di Renzo Piano o di Fuksas, che il requisito di un'architettura civile non è (non è soltanto, diciamo) la funzionalità, ma vi sono anche requisiti di bellezza, originalità, integrazione col contesto.

La differenza sostanziale tra l'architettura civile e quella informatica è che la prima di solito "funziona" (nel senso che assolve la sua funzione primaria, quella cioè di costituire una o più unità abitative) e di fatto "dura nel tempo".

Le architetture informatiche, anche quelle più complesse e con costi paragonabili a quelli dell'architettura civile, solitamente invece "non funzionano" (nel senso che non riescono a tradurre al 100% i requisiti funzionali in software) e, soprattutto, "non durano" - difficilmente un sistema informatico dura più di cinque anni, quasi mai dura più di dieci.

Come mai quindi l'industria spende milioni di dollari in sistemi informatici che non durano e che non funzionano? La risposta è piuttosto semplice: in questo campo umano, molto semplicemente, non esistono alternative. Noi architetti IT progettiamo "al meglio" quanto la tecnologia e l'ingegneria informatica oggi consentono di fare. In altre parole, come dicevo prima, l'architettura dei sistemi informativi è una scienza relativamente giovane, e come tale, largamente immatura.

Dobbiamo accontentarci di fare, dunque, spallucce, e realizzare quei sistemi qualitativamente pessimi a cui l'industria dei sistemi IT enterprise ci ha abituati?

Io credo di no. E suggerisco, umilmente s'intende, due linee guida (noi architetti IT siamo, questo sì, veramente bravi nel produrre Guidelines!) per migliorare la qualità complessiva dei progetti.

La prima è ovvia, ma sempre trascurata. Premiare la semplicità. Se andate da qualche responsabile IT di una media o grande impresa, vi accorgerete che non riuscirete facilmente a vendere cose semplici. Esistono pochi requisiti informativi enterprise che non siano in realtà soddisfacibili con uno script shell o al massimo con un programma in Python (o in Ruby, guardate per esempio alla lezione di Ruby On Rails), affiancato a un buon database e ad un buona tecnologia di front-end. Ma molto difficilmente riuscirete a vendere qualcosa che non si appoggi a J2EE (una delle tecnologie peggiori e più inutilmente complesse che siano mai state prodotte dall'Uomo) e che non richieda hardware secondo solo a quello della NASA. Credo che questa necessità di complessità sia in qualche modo correlata all'idea che si ha dei computer e del software come qualcosa di oscuro e di magico, campi esoterici in cui il Segreto e il Mistero sono connaturati alla soluzione che si va proponendo.

Della seconda ho parlato nel mio blog precedente a proposito del mio macellaio. Avremo, io credo, un balzo nella qualità dei sistemi informativi quando abbandoneremo del tutto l'idea (presuntuosa e sempre disattesa) di poter stimare il loro valore economico a preventivo. So di dare un dispiacere ai venditori di (complessissime!) metodologie che vorrebbero calcolare a priori il costo o il valore di un progetto informatico: ogni anno vengono pubblicati studi che confermano che questo è un campo del sapere in cui semplicemente non siamo in grado di fare previsioni! Non siamo in grado e non abbiamo una metodologia in grado di stimare il costo di un progetto informatico a partire dai suoi requisiti e dall'analisi funzionale. Come nella meteorologia, in un progetto informatico di medie o grosse dimensioni, le variabili sono talmente tante, che non è possibile tenerle tutte in conto. Perciò ogni previsione è destinata in genere a naufragare.

Per rispondere seriamente e onestamente alla domanda: "quanto costa" occorrerebbe applicare analisi statistiche da confermare con successivi ricicli ad ogni milestone del progetto, convincendo la controparte che - agli stadi iniziali - non si possono avere idee precise sui costi, e che darne una "spannometrica" equivale più o meno a mentire.

Quando ero ancora un ragazzino, il mio datore di lavoro, che fu tra i primi in Italia a proporre soluzioni di Workflow, aveva un metodo infallibile per stimare il prezzo a cui vendere una soluzione software: "Vedi" mi diceva sorridendo "io cerco di capire quanti soldi il mio cliente ha nel portafoglio, e poi cerco di prenderglieli tutti".

Benché tecnicamente ingiustificabile, e moralmente discutibile, questo approccio aveva se non altro il merito dell'onestà intellettuale.

giovedì 11 settembre 2008

Il costo del prosciutto

In questi giorni mi sto occupando del processo di costing di un'iniziativa di upgrade tecnologico e SOA-enabling piuttosto complessa.

Ci pensavo ieri sera, mentre andavo dal mio salumiere per un etto di prosciutto. Pensavo che se il processo di costing che adottiamo nell'industria del software dovesse essere applicato al prosciutto, molto probabilmente questo genere alimentare - di cui sono particolarmente appassionato - sparirebbe.

Mi immaginavo già la scena mentre entravo nel piccolo salumierino del mio paese.
Entro e saluto il ragazzo al banco. “Vorrei del prosciutto...” dico.
“Ah, le chiamo subito il salumiere capo” - Project Management, costo 2 euro.
“Buonasera sig.Saltarin, cosa le va di mangiare stasera?” - Technical Proposal, costo 1 euro.
“Mah, pensavo a del prosciutto...”
“Ma, mi scusi, del prosciutto cotto o del prosciutto crudo?” - Feasibility, costo 2 euro.
“Del crudo” e sorrido terrorizzato sapendo cosa mi aspetta.
“Ah, guardi, ho del Parma dolcissimo, assaggi... assaggi!” - Proof Of Concept, costo 2 euro.
“Mmm, buono... va bene, lo prendo!”
“Benissimo, sig. Saltarin! E lo vuole al fiocco, o all'osso?” - Functional Specification, costo 3 euro.
“Mah, non saprei... al fiocco?”
“Chiamiamo il Mauro” - il Mauro è l'aiuto salumiere (Development Team)
“Ah, lo so io cosa vuole il Sig. Saltarin” dice il Mauro “un etto bello dolce vicino al fiocco” - Architectural Specification, 3 euro.
“Taglio?” Faccio di sì terrorizzato con la testa.
E il Mauro taglia - Development, 5 euro + 1 etto di prosciutto crudo di Parma, 2 euro.
Le fette cadono sottilissime sulla carta da salumeria - Deployment, 2 euro.
“E mi faccia sapere se era buono!” - Testing, 1 euro.
“In tutto” dice il mio salumiere “fanno 23 euro, con lo sconto facciamo 20! Contento?”
“Mah, tutto sommato forse, guardi, è meglio che vado in Pizzeria...”
“Ma cosa fa, sig. Saltarin, si dà all'outsourcing?”

lunedì 31 marzo 2008

Scala e i suoi fratelli

Da qualche tempo guardo con interesse ai nuovi linguaggi che fanno la loro comparsa nel variegato orizzonte della programmazione dei computer. Tra gli altri, soprattutto Scala.

Giusto due note a proposito: che sono, lo sottolineo, del tutto soggettive.

La prima: il paradigma della programmazione funzionale non soppiantera' il paradigma a oggetti. Infatti il successo della programmazione a oggetti deriva dal fatto che l'essere umano,normalmente, pensa per oggetti e relazioni tra oggetti, e non per funzioni. Tranne casi particolari (il matematico, il fisico) l'uomo non pensa a un problema in termini funzionali (e men che meno di funzione di funzione, o di funzione di funzione di funzione...)

La seconda: dopo Java (e C#) il panorama dei linguaggi per computer e' abbastanza statico, e ho l'impressione che i nuovi venuti non portino significativo valore aggiunto. Ho l'impressione che oggi il focus si debba spostare dai linguaggi alle API. Il successo di Java, e poi del .NET Framework, si deve all'efficacia e all'ampiezza delle loro API piuttosto che delle specifiche tecniche del linguaggio. Francamente, al programmatore medio importa assai poco delle closures piuttosto che delle list comprehensions. Se invece riesce a creare un file e poi zipparlo in due linee di codice il discorso cambia...

Inoltre, il sempre maggior peso della UI (sia lato desktop che lato Web, il che ho l'impressione che prossimamente sara' la stessa cosa...) privilegia quei linguaggi e piattaforme che permettono di realizzare facilmente le interfacce grafiche e di integrarle con la business logic dell'applicazione.

In questo senso, il .NET Framework con il suo supporto a Silverlight attraverso XAML e il WPF, e dall'altra parte Adobe con AIR/Flex per Flash, siano i veri nuovi protagonisti della scena.

mercoledì 5 marzo 2008

Se starnazza come un'anatra...

... allora è un'anatra!

No, non sono diventato un membro del club degli ammiratori di Massimo Catalano (ricordate "Quelli della notte"?). E' solo un modo per esprimere un concetto che differenzia i linguaggi a oggetti di scripting da quelli compilati. I primi genericamente sono blandamente tipizzati, i secondi invece fortemente tipizzati. Questo impatta sul discorso delle interfacce che facevo in precedenza: nel primo caso (Ruby o Python, ad esempio) il fatto che io esprima un'interfaccia dei miei oggetti è solamente un aiuto che do a chi legge il mio programma: gli comunico esplicitamente come ho pensato il design a oggetti della mia soluzione. Nel secondo caso (Java o C#, ad esempio), senza un'interfaccia, il metodo polimorfico semplicemente non funziona.

Nel secondo caso, per tornare alle anatre, bisogna dire al compilatore: guarda che ti sto passando un'anatra, comportati di conseguenza! Nel primo, all'interprete, non dico niente: se starnazza come un'anatra, allora è un'anatra. Punto e basta.

Un esempio polimorfico in Java e in Ruby ci può aiutare a capire meglio. Cominciamo da un linguaggio fortemente tipizzato come Java:


package anatre;

import java.util.ArrayList;
import java.util.Collection;

interface IGallinaceo
{
String starnazza();
}

public class Anatra implements IGallinaceo
{
@Override
public String starnazza()
{
return "Sono un'anatra e starnazzo!";
}
}

public class Oca implements IGallinaceo
{
@Override
public String starnazza()
{
return "Sono un'oca e starnazzo!";
}
}


public final class Cortile
{

public static void main(String[] args)
{
Collection<IGallinaceo> cortile =
new ArrayList<IGallinaceo>();

cortile.add(new Anatra());
cortile.add(new Oca());
cortile.add(new Anatra());

for (IGallinaceo gall : cortile)
{
System.out.println(gall.starnazza());
}
}
}



Come si vede, le due classi Ocae Anatra implementano esplicitamente l'interfaccia IGallinaceo, cioè sono (IS-A) a tutti gli effetti dei Gallinacei e il compilatore lo sa a compile-time.

Vediamo lo stesso esempio in Ruby.


class Oca
def starnazza
return "Sono un'oca e starnazzo";
end
end

class Anatra
def starnazza
return "Sono un'anatra e starnazzo"
end
end

cortile = Array.new
cortile.push(Anatra.new)
cortile.push(Oca.new)
cortile.push(Anatra.new)

for animale in cortile
puts(animale.starnazza)
end


Qui semplicemente io passo una serie di classi al mio metodo polimorfico, e mi limito a richiamare il metodo "starnazza". Se facessi questa cosa in Java avrei un errore di compilazione! Invece, all'interprete Ruby non interessa che io "affermi" che un'Anatra è (IS-A) un Gallinaceo: se starnazza, allora lo è. Si fida! (Beato lui). E se gli passo un oggetto che non implementa "starnazza"? Be', semplicemente avrò un errore a run-time.

Si tratta dunque di due filosofie diverse: nella prima, io devo dichiarare sempre la classe dell'oggetto passato a un metodo, nella seconda posso farne a meno. Non c'è chiaramente una soluzione migliore dell'altra: nel primo caso privilegio le performance, e nel secondo la flessibilità del design.

(E se avete dei dubbi sul fatto che Oche e Anatre starnazzino, date un'occhiata qui!)

martedì 22 gennaio 2008

Mixin come interfacce in Ruby

Un utilizzo forse un po' anomalo dei mixin in Ruby è quello di considerarli alla stregua di interfacce per implementare un comportamento polimorfico.

Chi conosce almeno un linguaggio a oggetti puro (come Java o C#) sa che le interfacce sono dei contratti che il programmatore stipula con l'utilizzatore del suo codice sorgente per garantirgli che una classe "implementa" certi metodi, con certi parametri. Le interfacce sono alla base dell'utilizzo del polimorfismo nei linguaggi a oggetti compilati.

In genere nei linguaggi di scripting a oggetti, possiamo utilizzare il polimorfismo anche senza le interfacce, cioè ammettendo che, se l'oggetto passato al metodo polimorfico non implementa determinati metodi, avremo un errore a run-time.

In realtà a volte può essere difficile se non impossibile, non avendo a disposizione ad esempio il commento di un certo codice sorgente, sapere se una certa classe è stata progettata per un utilizzo polimorfico.

Bene, grazie ai mixin, noi possiamo rendere esplicita la nostra intenzione di voler far implementare a una classe una determinata interfaccia, o, in altri termini, ad assicurare il programmatore che utilizzerà il nostro codice, che questo utilizza un certo modulo come interfaccia, quindi garantendo che i metodi in quel modulo saranno implementati.

Ad esempio:


module Animale
def mangio
puts "Sono un animale e mangio"
end
end

class Uccello
def volo
puts "Sono un uccello e volo"
end
end

class Gazzella < Uccello
include Animale

def mangio
puts "Sono una gazzella e mangio"
end
end

def metodopolimorfico(animale)
animale.mangio
end

metodopolimorfico(Gazzella.new)

In questo codice noi abbiamo una classe di Gazzelle che eredita dalla classe base Uccello. Qui il programmatore vuole dirci che Gazzella è (IS-A) sì un Uccello, ma è "anche" un Animale (infatti implementa "mangio"). In questo modo il client-programmer che vuole sapere se potrà passare una "Gazzella" al suo metodo "metodopolimorfico" che prende in ingresso un "Animale" è assicurato: siccome Gazzella è un mixin di Animale, sicuramente rispetta l'interfaccia di Animale (che nel nostro caso è il metodo mangio).

Non solo: Gazzella può fare l'override di un metodo incluso. Infatti lo fa, e "mangio" di Gazzella ha un'implementazione diversa da "mangio" di Animale. Chiaramente, poteva anche non farlo, mantenendo l'implementazione originale (e qui sta la differenza con le interfacce, che sono sempre astratte e vanno sempre e comunque implementate).


sabato 19 gennaio 2008

Nuovo anno, nuovo blog

Avevo cominciato con l'idea "peregrina" di tenere separato il blog diciamo così delle attività lavorative, che sarebbe questo, dal blog delle attività extra (ho scritto "letterarie" ma poi ho eliminato a furia di backspace), con il risultato che scrivo poco su quello e su questo.
Comunque: il blog "altro" è qui: Fogli sparsi
Ma quest'anno ho intenzione di fare un po' di casino e mescolare i due mondi (i tre mondi, dovrei dire: informatica, letteratura e poesia... aaargggh).
Del resto, come dice Lucilla, lo scrittore e il poeta è morto da tempo, e ora possiamo dare vita a una campagna pubblicitaria ex post....