Agile Day 2011

Anche quest'anno eccomi a stilare il mio personalissimo resoconto dell'Agile Day.
In primo luogo vorrei ringraziare gli organizzatori, che hanno svolto un lavoro perfetto. Se non ci siamo "accorti" di voi è perché tutto ha funzionato al meglio: bravi!
Ed ora mia una interpretazione delle sessioni a cui ho partecipato.

Back to basics: OOP and design

Il senso dell'intervento di Paolo Polce sta tutto nel titolo: dopo anni spesi a concentrarsi sul processo, abbiamo forse perso di vista i problemi tecnici, quasi fossero semplici dettagli implementativi. Scrum masters, sprints, story points, sì, vabbè, ma il codice? Beh, al codice ci penseranno le "risorse"... :-)
E' tempo di tornare a focalizzarsi sulle "risorse", ovvero sui programmatori, e sulle loro competenze, che devono costantemente essere allenate, come i muscoli di un atleta.
Come ottenere lo scopo? Con buone letture, buoni strumenti, ed un continuo esercizio volto a creare design realmente ad oggetti. Una buona architettura Object Oriented modularizza i problemi tramite gli oggetti, ed evita quindi classi "Star gate" (spesso incarnate da dei Singleton), che leggono attraverso una pioggia di getter le informazioni più disparate, collassando al loro interno l'intera logica applicativa. Occorre quindi evitare i getter, scrivendo sempre più metodi che restituiscono void. Ma come testare queste architetture? La chiave consiste nel passare da test sullo stato degli oggetti, a test che ne verificano le interazioni.

Codice legacy: usciamo dal pantano!

Bel workshop di Stefano Leli e Simone Casciaroli. I partecipanti sono stati invitati a fare refactoring su un piccolo progetto, che nella gerarchia Bird-Duck-Chicken mostra un caratteristico caso di violazione del Principio di sostituzione di Liskov, il complesso edipico irrisolto della programmazione ad oggetti.
La sessione, terminata con la presentazione della soluzione dei relatori, è stata interessante, anche se avrebbe richiesto sicuramente almeno un'altra ora per riuscire al meglio.

Lean, A3 e kaizen

Claudio Perrone nel suo intervento ha illustrato i i Kaizen Memo ed il medoto A3.
I Kaizen Memo sono piccoli fogli di carta da appendere su una parete per dare evidenza ai miglioramenti raggiunti nel processo produttivo. Dovrebbero riportare il problema affrontato, la misura intrapresa per risolverlo e le conseguenze ottenute.
Il metodo A3 prevede di utilizzare un modulo di carta, solitamente di dimensione appunto A3, sul quale presentare in modo oggettivo:

  • la situazione corrente;
  • l'obiettivo da raggiungere (ciò definisce il problema come differenza tra situazione corrente ed obiettivo da realizzare);
  • l'analisi delle cause del problema;
  • l'elenco delle contromisure da adottare;
  • una matrice what-who-where-how per realizzare le contromisure;
  • un elenco di azioni supplementari (follow-up) da intreprendere in caso di problemi.

L'intervento è proseguito definendo la figura del manager ideale, che non dovrebbe essere né un poliziotto che punisce chi si comporta male, né una mamma che coccola i suoi figli, e neppure una figura assente. Il vero manager dovrebbe invece essere una persona che si occupa di eliminare i problemi che ostacolano il processo produttivo. La domanda che un manager dovrebbe rivolgere ai suoi sottoposti non è "cosa hai prodotto ieri", ma "quali problemi hai avuto".
Claudio Perrone ha concluso dando una bella definizione dei metodi lean/agili: strumenti per fare soldi attraverso la crescita delle persone.

Back to basics hands-on

Antonio Carpentieri e Paolo Polce hanno condotto un efficace workshop sul design ad oggetti. Utilizzando come esempio il gioco del monopoli, hanno mostrato nella pratica come realizzare software ad oggetti senza abusare di getters e favorendo composizione, basso accoppiamento ed alta coesione.
Molto importante la sottolineatura finale di Antonio Carpentieri che ha ripreso il keynote di Paolo Polce: un programmatore non può crescere lavorando solo su codice di produzione. Come un atleta non migliora solo con le partite, ma soprattutto con gli allenamenti, anche chi sviluppa software non può non allenarsi praticando i kata.

Unit Tests VS End to End Tests

Probabilmente il mio giudizio su questo intervento è falsato dalla fatica accumulata alla fine di una giornata così intensa, ma dalla presentazione di Domenico Musto non sono riuscito a trarre nessuna informazione interessante. Chiedo venia.

