L’architettura Software stabilisce l’organizzazione globale di un sistema software, definendo:
La progettazione architetturale è un processo di progettazione finalizzato ad individuare i sottosistemi che compongono il sistema da realizzare, e le loro inter-relazioni di controllo e di comunicazione.
L’output di questo processo di progettazione sarà una descrizione dell’architettura software.
Partire con una prima definizione di massima dell’architettura.
Basandosi sui principali requisiti e use cases.
Determinare i principali componenti richiesti dal sistema (database, particolari dispositivi hardware, e sottosistemi software).
Si può scegliere tra vari pattern architetturali.
Può essere utile far lavorare più team su una prima bozza dell’architettura per poi fondere le migliori idee.
Raffinare l’architettura
Considerare ogni use case e modificare l’architettura per renderlo realizzabile.
Definire l’architettura finale, quando si saranno ottenuti class diagrams e interaction diagrams finali.
Il concetto di pattern può essere applicato alle architetture software.
Si parla di architectural patterns o stili/modelli architetturali.
Permettono di progettare sistemi flessibili usando componenti quanto più indipendenti possibile.
Esempi:
In un sistema a livelli (layers), ciascun livello comunica solo con il livello sottostante.
Ogni livello offre un’interfaccia ben definita al livello immediatamente sovrastante.
Il livello più alto vede quello più basso come un insieme di servizi.
Un sistema complesso può essere costruito stratificando layers aventi via via crescenti livelli di astrazione.
É importante avere un layer separato per l’Interfaccia Utente (UI).
I livelli sotto il livello UI forniscono le funzioni applicative corrispondenti ai casi d’uso.
I livelli più bassi forniscono servizi generici.
es. comunicazione su rete, accesso a database.
1. Modularità: I layer possono essere progettati indipendentemente.
2. Coesione: I layer hanno coesione di layer.
3. Accoppiamento: Ogni layer è accoppiato solo con quelli adiacenti (al più due).
4. Astrazione: I livelli superiori devono conoscere solo l’interfaccia del livello inferiore, non la sua implementazione.
5. Riusabilità: I livelli possono essere liberamente riusati se si ha necessità degli stessi servizi forniti.
6. Riuso: I livelli possono essere liberamente sostituiti a patto di rispettare le interfacce richieste e fornite.
7. Flessibilità: nuovi livelli possono essere facilmente aggiunti senza modificare quelli esistenti.
8. Obsolescenza: L’obsolescenza dovrebbe riguardare separatamente i vari layer, per cui può essere efficacemente contrastata modificando un solo livello per volta.
9. Portabilità: Tutti i moduli dipendenti dall’ambiente operativo sono ai livelli inferiori: gli altri moduli sono sempre portabili.
10. Testabilità: I livelli possono essere testati separatamente.
11. Progettazione difensiva: I layer possono essere testati sulla base di asserzioni generali sul loro funzionamento.
C’è almeno un componente col ruolo di server, che attende e gestisce connessioni.
Ad esempio, nel caso di un server web, esiste un software (web server, ad esempio Apache) che ascolta continuamente richieste da parte di altre macchine sul porto di comunicazione http (di solito il porto 80) e le elabora.
C’è almeno un componente col ruolo di client, che inizia la connessione richiedendo qualche servizio al server.
Tale modello è diffuso nel World Wide Web, nel quale ci sono (relativamente) pochi server, molto potenti, e una moltitudine di client (generalmente poco potenti).
Il numero e la disposizione dei server è stabile; i client invece possono essere inseriti e tolti a piacimento.
Una estensione del pattern Client-Server è il three-tier con livello Client, Business Logic server, e Database server.
Il database server è in ascolto su di un canale di comunicazione aperto con il web server. Quest’ultimo interroga il DB server che può solo rispondere.
Un’ulteriore estensione è il pattern Peer-to-Peer.
Un sistema composto da vari componenti software distribuiti su sistemi host diversi.
I Peer sono potenzialmente equivalenti tra loro, per cui possono comunicare da pari a pari e scambiarsi vicendevolmente e dinamicamente i ruoli di client e server.
1. Modularità: Client e server possono essere sviluppati separatamente
2. Coesione: Il server ha coesione comunicazionale
3. Accoppiamento: Le comunicazioni tra client e server sono ridotte al minimo
4. Astrazione: Il server può essere visto come un fornitore di servizi astratti
6. Riuso: I servizi del server potrebbero essere riusabili; quelli del client invece, in generale, no
7. Flessibilità: I sistemi distribuiti possono spesso essere facilmente riconfigurati aggiungendo ulteriori server o client
9. Portabilità: Si possono scrivere client per nuove piattaforme senza dover modificare il server
10 Testabilità: Si può testare il server in maniera indipendente dal client
11. Progettazione difensiva: Si possono effettuare controlli rigorosi basati sulla gestione dei messaggi scambiati
Distribuisce in maniera trasparente vari aspetti del sistema software su nodi diversi.
Un oggetto può chiamare metodi di un altro oggetto senza sapere che l’oggetto è localizzato su una sede remota.
Il Proxy inoltra la richiesta al Broker.
CORBA è un open standard che consente di costruire questo tipo di architettura.
1. Modularità: Gli oggetti remoti possono essere progettati separatamente
5. Riusabilità: È spesso possibile progettare oggetti remoti in maniera tale da renderli disponibili anche agli altri sistemi
6. Riuso: Si possono riusare oggetti remoti creati da altri
7. Flessibilità: I brokers possono essere aggiornati quando necessario; i proxy possono comunicare anche con altri oggetti remoti
9. Portabilità: Client per nuove piattaforme possono essere scritti continuando ad accedere agli stessi broker e oggetti remoti
11. Progettazione difensiva: Controlli precisi possono essere fatti sugli oggetti remoti
Un processo legge una serie di input.
Ogni input descrive una transazione – un comando che esegue una modifica ai dati gestiti dal sistema.
C’è un componente dispatcher di transazioni che decide cosa fare per ogni transazione.
Questo componente esegue una chiamata a procedura o invia un messaggio ad una serie di componenti che gestiranno la transazione.
1. Modularità: Gli handler delle transazioni sono sistemi che possono essere sviluppati separatamente
2. Coesione: Gli handler delle transazioni hanno coesione procedurale
3. Accoppiamento: Separando il dispatcher dagli handler si riduce l’accoppiamento
7. Flessibilità: Si possono facilmente aggiungere nuovi handlers
11. Progettazione difensiva: Si possono facilmente fare delle asserzioni sugli handler delle transazioni e sul dispatcher
Uno stream di dati, in un formato relativamente semplice, viene sottoposto ad una serie di processi elaborativi (la pipeline).
Ogni procsso trasforma lo stream.
I dati vengono continuamente inseriti nella pipeline.
I processi lavorano concorrentemente, mantenendo costante il flusso nella pipeline.
L’architettura è molto flessibile.
1. Modularità: I processi possono essere progetati separatamente
2. Coesione: I processi hanno coesione funzionale
3. Accoppiamento: Ogni processo comunica solo i propri dati di input e riceve i dati di output da un solo altro processo
4. Astrazione: I componenti della pipeline rappresentano spesso buone astrazioni, e nascondono i loro dettagli interni
5. Riusabilità: I processi possono spesso essere usati in molti contesti differenti
6. Riuso: È spesso possibile trovare componenti riusabili da utilizzare in una pipeline
7. Flessibilità: Il sistema é flessibile potendo modificare ogni processo indipendentemente dagli altri, rispettando le interfacce
10. Testabilità: È di solito facile testare singolarmente I processi
11. Progettazione difensiva: Si possono controllare rigorosamente gli input di ogni componente
Un pattern che aiuta a separare il livello dell’interfaccia utente da altre parti del sistema.
Il model contiene le classi le cui istanze rappresentano i dati da visualizzare e manipolare.
La view contiene oggetti usati per rendere in output, nella UI, i dati contenuti nel model.
Il controller contiene gli oggetti che controlleranno e gestiranno l’interazione dell’utente sia con il livello view che il model.
Il modello non sa nulla della view, nè del livello controller.
1. Modularità: I tre componenti possono essere progettati (più o meno) indipendentemente.
2. Coesione: I componenti hanno maggiore coesione di livello della soluzione in cui vista e controller fanno parte di un solo layer per la UI.
3. Accoppiamento: I canali di comunicazione tra i tre livelli sono minimi.
6. Riuso: La view e il controller fanno normalmente grande uso di componenti riusabili per vari tipi di controlli UI.
7. Flessibilità: é normalmente facile modificare l’interfaccia utente cambiando la View o il Controller, o entrambi.
10. Testabilità: L’applicazione può essere testata indipendentemente dalla UI.
I vari sotto-sistemi si devono scambiare dati. Lo scambio è realizzabile in due modi:
In genere, quando devono essere scambiate grandi quantità di dati, il modello basato su repository è quello più utilizzato.
Esempi: Sistemi gestionali di informazioni, sistemi CAD, e i CASE.
La documentazione di progetto aiuta ad ottenere un buon progetto.
Forza ad essere espliciti e a considerare gli aspetti chiave, prima di iniziare la codifica.
Permette di fare la revisione del documento e dunque di migliorare il progetto.
I documenti di progetto sono uno strumento per la comunicazione.
Evitare di documentare informazioni ovvie a progettisti o programmatori esperti.
Evitare di scrivere dettagli che possono andar meglio come commenti nel codice.
Evitare di scrivere dettagli che possono essere estratti automaticamente dal codice, come la lista dei metodi pubblici.
Richiede esperienza
Una scadente progettazione comporta scarsa manutenibilità
1. Introduzione
4. Casi d'uso
6. Class Diagram – parte prima
7. Class diagram – parte seconda
8. Class diagram – parte terza
9. Modellazione architetturale
10. Sequence Diagram
14. Progettazione Architetturale
15. Design Patterns – Parte prima
16. Design Patterns – Parte seconda
17. Progettazione dell'interfaccia utente
I. Sommerville – Ingegneria del Software – 8a edizione – Cap. 11, 13, 14.
T. Lethbridge, R. Laganière - Object-Oriented Software Engineering: Practical Software Development using UML and Java – Capitolo 9 (http://www.site.uottawa.ca/school/research/lloseng/).