L'angolo di 6502Transazioni in C++ [1]
2002-12-28
Indice

Benvenuti!
Chi sono
Demo
Documenti
Quelli piccoli
Problemi
Scacchi
Immagini
Musica
Il mio blog
Scrivimi

English version 


La gestione di transazioni in C++

Una delle tante novita' introdotte dal C++ rispetto al C e' la gestione delle eccezioni. Nella letteratura questo nuovo metodo di segnalare il fallimento di una operazione viene descritto molto piu' elegante, stabile e compatto dell'uso sistematico di return code come segnalazione di completamento o errore.

Senza voler ridescrivere nel dettaglio i problemi legati all'uso delle exceptions(1) per la gestione degli errori intendo soltanto ribadire il problema di fondo. La parte complicata non e' in chi genera (throw) o chi gestisce (catch), ma nei metodi di tutte le classi che l'exception attraversa in maniera quasi asincrona durante il processo di stack unwinding.

Stando attenti a come si scrivono i metodi e' possibile evitare di perdere risorse in caso di exception (vedi uso di auto_ptr) ma le cose si complicano notevolmente quando si considera lo stato logico in cui l'oggetto o altri oggetti coinvolti in quanto manipolati prima della throw devono restare. Nella sua accezione piu' stringente la scrittura di un metodo compatibile con le exception richiede infatti che in caso di generazione di una exception nulla sia stato fatto per quanto riguarda lo stato logico dell'oggetto. In altre parole le condizioni devono essere identiche a quelle precedenti la chiamata del metodo (eventuali diversita' non devono essere visibili tramite l'interfaccia pubblica degli oggetti coinvolti).

Quello che in pratica sarebbe auspicabile e' la presenza di "transazioni" simili a quelle disponibili sui DBMS relazionali.

Proprio partendo da quest'idea ho implementato una gestione di transazioni in C++ che semplifica notevolmente l'uso di exception per la segnalazione di errori.

Implementare commit/rollback in C++

Per la realizzazione di un programma di gestione della produzione sto implementando un server transazionale scritto in C++ che mantiene una rappresentazione in memoria di tutti i dati gestionali. Il server centrale espone dei servizi applicativi e i vari client richiedono l'esecuzione di questi servizi tramite dei form di richiesta opportunamente compilati.

I dati gestionali sono tenuti in memoria in una stuttura dati reticolare e il codice delle transazioni si occupa eseguire le operazioni e a restituire ai client i risultati richiesti.

Nel caso che durante l'esecuzione di una transazione si verifichi un errore il server ripristina la situazione a prima che la richiesta fosse stata ricevuta e informa del problema il client.

Le informazioni di tipo gestionale sono contenute in classi "stupide", nel senso che gli unici metodi interni alle classi sono relativi alla gestione della struttura dati stessa (2) . In pratica le transazioni manipolano dati molto simili alle catene di un database reticolare classico e le operazioni che vengono eseguite sono l'assegnazione di campi di vario tipo o l'assegnazione di puntatori.

Quello che ho fatto e' stato sostituire i campi dati con degli oggetti "intelligenti" che fossero in grado di memorizzare in un registro le variazioni effettuate. Per fare questo sono risultati molto utili i template disponibili in C++.

 

(1)Per una trattazione completa si veda l'interessante articolo "Exception Handling: A False Sense of Security" di Tom Cargill disponibile online oppure la raccolta di problemi/soluzioni che da quell'articolo sono stati tratti e raccolti nel libro "Exceptional C++" di Herb Sutter ISBN=0-201-61562-2.
(2)Non sono al momento un convinto fautore di un approccio object oriented per l'analisi di procedure di tipo gestionale. A mio parere nelle problematiche gestionali e' presente un forte coordinamento di entita' con scarsa autonomia; distribuire questo coordinamento su classi non semplifica l'analisi. In altre parole il forte coupling presente nelle problematiche gestionali rende l'approccio OO inutilmente dispersivo.