Conclusioni

Anche questa edizione dell'Agile Day è stata all'altezza delle aspettative. Mi è piaciuta molto l'enfasi sul codice, dopo troppo tempo speso sui problemi di processo. Grazie ancora agli organizzatori ed arrivederci al 2013!

Porte IBM Client Access per AS400

Uso questo post come promemoria per l'elenco delle porte usate da IBM Client Access, conosciuto anche come IBM i Access.
Ricapitolando, le porte indispensabili per l'emulazione video sono

  • Server Mapper - 449
  • License Management - 8470
  • Signon Verification - 8476
  • Telnet - 23

Per ODBC/JDBC

  • Server Mapper - 449
  • Signon Verification - 8476
  • Database - 8471

Ecco l'elenco completo delle porte

Funzione Nome server Non-SSL SSL
Mappa porte servizi as-svrmap 449 449
Gestore licenze as-central 8470 9470
Database as-database 8471 9471
Code dati as-dtaq 8472 9472
Accesso ai File as-file 8473 9473
Stampa di rete as-netprt 8474 9474
Comando remoto as-rmtcmd 8475 9475
Verifica collegamento as-signon 8476 9476
Telnet (emulazione 5250) telnet 23 992
Amministrazione HTTP as-admi 2001 2010
Management Central as-mgtc 5555 and 5544 5566
DRDA DRDA 446 ---
DDM DDM 447 448
NetServer netbios 137 ---
NetServer CIFS 445 ---
NetServer netbios 139 ---
Service Tools Server as-sts 3000 ---
RUNRMTCMD REXEC 512 ---

L’apostata del TDD

Ho seguito con molto interesse la discusione generata da un post che vuole essere iconoclasta già nel titolo: l'apostata del TDD. Vorrei sottoporvi le mie annotazioni.

Perché il post mi pare interessante

Perché il post mi pare interessante? Perché tocca le corde della mia esperienza personale: anche io, come l'autore, ho provato curiosità nel notare di aver sviluppato a volte del buon codice senza l'uso del TDD e del pessimo codice con il TDD. Posto che è plausibile che problema risieda in me e non nel metodo, mi pare lecito comunque chiedersi se anche il metodo stesso non abbia qualche pecca. Provo infatti un certo fastidio quando, durante l'analisi di fallimenti del TDD (e mi pare che comunque ve ne siano), si escluda dogmaticamente che lo strumento possa avere qualche difetto. Tutto questo mi ricorda le critiche che (inutilmente) qualcuno negli anni 70 muoveva a psicanalisi e marxismo: ci si chiedeva infatti se fosse possibile che queste dottrine fossero di per sè corrette, mentre ogni loro clamorosa debacle si dovesse addebitare sempre ad una loro incorretta realizzazione, pienamente giustificabile ed interpretabile all'interno delle dottrine stesse.

Cosa non funziona nel TDD?

Ma allora cosa ci sarebbe di sbagliato nel TDD? Non so se vi sia qualcosa di "sbagliato", sicuramente indagherei su questi punti.

La visione d'insieme

Riprendendo quanto detto da Carlo Bottiglieri sulla lista extremeprogramming-it, il TDD potrebbe far perdere la visione d'insieme del problema, o anche problematiche trasversali all'intero sistema.

Cicli troppo stretti

Il TDD si basa sul "mantra" "red-green-refactor", che però, nella sua definizione, prevede di essere un ciclo di breve durata, per consentire un riscontro immediato. Ciò a mio avviso implica che la fase di refactor non possa spostare di molto l'"inerzia" del sistema: ciclo breve, refactoring breve, quindi spesso indirizzato a piccoli obiettivi. Il refactoring, inoltre, nascendo come "cura" per le puzze del codice, a risulta uno strumento di ottimizzazione locale: diminuisco la lunghezza dei metodi ed il numero di parametri, creo classi disaccoppiate, ottimizzo gli indicatori "locali" di qualità, ma la struttura generale è comprensibile e riutilizzabile?

Coesione vs accoppiamento

Durante un suo corso, Francesco Cirillo mi ha fatto riflettere su questo concetto: del buon codice deve essere ad alta coesione e a basso accoppiamento, ma vi è una tensione tra i due aspetti. Il mio dubbio è: il TDD tende a sistemi a basso accoppiamento, ma forse anche a bassa coesione?

No Big Upfront Design?

