Home   |   Archivio   |   Chi siamo   |   Contatti
Andrea Gini
MiniPad come progettare e implementare un editor Java con compilatore in linea
Parte III - Ciclo di Vita del Software e Reverse Engineering
di
Andrea Gini
Negli scorsi due articoli ho illustrato lo sviluppo di un piccolo progetto, dalla definizione del problema all'implementazione in java. I diagrammi UML hanno fornito in prima battuta gli strumenti per sviluppare l'analisi del problema, e in un secondo tempo mi hanno permesso di creare un modello simbolico del sistema. In questo articolo voglio illustrare in che modo l'UML può tornare utile nelle fasi successive del ciclo di vita del Software, anche in presenza di programmi progettati da terzi, di cui vogliamo capire il funzionamento.

Il ciclo di vita del Software

Il ciclo di sviluppo ideale di un sistema software si compone di cinque fasi:

  • analisi
  • progettazione
  • realizzazione
  • collaudo
  • manutenzione

Queste cinque fasi (denominate nel loro complesso "Ciclo a Cascata") sono caratteristiche del tradizionale ciclo ingegneristico (pensate, ad esempio, all'ingengeria civile e alla progettazione di un ponte o di un'autostrada). Tuttavia il Software presenta, rispetto ad altre opere di ingegneria, una differenza enorme nel concetto di manutenzione: nell'ingegneria tradizionale la manutenzione è tesa a preservare lo status quo, mentre nel Software un intervento di manutenzione può arrivare a modificare profondamente la struttura originale di un programma.

L'evoluzione di Windows 95 può fornire un valido esempio: il progetto originale lo vedeva come la consacrazione della filosofia desktop-centrica, ma esigenze del mercato hanno spinto a rivedere le basi stesse del progetto al fine di adeguarlo alla nascente era Web-centrica: dapprima è stato aggiunto (attraverso un package esterno) la connettività TCP/IP, quindi è stato proposto Explorer come browser consigliato; infine questi componenti sono stati integrati nella distribuzione standard del Sistema Operativo. Windows 98, realizzato nei tre anni successivi, usa Explorer come interfaccia grafica standard per l'utente, un'evoluzione certamente non prevista né prevedibile appena tre anni prima.

Volendo fare un paragone il lavoro di un ingegne civile e quello di un ingegnere del Software, è come se il primo fosse costretto ogni volta a costruire un edificio diverso su un pianeta diverso, con leggi fisiche diverse (e non documentate), con materiali appena scoperti e con una popolazione ogni volta diversa per abitudini e fisionomia.

Queste considerazioni hanno portato alla definizione di un modello più realistico per rappresentare la vita dinamica del software: il Modello a Spirale, in cui analisi, progettazione e sviluppo forniscono un prodotto che viene collaudato e distribuito, mentre contemporaneamente i progettisti intraprendono un nuovo ciclo di analisi, progettazione e sviluppo, descrivendo una metaforica spirale, di durata potenzialmente infinita (basta pensare a Word, giunto ormai alla nona release, o ad Autocad che ha ormai superato la quindicesima).

Figura 1 – Modello a Spirale del ciclo di vita del software
Figura 1 – Modello a Spirale del ciclo di vita del software

Reverse Engineering

Il Reverse Engineering è un processo di "analisi all'indietro", volto a capire il funzionamento di un determinato programma già realizzato e in uso.

Questo processo è utile principalmente in due casi:

  • esigenza di modificare un programma proprietario di cui è assente la documentazione.
  • desiderio di capire il funzionamento di un prodotto concorrente

Il primo dei due casi riporta alla mente il Millennium Bug, il cui pericolo maggiore risiedeva nel fatto che molti servizi indispensabili al funzionamento degli uffici anagrafici e bancari erano stati realizzati negli anni '50 e '60, e che da allora avevano subito talmente tante modifiche da discostarsi completamente dal progetto iniziale. A peggiorare le cose si aggiungeva il fatto che la documentazione originale molte volte era andata persa, o risultava incomprensibile. O peggio: il programma era stato scritto in un linguaggio (ad esempio in COBOL) e in seguito modificato più volte in assembler.

Il secondo caso di Reverse Engineering è molto comune nel businnes informatico, dove un programma di successo (si pensi a Netscape) viene studiato e in parte copiato dalla concorrenza (Internet Explorer, HotJava, Opera....).

Java, UML e il Reverse Engineering

Ho notato che, malgrado l'accuratezza dell'analisi, capita che durante l'implementazione emergano nuove esigenze. Se risolvo questi imprevisti localmente, senza riprendere in mano il progetto, corro il rischio di modificare il design originale, producendo una soluzione funzionante ma instabile (e dunque fonte di nuovi problemi).

Analisi e progettazione dovrebbero proseguire anche ad ogni passo dell'imlementazione, fornendo sempre una documentazione adeguata.

Un'aiuto in questo senso viene da TogetherJ, un tool di sviluppo UML che mantiene una costante sincronizzazione tra i diagrammi e il codice dell'implementazione.

Ogni modifica sui diagrammi (ad esempio aggiunta di un metodo) viene immediatamente riprodotta sul codice, e viceversa ogni modifica sul codice è immediatamente visibile sul diagramma. Questa funzione, definita Rund-Trip Engineering, consente addirittura di effettuare in maniera automatica e in tempo reale il Reverse Engineering di un programma java esistente.

