Visualizzazione post con etichetta Software engeneering. Mostra tutti i post
Visualizzazione post con etichetta Software engeneering. Mostra tutti i post

mercoledì, marzo 04, 2009

E se dovessi programmare in C ANSI.. ma OO?

Oramai é sempre più raro trovarsi in questa situazione esistendo svariate soluzioni sia open che commerciali per lo sviluppo e la compilazione di codice C++ anche per architetture embedded. Ogni tanto però capita ancora di avere questa esigenza.. in quei casi?

La risposta viene da molto lontano nel tempo, molti di voi avranno sentito parlare del documento OOC, in cui si descrivono le tecniche per programmare in uno stile OO utilizzando l'ANSI C. Questo documento esiste da molti anni.. e quando lo scoprii (nel 2002 se non ricordo male) mi entusiasmò! In questi giorni però la stessa domanda mi é stata riproposta da un curioso molto in gamba.. e perché non fornirla a tutti sul blog? Ma di più.. dato che non ho mai nulla da fare (ironico ovviamente), perché non scrivere un esempio semplice semplice di tool costruito con le macro di preprocessore? E' un giocattolino senza esplicito supporto per l'ereditarietà, il polimorfismo e quant'altro.. però é simpatico e chi vuole può usarlo/estenderlo per gioco. Eccovelo in sole 50 righe di macro con un esempio semplice semplice.

Vediamo un esempio di dichiarazione di classe:

// La classe:
CLASS_BEGIN(CheckedInt)
ATTRIBUTE(CheckedInt,int,version);
METHOD(CheckedInt,void,setValue,unsigned long val);
METHOD(CheckedInt,unsigned long,getValue);
STATIC_METHOD(CheckedInt,unsigned long,max_val);
CLASS_END(CheckedInt)

// La struttura rappresentante un'istanza:
CLASS_INSTANCE_BEGIN(CheckedInt)
ATTRIBUTE(CheckedInt,unsigned long,value);
ATTRIBUTE(CheckedInt,unsigned long,not_value);
CLASS_INSTANCE_END(CheckedInt)

// Definizione di costruttore e distruttore:
CLASS_ALLOCATORS(CheckedInt,unsigned long val);
Lineare no? E l'implementazione? Eccola:

// Metodo d'istanza:
METHOD_IMPL_BEGIN(CheckedInt,void,setValue,unsigned long val)
this->value = val;
this->not_value = ~val;
METHOD_IMPL_END(CheckedInt)

// Caso statico:
STATIC_METHOD_IMPL_BEGIN(CheckedInt,unsigned long,max_val)
return 0xFFFFFFFE;
STATIC_METHOD_IMPL_END(CheckedInt)

//...

// Inizializzazione della struttura statica:
CLASS_INIT( CheckedInt,1,
CheckedInt_setValue,
CheckedInt_getValue,
CheckedInt_max_val);

// Costruttore:
CONSTRUCTOR_BEGIN(CheckedInt,unsigned long val)
this->value = val;
this->not_value = ~val;
CONSTRUCTOR_END(CheckedInt)

// Distruttore:
DESTRUCTOR_BEGIN(CheckedInt)
// Rilascio risorse.
DESTRUCTOR_END(CheckedInt)
Usiamo la nostra classe ora!

// Istanzio:
CheckedInt *ckdInt = CheckedInt_new(10);

// Chiamo un po:
printf("A checked value: %d\n", CALL(ckdInt,getValue));
CALL(ckdInt,setValue,42);
printf("A checked value: %d\n", CALL(ckdInt,getValue));

// Accedo agli attributi direttamente:
printf("I'm a bad boy! ;)\n");
ckdInt->not_value = 0;
printf("A checked value: %d\n", CALL(ckdInt,getValue));

// Uso il distruttore:
CheckedInt_free(ckdInt);
Ok, probabilmente molti di voi diranno "Tra C++, Java, C#, cicici e tututu sicuramente questo non mi serve!", sono perfettamente d'accordo con voi... ma ogni sfizio è sfizio!!! ;)

martedì, maggio 22, 2007

Aspetti ortogonali