Il TDD ha viaggiato a braccetto con il concetto di "No Big Upfront Design", anche nella sua variante "non facciamo design prima di scrivere il codice, ma solo scrivendolo". Ma siamo proprio sicuri che il codice sia il l'unco luogo, o comunque quello ideale, dove disegnare il codice stesso?

Il lato oscuro dei test

Non dobbiamo dimenticare quello che Matteo Vaccari chiama "il lato oscuro dei test": paradossalmente un sistema copero al 100% da test potrebbe invitarci a scrivere codice "peggiore", in quanto, qualsiasi schifezza volessimo introdurre, avremmo sempre la certezza di non rompere nulla.

Sono anch'io un apostata?

Non so se dirmi apostata anch'io: forse non posso, non essendo mai stato un fedele praticante. ;-)
Sicuramente diffido di chi ha fatto del TDD una religione, o meglio un feticcio.
Forse, riprendendo la bella analogia di Jacopo Romei, sono nella fase "Ha – Vìola la regola" del ciclo "Shu-Ha-Ri": sto cercando di mettermi in opposizione al TDD, al fine di capirlo meglio.
Certamente vorrei saper usare il TDD come Carlo, ma a volte mi chiedo se questo non sia un tipo di programmazione che solo dei grandi virtuosi sono in grado di svolgere.
O forse sto ancora ricercando la mia via e sono ancora molto lontano anche dalla fase "Shu"...

Italian Agile Day 2010

Anche l'Italian Agile Day del 2010 è stato un bellissimo evento, e vorrei darne qui il mio personalissimo resoconto.

Keynote

Paolo Perrotta ha condotto con brio ed intelligenza un bellissimo escursus su come, nel corso del tempo, sia stato affrontato il problema di ridurre i fallimenti nei progetti software.
Un primo tentativo si è basato su un mito: i progetti falliscono perché gli strumenti di programmazione sono troppo complessi, tant'è che richiedono degli specialisti come i programmatori per essere realizzati. Se solo potessimo eliminare i programmatori...:-) Si cerca così soppressione dei programmatori tramite strategie che si chiamano di volta in volta SOA, UML, CASE; persino il Cobol è nato per scrivere programmi senza avere programmatori! Tutti questi tentativi si sono però scontrati contro un medesimo scoglio: scrivere algoritmi che vengano eseguiti è qualcosa di intrinsecamente complesso.
Si è anche pensato di controllare il fallimento eliminando la componente di errore umano. Nascono quindi i metodi formali di verifica di correttezza del software, che comunque non sembrano aver avuto molto successo.
Si è quindi pensato di eliminare la variabilità dei progetti irregimentando lo sviluppo all'interno di procedure ben determinate. Ecco allora nascere metodi di lavoro come il Waterfall, che conteneva alle sue origini idee apprezzabili come la valorizzazione delle persone e l'enfasi sul test anche automatizzato del codice. Waterfall, come molte altro processi di sviluppo, si sono nel tempo "distorti" nel loro divenire strumenti di successo. Anche "Agile" subirà la stessa fine? Forse sì, ma sicuramente lascerà qualcosa di buono alle sue spalle. Il seme "Agile" consiste nell'idea non eliminare, ma di accettare la variabilità dei progetti, scomponendoli in piccole parti, ognuna delle quali attraversa tre fasi (il corsivo indica mie ipotesi)

  1. Osservazioni (user stories)
  2. Ipotesi (codice)
  3. Verifica sperimentale (test)

Questo è il cuore dei "Metodi agili", che è destinato a rimanere perché non è altro che il cuore del metodo scientifico.

Affiliamo i nostri strumenti: un test driver fatto in casa

In questa interessante sessione Jacopo Franzoi ha illustrato la sua esperienza nell'introdurre in un progetto reale i test unitari anche in quel regno dimenticato costituito dalle interfacce web.
Jacopo è infatti riuscito a creare una mini libreria per testare le pagine generate tramite FreeMarker.
Il messaggio è stato chiaro: anche in ambienti apparentemente ostili, come lo sviluppo di pagine web, è possibile crearsi strumenti che consentano di testare le nostre applicazioni. La sovrabbondanza di dettagli implementativi, che probabilmente sono sfuggiti a chi non ha mai utilizzato il particolare strumento di template in esame, è forse stato l'unico piccolo neo nella presentazione.

Code Kata Live

