MokaByte Numero  43  - Luglio Agosto 2000
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
Il ciclo di vita del Software

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 puo' 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 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 e' tesa a preservare lo status quo, mentre nel Software un intervento di manutenzione puo' arrivare a modificare profondamente la struttura originale di un programma.

L'evoluzione di Windows 95 puo' 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 e' stato aggiunto (attraverso un package esterno) la connettivita' TCP/IP, quindi e' 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 ne' prevedibile appena tre anni prima.

Volendo fare un paragone il lavoro di un ingegne civile e quello di un ingegnere del Software, e' 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 piu' 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



Reverse Engineering

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

 Questo processo e' utile principalmente in due casi:

- esigenza di modificare un programma proprietario di cui e' assente la documentazione.
- desiderio di caprire 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 piu' volte in assembler.

Il secondo caso di Reverse Engineering e' 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, UMLe 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 e' 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 e' possibile dimostrare che, se un programma e' stato progettato correttamente in UML, un'analisi del suo codice sara' 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 (cliccare per l'ingrandimento)




Se escludiamo il layout, il diagramma generato corrisponde a quelli su cui avevo realizzato il progetto! Ovviamente un intervento manuale puo' rendere il diagramma piu' 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 e' 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

anche in questo caso il risultato e' conforme al diagramma di partenza. 
La generazione automatica di diagrammi UML a partire dal codice e' un fenomeno sorprendente. E' importante, a mio avviso, arrivare a capire il meccanismo logico alla base di questo fenomeno, poiche' in esso risiede l'essenza stessa dell'utilita' 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 dovra' 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

Codice e diagramma contengono, in questo esempio, le stesse informazioni. L'aggiunta di istruzioni al metodo getName() puo' influire sulla funzionalita' del codice (cosa fa), ma non andra' 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 e' proprio questa corrispondenza che permette di estrarre i diagrammi direttamente dal codice. Ovviamente i diagrammi cosi' ottenuti hanno un senso solo se il programma e' 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 ambiguita', 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 affinche' 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 capacita' espressiva elevatissima, in grado di suggerire con precisione la funzionalita' 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
 

 

Chi volesse mettersi in contatto con la redazione 
può farlo scrivendo a mokainfo@mokabyte.it