Come tutti ben sanno, il paradigma di programmazione per aspetti (AOP) è stato inventato appositamente per superare (o tentare di superare) le problematiche di ortogonalità fra differenti aspetti all'interno di un progetto software.

Al di là della poca diffusione e della poca risonanza che ha avuto questo paradigma (se volete un flame sul perché AOP non ha preso piede.. fate pure.. partecipo volentieri ;)), sicuramente un commento è dovuto: il problema dell'ortogonalità è diffuso in ogni dove, e tende a devastare rapidamente il risultato di moltissimi sforzi fatti da programmatori, da progettisti esperti di SE, da DBA, da CTO.. cicici e tututu! Insomma gli aspetti ortogonali rompono e parecchio!

Esempi? Allora: considerate il problema di etichettatura di dati al fine della classificazione, ad esempio chi di noi non ha incontrato l'annoso problema di memorizzare all'interno di una struttura di cartelle sensata la CATERVA di articoli scientifici raccolta in anni di lavoro? Chi di noi non si è accorto che UN ALBERO NON VA BENE? Ovvio, un albero no va bene perché esistono aspetti ortogonali che possono essere descritti solamente tramite un grafo diretto aciclico connesso (DAG). Sigle a parte la struttura dati che in questo caso avrebbe più senso è un MULTIALBERO.. se mi concedete la licenza poetica per coniare questo vocabolo. Si perchè mentre un grafo non distingue l'appartenenza degli archi a una sottostruttura, in questo caso ESISTE!

Ok ok.. sembra che io stia DIVAGANDO un po' troppo deragliando dal fulcro della questione.. ma quello che penso è che queste strutture a multialbero dovrebbero essere adottate in:
- documenti XML, dove spesso vengono solo simulate con riferimenti ovunque;
- linguaggi di programmazione, dove l'ereditarietà consente di ottenere alberi, o al più DAG;
- database, dove spesso si tenta inconsapevolmente di emularli con tabelle e query fra di esse.. ma in molti casi si tende a confondere le query con le tabelle.. soprattutto i discepoli di Access ;), in realtà il problema è che siccome i dati da qualche parte devono finire realmente, li si infila nelle tabelle e gli aspetti ortogonali li si mostra con le query.. quindi aggiungendo l'elaborazione di una query per non costruire una struttura dati adeguata (un multialbero).

L'elenco potrebbe allungarsi.. ma prima vorrei sapere.. siete d'accordo? Volete anche voi un multitagged-XML? ;)

martedì, aprile 03, 2007

Programmare OOP in Matlab

In Matlab esistono degli strumenti del linguaggio appositamente realizzati per consentire la programmazione OOP, essi sono descritti nel capitolo "Classes and Objects" e sono lo standard utilizzato anche all'interno della toolbox standard di Matlab per l'UI e per molto altro.
Tale tecnica di programmazione presenta alcuni indubbi vantaggi ma anche degli svantaggi enormi, a partire dalla struttura e costruzione delle classi all'interno del file-system, l'impossibilità di utilizzo della dot-notation e molti altri.
Una tecnica alternativa per fare OOP in Matlab sfrutta lo storing del workspace locale condiviso nel caso in cui vengano utilizzate delle funzioni innestate. La seguente dichiarazione della classe "counter", completamente commentata, mostra come può essere facilmente utilizzata questa tecnica:

function c = counter(start)
% COUNTER Generates a new counter object created with internal functions.
%
% The technique used here allows to create objects with all private
% attributes and public methods exported in a structure. All local
% variables defined here can be used as object attributes. Sub-functions
% can be used as private methods and setter/getter methods can be written
% to give the acces to attributes.. using the complete information
% hiding paradigm. The main funciton is the constructor. The object status
% is stored in a local workspace that have the same lifetime of the
% generated object.

% Save the initial value:
startVal = start;

% ===========
% Now there are two object attributes: start and startVal.
% ===========

% Returning the counter: this is the public methods set exported.
c = struct('next',@Next,'prev',@Prev,'reset',@Reset);