Una brillante presentazione di Gabriele Lana sui code Kata ha introdotto la perfomance di Giordano Scalzo e Tonino Lucca.
Tesi centrale dell'esposizione di Gabriele: il talento non è (solo) innato, bensì sgorga da un esercizio costante. Perché l'esercizio giunga a dei risultati occorre che:

  1. sia sfidante: ogni prova deve essere leggermente più difficile delle precedenti, senza però essere frustrante;
  2. sia ripetuto;
  3. abbia un riscontro da parte di altri, sia da persone più esperte, che sappiano dare suggerimenti, sia da persone meno esperte, che possano dare opinioni non convenzionali.

Ripetere incessantemente buoni esempi ci consente di passare dal codice "quick and dirty" al codice "quick and clean". Quando le nostre abilità sono limitate, il codice "dirty" ci risulta "quick" perché non sappiamo fare altro. Al crescere delle nostre competenze invece, il codice "clean" ci dovrebbe risultare più "quick", cioè più veloce e naturale da scrivere di quello "dirty".

Guelfi versus Ghibellini


"Noi tutti dobbiamo essere animati da un grande desiderio di competere fra noi per sapere cosa sia il vero e cosa il falso sull'argomento che stiamo trattando; è infatti comune interesse che ci sia chiarezza su questo punto.
Mi accingo ad esporre il mio pensiero; se a qualcuno di voi sembra che io ammetta cose non vere, costui dovrà interrompermi e confutarmi. Del resto io non dico le cose che dico forte di una verità di cui sono sicuro, ma ricerco assieme a voi; pertanto, qualora il mio oppositore mi paia avere ragione, sarò io il primo a riconoscermi d'accordo con lui."

Questo passo del Gorgia di Platone è perfetto per descrivere il messaggio che Sergio Berisso, coaudiuvato da Tonino Lucca, ha voluto indicare nella sua presentazione interattiva. Occorre affrontare le retrospettive, ed in genere tutti i momenti di riflessione e confronto dei gruppi di sviluppo, con questo spirito costruttivo, cercando di trovare i punti di sintesi comuni tra visioni discordanti.

Open space sul Kata "Sasso-forbici-carta" svolto secondo le regole "Aperto-Chiuso"

In un angolino molto defilato, io e l'amico Marco Testa dell'XP User Group di Bergamo abbiamo provato a rifare il Kata "Sasso-forbici-carta" seguendo le regole "Aperto-chiuso" suggerite da Matteo Vaccari. Il pubblico non era certo numeroso...ehm...ehm...vabbe', se vi interessa qui sono le slides e questo è il codice.

TDD per le viste

Questa è stata sicuramente la presentazione più interessante fra quelle da me seguite nella giornata: valeva la pena di partecipare all'Agile Day solo per sentire Matteo Vaccari e Carlo Bottiglieri tenere questa lectio magistralis sul TDD.
TDD spinto sino alle estreme conseguenze: Matteo ha infatti mostrato come gestire con questa tecnica anche la produzione di interfacce HTML, mentre Carlo ha dato un esempio di come costruire partendo dalle fondamenta dei test ogni singolo aspetto dell'architettura di un'applicazione, inclusa l'interfaccia Javascript e l'ambiente di esecuzione dell'application server. Geniale l'idea di Carlo di simulare in un test l'occhio dell'utente che guarda la videata! Non so se questa visione radicale del TDD sia realmente applicabile da noi comuni mortali, ma sono certo che il suo fascino mi rimarrà impresso a lungo.
Ecco il link alle slides di Matteo, mentre rimango in attesa spasmodica di quelle di Carlo.

Conclusioni

Ancora una volta l'Italian Agile Day si è dimostrato un evento eccezionale: complimenti agli organizzatori e arrivederci alla prossima edizione! (A Roma? Io, voto per un Genova-bis! Ma a Milano proprio no???)

P.S. Ricevo da Carlo il link alle sue slides. Ragazzi, non perdetevele!!!

Esportare le definizione delle stampanti su un altro AS400

Per copiare la definizione delle stampanti (o in generale di device) da un AS400 ad un altro è possibile seguire il procedimento seguente.

Sull'AS400 di partenza digitare

SAVCFG TAP01

dove TAP01 è l'identificativo dell'unità nastro da utilizzare (è possibile far ricorso anche ad un save file)

Sull'AS400 di destinazione, dopo aver inserito il nastro su cui la configurazione di partenza è stata memorizzata, digitare

RSTCFG OBJ(NOME_STAMPANTE)  DEV(TAP01)  OBJTYPE(*DEVD)  SRM(*NONE)

Si noti che NOME_STAMPANTE può essere generico: ad esempio PRT* indica tutte le stampanti il cui nome inizia per PRT.