Utilizzando questo strumento è possibile dimostrare che, se un programma è stato progettato correttamente in UML, un'analisi del suo codice sarà in grado di generare i diagrammi di partenza.

Se apro un nuovo progetto in una directory contenente dei sorgenti java, TogetherJ ne scandisce il codice e genera automaticamente un diagramma di classe per ogni package. Provo a vedere come si comporta ad analizzare i sorgenti di MiniPad, il mini editor sviluppato nei due articoli precendenti.

Figura 2 – Diagramma delle classi di MiniPad generato automaticamente da TogetherJ
Figura 2 – Diagramma delle classi di MiniPad generato automaticamente da TogetherJ

Se escludiamo il layout, il diagramma generato corrisponde a quelli su cui avevo realizzato il progetto! Ovviamente un intervento manuale può rendere il diagramma più bello e leggibile, spostando le classi in modo da dargli un ordine logico o gerarchico, nascondendone alcune e creando un diagramma diverso per illustrare ogni aspetto del programma.

I diagrammi di sequenza

Si è visto che i diagrammi di sequenza descrivono lo sviluppo di un'azione. Ovviamente vale anche il contrario: provo a selezionare l'opzione "Generate Sequence Diagram" sul metodo compile() della classe AbstractMiniPad e....

Figura 3 – Diagramma di sequenza del metodo compile() generato automaticamente
Figura 3 – Diagramma di sequenza del metodo compile() generato automaticamente

Anche in questo caso il risultato è conforme al diagramma di partenza.

La generazione automatica di diagrammi UML a partire dal codice è un fenomeno sorprendente. È importante, a mio avviso, arrivare a capire il meccanismo logico alla base di questo fenomeno, poiché in esso risiede l'essenza stessa dell'utilità di UML come strumento di progettazione.

I Metadati, la semantica di Java e i Diagrammi di Classe

I Metadati sono dati che descrivono altri dati. Se guardate un file HTML con un editor di testo (potete farlo direttamente su questa pagina clickando il tasto destro del mouse e scegliendo l'opzione "HTML" o "View HTML") noterete che, oltre al testo della pagina, compaiono numerosi Tag (le parole contenute tra i simboli < e >). Questi tag sono Metadati: descrivono come il documento dovrà essere visualizzato (margini, centratura, stile del carattere, immagini....).

Le intestazioni presenti in un sorgente java (definizioni di classi, metodi, attributi) sono un'altro esempio di metadati: essi infatti non "fanno" qualcosa, ma concorrono a definire la semantica del linguaggio. Si veda ad esempio il sorgente java:

public class Class1
{}
public class Class2 extends Class1
{
  private Class3 lnkClass3;
  private String name;
  public String getName()
  {
    return name;
  }
}
public class Class3
{}

Esso ha una corrispondenza semantica col seguente diagramma:

Figura 4 – Diagramma delle classi Class1, Class2 e Class3
Figura 4 – Diagramma delle classi Class1, Class2 e Class3

Codice e diagramma contengono, in questo esempio, le stesse informazioni. L'aggiunta di istruzioni al metodo getName() può influire sulla funzionalità del codice (cosa fa), ma non andrà a modificarne il significato semantico (come lo fa). La semantica dei diagrammi di classe UML ha una corrispondenza precisa con quella del linguaggio Java, ed è proprio questa corrispondenza che permette di estrarre i diagrammi direttamente dal codice. Ovviamente i diagrammi così ottenuti hanno un senso solo se il programma è stato progettato correttamente, in modo da rispettare il "contratto" implicito nelle sue definizioni di metodo. La progettazione UML incoraggia il programmatore a definire tali contratti in modo preciso e senza ambiguità, come richiesto dalla filosofia della programmazione orientata agli oggetti.

Conclusioni

Lo sviluppo di un piccolo progetto mi ha permesso di illustrare, negli scorsi articoli, come l'UML sia utile al programmatore java. Ma affinché la pratica della progettazione non venga percepita come pura speculazione, ho voluto dimostrare che il progetto contenuto nei diagrammi UML viene trasferito nel codice, e che da un punto di vista puramente semantico, codice e diagrammi contengono esattamente le stesse informazioni. Questa corrispondenza assume un'importanza enorme nel momento in cui il programmatore si preoccupa di definire in modo rigoroso le interfacce di programmazione, seguendo i dettami della "programmazione per contratto" (vedere MokaByte 35 novembre 1999 - "Design by Contract" di Andrea Giovannini). In questo caso il modello raggiunge una capacità espressiva elevatissima, in grado di suggerire con precisione la funzionalità del programma.

Bibliografia

P. Coad - E.Yourdon

  • "Analisi dei Sistemi orientati agli oggetti"
  • "Progetto dei sistemi OO", Ed. Jackson

Nigel Warren, Phil Bishop, Philip Bishop Java in Practice : Design Styles and Idioms for Effective Java Addison-Wesley Pub Co

Campbell Craig "Destroying The Village - Eisenhower and Thermonuclear War" Columbia University Press / New York www.columbia.edu/cu/cup

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it