% ===========
% The public methods body.
% ===========
% The next integer function:
function n = Next
% Set:
n = start;
% Increment:
start = start + 1;
end
% The prev integer function:
function n = Prev
% Set:
n = start;
% Decrement:
start = start - 1;
end
% The reset function:
function Reset
% Reset:
start = startVal;
end
% ===========
% Private methods are simple functions and can be defined here.
% ===========
end

% ===========
% Support functions that are not methods (no access to attributes) are
% defined here.
% ===========

Per creare un oggetto di classe "counter" è sufficiente eseguire la funzione:
c1 = counter(1);
c2 = counter(-2);
Per eseguire un metodo è sufficiente utilizzare la dot-notation:
c1.next()
ans = 1
c1.next()
ans = 2
c1.reset()
c1.next()
ans = 1
Have fun! ;)

mercoledì, marzo 28, 2007

Hookka che ti hookko anch'io

Confronto fra tecniche di hooking e l'AOP

Piccola osservazione forse banale:
  • le tecniche di hooking consentono di definire dei punti del proprio codice in cui l'esecuzione di codice esterno è ammessa previa registrazione di simpatiche funzioncine di callback, questo ad esempio permette a mtrace di tracciare l'attività della libreria malloc (ad es. funzioni malloc, realloc, free, ...). Ogni funzione di callback è però registrata come callback per esattamente una funzione da tracciare, eventualmente tipizzata per poter tracciare punti differenti;
  • l'AOP (Aspect Oriented Programming) prevede la possibilità di dichiarare degli aspetti come collezioni di azioni da poter eseguire eventualmente dietro esplicita richiesta oppure prima o dopo l'esecuzione di ben precisi metodi degli oggetti di ben precise classi (o tutte, o una parte). Differenti aspetti possono definire differenti azioni o classi su cui operano o metodi che "modificano".
Ok, questo era un riassunto BRUTTISSIMO e non esattamente corretto di quello che sono le due tecniche.. ora le riflessioni:
  • esiste sempre del codice esterno (es. funzioni) da eseguire in determinati punti del codice delle classi che descrivono le entità del dominio;
  • esiste sempre una tipizzazione (tipo di hook, aspetto legato all'azione);
  • si tenta sempre di imporre una separazione fra il codice che si vuole "iniettare" ed il codice preesistente;
  • gli aspetti lavorano su sottoinsiemi di classi, l'hooking lavora su ogni singola funzione.
Non vi sembrano simili simili simili? Decisamente direi che è possibile mettere l'hooking e l'AOP sotto lo stesso tetto. In realtà le implementazioni dell'AOP in genere prevedono un preprocessore che modifichi il codice sorgente prima della compilazione mentre nell'hooking tutto è eseguito a run-time.. però questo è solo un dettaglio tecnico.
Esempio.. ho implementato uno strumento di hooking per Matlab (FHook) che consente di fare anche AOP, è grezzo, non consente di sfruttare il pattern-matching per la selezione delle funzioni/sottofunzioni a cui applicare gli aspetti o su cui fare hooking.. però anche come strumento embrionale direi che può essere utile e si può usare per studiare a fondo questa simbiosi di concetti ;)

martedì, gennaio 23, 2007

GoF design patterns

Chi non avesse mai studiato o letto il libro "Design Paterns" della GoF (Gang of Four).. ma anche chi lo conosce a memoria ed è uno "squilibrato patternizzatore" di tutto il codice che scrive.. eccovi un link ad un lavoro di descrizione per esempi dei pattern GoF.. comprensivo di tavola periodica dei design patterns :D

GoF Design Patterns

C++: i paradigmi Object Oriented e Generics Oriented accoppiati

Con il C++ si ha un esempio di linguaggio di programmazione multiparadigma in cui i vari paradigmi inclusi sono in grado di cooperare per generare nuove famiglie di design patterns. In particolare in C++ è possibile sfruttare in maneira furba l'esistenza di OO e dei generics (templates) per ottenere codice flessibile ed ottimizzato per le proprie esigenze.
Al link seguente troverete un pattern curioso.. che per questo ha preso il nome di Curiously Recurring Template Pattern (CRTP).
Un altra serie di pattern a paradigma misto.. li pubblicherò in questo blog a breve.. vi aspetto ;)