ATTENZIONE: È MOLTO IMPORTANTE INDICARE IL PARAMETRO SRM(*NONE), altrimenti la configurazione ripristinata potrebbe essere inutilizzabile.

In alcuni casi i device potrebbero non essere ripristinati perché il nome dell’unità di controllo è differente tra i due sistemi. In questo caso occorre quindi ripristinare anche l’unità di controllo con il comando:

RSTCFG OBJ(NOME_UNITA_CONTROLLO)  DEV(TAP01)  OBJTYPE(*CTLD)  SRM(*NONE)

Spegnere la luce di attenzione arancione dal Service Action Log di AS400

- Collegarsi con l'utente QSECOFR di sistema operativo.

- Digitare dalla riga comandi STRSST

- Inserire l'utente e password di manutenzione DST richiesti

Type choice, press Enter.  

Service tools user ID. . . . . QSECOFR
Service tools password . . . xxxxxxx (case sensitive)

- Selezionare Start a service tool / Avvio di un programma di manutenzione
(opz.1)

- Selezionare Hardware Service manager / Programma di manutenzione hardware
(opz.7)

- Selezionare Work with service action log / Gestione delle registrazioni
delle azioni di assistenza (opz.6)

- Dare la data di inizio ricerca errori più vecchia possibile (installazione del sistema ) fino alla data attuale, quindi invio.....

- Verificare gli errori che appaiono sul sito INFOCENTER

- Spegnere la luce di attenzione facendo l'acknowledge dei problemi
F6=Acknowledge All Errors / Ricezione di tutti gli errori

- Rimuovere tutti gli errori presenti , uno alla volta, utilizzando l'opzione 8 di Close (Chiusura) e poi 9 di Delete (Cancellazione).
Se non ci sono errori nella pagina ma è presente la funzione F6 fare comunque l'acknowledge per spegnere la luce.
Verrà richiesto un F10 di conferma

- Una volta eseguito l'Acknowledge(Ricezione) appare sul fondo della videata la scritta: All errors have been acknowledged / Tutti gli errori sono stati ricevuti (a questo punto la luce si dovrebbe essere spenta)

Too many illegal datagrams from the remote computer AS400

A volte nei log di sistema dei server Windows che convivono in una subnet con un AS400 può comparire il seguente errore:

"The browser driver has received too many illegal datagrams from the remote computer YOUR_AS400_NAME to name xxxx on transport NetBT_Tcpip_{DF3149C4-A44D-493F-BD8C-BE3B. The data is the datagram. No more events will be generated until the reset frequency has expired."

Il problema può essere risolto eliminando la spunta da "Invia annunci di ricerca" dalla configurazione del NetServer in iSeries Navigator.
Illegal datagram from AS400 - Configurazione iSeries Navigator

Some problems with Microsoft SQL Server

Problem 1: changes in sqlcmd

I don't know exactly what happened, but from a certain moment the sql script I used to backup my SQL server DB stopped working. I usually ran it with this syntax:

sqlcmd  -i backup.sql

Where backup.sql contained the code to connect to my server. Suddenly the script started acting up, giving this message:

HResult 0x2, level 16, state 1
Named Pipes Provider: Could not open a connection to SQL Server [2].

After a while, I understood that for some reason, the sqlcmd utility changed its behavior, and forced the user to set the server with the -S parameter. So, in my case, I solved changing my batch script this way

sqlcmd -S lpc:.\SQLEXPRESS -i backup.sql

where lpc:.\SQLEXPRESS is the way to connect to my SQLEXPRESS instance via shared memory.

Problem 2: the wrong restore place

I also have a script that restores my db on another machine. I changed the destination PC, and, guess what, the restore script started acting up too!!! :-( This was the error message:

Msg 5133, Level 16, State 1, Line 1
Directory lookup for the file "C:\SomePathTo\myDB.mdf" failed with the operating system
error 3(The system cannot find the path specified.).

As the database was in C:\SomePathTo in the source machine and the target machine had not such directory, this stupid SQL server could not complete the restore operation!
The solution is

1) Run the command

restore filelistonly from DISK= 'C:\someDirt\myDB.bak'

If you run this from sqlcmd, redirect the output to some file with the -o option, as you can't see this large output on one line.

2) Search the results of this command for the colums "LogicalName" and substitute them in this script (here I used the names myDB_dat and myDB_log)

RESTORE DATABASE [myDB]
FROM DISK = 'c:\mfoff\mfoffdb.bak'
with
move 'myDB_dat' TO 'C:\newPath\myDB.mdf',
move 'myDB_log' To 'C:\newPath\myDB_log.ldf'

Escript under Windows

Escript is a tool for executing simple scripts written in Erlang. It's a nice tool, but the manual page is too much "Unix oriented":if we try to run the example script under one of the funny and exotic operating systems of the Windows family, we get something like this:

C:\temp>escript factorial.escript 5
escript: Failed to open file: C:\temp\escript.escript

Ouch! The solution to the problem comes reading the sources of escript.exe. Under Windows it takes the program name used to call it (in our example escript): if it doesn't end with the exe suffix it takes it as the name of the script, then it adds the escript suffix ant tries to run it: so it looks for as escript.escript which doesn't exist. Obviously it's a bug, but to overcome it, we can add the exe suffix to our command line:

C:\temp>escript.exe factorial.escript 5
factorial 5 = 120

Another note for Windows users: the first line cannot contain Erlang (it's the place for the Unix # line).If you try to run this script

main(Args) ->
	print_args(Args). 

print_args([]) ->
    ok;
print_args([FirstArg | Rest]) ->
    io:format("~s~n", [FirstArg]),
	print_args(Rest).

You'll get this result:

C:\temp>escript.exe x.escript Hello World
x.escript:2: syntax error before: '.'
escript: There were compilation errors.

You must add a line before the main in order to run it.

Software gestionale in Erlang?

Come forse saprete, il mio lavoro consiste nello sviluppo di software gestionale. Ultimamente, però, grazie agli amici dell'XP User Group di Milano, mi sto appassionando al linguaggio Erlang. Mi è allora venuta la balzana idea di vedere se le due cose potessero avere un punto di incontro. Sia chiaro, con questo post non sto invitando nessuno a sviluppare programmi gestionali in Erlang, cosa che ritengo piuttosto difficile, ma desidererei da un lato saggiare la duttilità del linguaggio, dall'altro cercare di imparare qualcosa riguardo ai principi di scomposizione funzionale dei problemi.

La gestione di un ordine

Durante una mia presentazione del linguaggio Scala tenutasi all'XP User Group di Bergamo, ho già affrontato la questione di scomporre "funzionalmente" un elementare problema gestionale. Gli esiti non sono stati brillantissimi in quanto a chiarezza, desidererei quindi riprovare utilizzando un diverso linguaggio.

Il problema giocattolo che vorrei affrontare è quello di effettuare dei calcoli su un ordine, rappresentato come una lista di righe d'ordine. Definisco quindi come prima cosa il record riga d'ordine:

 
-record(order_row, {description, price, qty, vat_rate = 0.2}).
 

Su questo record posso quindi definire delle banali funzioni quali il calcolo del prezzo netto, dell'IVA e del prezzo ivato:

 
net_amount(OrderRow) ->
  OrderRow#order_row.price * OrderRow#order_row.qty.
 
vat(OrderRow) ->
  net_amount(OrderRow) * OrderRow#order_row.vat_rate.
 
amount(OrderRow) ->
  net_amount(OrderRow) + vat(OrderRow).
 

Una generica elaborazione su un intero ordine si può quindi intendere come la composizione di un'operazione di aggregazione, quale la somma, e di una funzione di calcolo applicata ad ogni riga.

 
computation(Order, AggregationFunction, CalculusOnRow, StartResult) ->
  lists:foldl(fun(OrderRow, ResultSoFar) ->
                 AggregationFunction(CalculusOnRow(OrderRow), ResultSoFar)
              end, StartResult, Order).
 

Rielaborando questi mattoncini possiamo pertanto ottenere facilmente diversi tipi di computazioni:

 
total_amount(Order) ->
  computation(Order, fun erlang:'+'/2, fun amount/1, 0).
 
max_vat(Order) ->
  computation(Order, fun erlang:max/2, fun vat/1, 0).
 
min_net_amount(Order) ->
  computation(Order, fun erlang:min/2, fun net_amount/1, 0).
 

Conclusioni

La scomposizione funzionale del problema in Erlang sembra più semplice che in Scala. La sintassi Erlang per i record risulta però piuttosto "legnosa" e temo possa sfuggire presto di mano con problemi di dimensioni reali. Rimango inoltre sempre perplesso sulla tipizzazione dinamica: capire con che a parametri invocare una funzione potrebbe essere un problema. Ciò nonostante, ritengo che Erlang meriti senza dubbio un ulteriore approfondimento.