Tesi di laurea di Giancarlo Todone dal titolo
"Progetto e realizzazione di una infrastruttura modulare per acquisizione ed archiviazione remota di documenti"
Progettazione e Sviluppo di un Sistema per Migliorare il Codice Generato da u...
Tesi Todone
1. Università Degli Studi di Trieste
Facoltà di Ingegneria
Corso di Laurea Specialistica in Ingegneria Informatica
Tesi di laurea in reti di calcolatori
Progetto e realizzazione di una infrastruttura
modulare per acquisizione ed archiviazione
remota di documenti
LAUREANDO RELATORE
Giancarlo Todone Prof. Alberto Bartoli
CORRELATORE
Ing. Giorgio Davanzo
Anno Accademico 2008/2009
7. Capitolo 1
Introduzione
La gestione di un documento cartaceo per via informatica inizia con le
operazioni di acquisizione ed archiviazione. Per “acquisizione” si intende
l’operazione di traduzione e codifica di un documento cartaceo in una
forma comprensibile e fruibile da un elaboratore. Per “archiviazione” si
può distinguere tra la mera operazione di immagazzinamento dati e la
“conservazione sostitutiva”—con la quale si intende tutto il complesso
di azioni che permettono di conservare elettronicamente dati di valore
legale o tributario senza per questo conservare anche i documenti cartacei
originali.
A seguito e come proseguimento del tirocinio svolto presso la soft-
ware house MIDA4, lo scrivente ha realizzato un pacchetto software per
consentire di aggiungere le funzionalità di archiviazione al software di
contabilità preesistente GEC. Tale pacchetto fornisce una infrastruttura
per interfacciare GEC con altri sistemi di archiviazione (già esistenti o
futuri) grazie ad un sistema estendibile con plug in, e si inserisce in un
più ampio contesto di gestione documentale in sviluppo nel “Laborato-
rio Reti” del DEEI, Università Degli Studi di Trieste. Un tema trattato
con particolare riguardo è quello dell’archiviazione remota, cioè l’inte-
grazione con servizi di terze parti—come Google Documents o Microsoft
Sharepoint—per la memorizzazione dei dati su un server connesso ad
Internet.
1
8. 2 1. Introduzione
Dall’osservazione della situazione di partenza, dopo lo studio del pro-
blema nella sua accezione più generale, sono stati definiti dei requisiti
che hanno portato alla suddivisione del lavoro nei tre moduli software
responsabili di comunicazione, acquisizione e archiviazione; per ognuno
dei tre moduli sono stati definiti ulteriori requisiti in base ai quali sono
state poi concepite l’architettura e le specifiche tecnologiche di ogni sin-
gola parte. Ogni classe o componente sviluppato è stato verificato con
metodologie di unit-test ed in alcuni casi anche con test automatici di
carico. L’intero progetto ha subito anche diversi test funzionali condotti
da operatori umani.
I requisiti tecnologici del committente hanno portato alla scelta del
linguaggio C# e del framework dotNet all’interno dell’ambiente di svi-
luppo integrato Visual Studio 2008, su un sistema operativo Windows
XP/Vista. L’interfacciamento con le periferiche di acquisizione è gestito
con lo standard TWAIN mentre l’interfacciamento con il software GEC
è gestito con le tecnologie COM e XML.
Nel capitolo 2 si affrontano tematiche di carattere generale inerenti
l’insieme del software sviluppato. Nei tre capitoli successivi ( 3 nella pa-
gina 13, 4 nella pagina 43, 5 nella pagina 73) si affrontano separatamente
i tre moduli software, esponendo di ognuno:
• situazione pregressa e/o requisiti;
• architettura e definizioni;
• tecniche implementative e tecnologie utilizzate;
aggiungendo—ove pertinente—un breve riassunto delle operazioni
necessarie all’installazione e alla manutenzione del modulo.
9. Capitolo 2
Il caso di studio
2.1 Situazione iniziale e requisiti
La software house MIDA4 ha prodotto e mantiene il software di con-
tabilità chiamato GEC. La necessità dei clienti di MIDA4 di archiviare
documenti per via informatica contestualizzandoli con le loro situazioni
amministrative e altri dati, ha spinto la software house a ricercare un
modo per ampliare in tal senso le capacità del suo prodotto.
La richiesta era quella di aggiungere le funzionalità desiderate in un
modo che permettesse di iniziare a servirsi di tecnologie più recenti e
promettenti senza per questo dover riscrivere da capo un programma già
rodato e funzionante come GEC.
GEC viene attualmente fornito in due versioni: installabile e ASP
(2.2):
• la versione installabile è un normale programma che risiede ed ope-
ra sul personal computer dell’utente finale, ed eventualmente co-
munica con un server centralizzato per recuperare informazioni di
licenza ed aggiornamenti;
• la versione ASP consiste nella versione installabile montata però su
un server accessibile da molti fruitori contemporaneamente tramite
Internet ed un software di remote desktop.
3
10. 4 2. Il caso di studio
Il software necessario ad aggiungere le funzionalità di archiviazione de-
siderate, deve necessariamente interagire con GEC—qualsiasi sia la sua
ubicazione—ma deve anche interagire con l’hardware dell’utente fina-
le (es: scanner e fotocamere) e deve essere in grado di comunicare
autonomamente con eventuali servizi di archiviazione di terze parti.
Il modo in cui il nuovo software si integra con GEC deve
1. richiedere il minimo sforzo in termini di modifiche al codice
sorgente di GEC;
2. essere facilmente utilizzabile dagli sviluppatori di GEC;
3. permettere l’integrazione futura con nuovi servizi di terze parti
senza riscrivere il codice sorgente;
per poter permettere rispettivamente:
1. di rendere il più possibile indipendenti lo sviluppo e il manteni-
mento di GEC da quelli del nuovo software di archiviazione;
2. di consentire una rapida integrazione al momento del rilascio;
3. di poter essere rapidamente espandibile con nuove funzionalità.
Dal punto di vista dell’utente, il software sviluppato dev’essere:
• facilmente integrabile con il proprio sistema di produzione;
• di utilizzo semplice ed immediato.
In quest’ottica, un sistema di astrazione delle periferiche di acquisi-
zione immagini dell’utente è stato posto come requisito; fondamentale è
anche la trasparenza di tale meccanismo, necessaria al fine di ottenere
un’interfaccia grafica consistente per tutti gli utenti, a prescindere da
marca e modello dei loro hardware.
Infine, la scelta dell’ambiente di sviluppo ha dovuto tenere conto di
varie richieste:
• GEC opera in ambiente Microsoft Windows, e quindi anche il nuovo
software di archiviazione deve funzionare almeno in tale sistema;
11. Architettura generale e definizioni 5
• esso deve consentire di proporre all’utente finale un’interfaccia
piacevole, immediata e consistente;
• metodologie, linguaggi, librerie, framework utilizzati (a parte quelli
finora citati che hanno diverse motivazioni) devono essere allo stato
dell’arte, o quantomeno ancora vivamente supportati da produttori
e da una nutrita schiera di sviluppatori; essi devono però permet-
tere allo sviluppatore di interfacciarsi anche con moduli software
utilizzanti tecnologie meno recenti, come TWAIN o Visual Basic 6
(di cui—come vedremo—fanno uso alcune parti del sistema).
Da ciò si evince come la capacità di interoperabilità tra diverse tecnolo-
gie sia essa stessa un requisito; viste queste necessità, in fase di analisi
preliminare è stato posto l’utilizzo del dotNet framework di Microsoft
come requisito.
2.2 Architettura generale e definizioni
Per motivi di natura tecnica e per questioni di manutenibilità del codice
che vedremo in seguito, il modulo che dovrà svolgere le operazioni di
acquisizione e archiviazione dev’essere indipendente, cioè non fare parte
di GEC, ma essere compilato in un eseguibile autonomo: questo significa
che GEC e il nuovo software di acquisizione sono due entità distinte che
necessitano di comunicare.
Si considerino quindi i seguenti attori:
GEC è il programma di contabilità già esistente, che dovrà subire delle
modifiche per poter utilizzare SyncUtils e comunicare con il soft-
ware di nuova creazione dedicato all’acquisizione e archiviazione;
in seguito, se non esplicitamente specificato, col nome di GEC ci
si riferirà indistintamente al programma in versione tradizionale o
ASP;
GEC_Scan è il software di acquisizione e archiviazione: esso è un soft-
ware a se stante, ma può dialogare con GEC—tramite un mec-
canismo descritto in 3.3 nella pagina 20—e con servizi di terze
parti—mediante dei moduli aggiuntivi chiamati plug in ( 5.3 nella
pagina 80).
12. 6 2. Il caso di studio
ASP Remote desktop
Internet (A)
User 1
GEC_Scan
ASP Remote desktop
GEC-2 (B)
User 2
ASP
GEC-1
GEC_Scan
GEC-3 (C)
User 3
GEC_Scan
Figura 2.1: Tre casi di utilizzo del sistema di archiviazione: nel caso (A)
l’utente 1 utilizza solo l’istanza 1 di GEC tramite ASP e il suo sistema di
remote desktop; nel caso (C) l’utente 3 utilizza solo GEC-3 in esecuzione sul
suo computer locale; nel caso (B), l’utente 2 utilizza sia la locale istanza 2 di
GEC, sia GEC-1 tramite sistema ASP.
Queste due entità devono poter comunicare tra loro in vario modo.
Nel caso più semplice GEC e GEC_Scan vengono eseguiti sullo stesso
calcolatore e comunicano senza interferenze esterne; in figura 2.1 si os-
servano anche i casi in cui GEC sia remoto e quello più complesso in cui
13. Architettura generale e definizioni 7
un solo utente utilizzi più istanze di GEC, eventualmente miste tra locali
e remote.
plug in
SyncUtils
GEC GEC_Scan plug in
plug in
acquisizione archiviazione
comunicazioni funzionalità
software software
preesistente nuovo
Figura 2.2: Descrizione dei software coinvolti; GEC è preesistente e viene
modificato solo per poter usare SyncUtils; il resto del software è sviluppato
ex novo; di questo è visibile la suddivisione in comunicazioni, acquisizione ed
archiviazione: solo le ultime due implementano funzionalità richieste, mentre
la prima serve a rendere interoperabili nuovo e vecchio software.
Come illustrato in figura 2.2, tutte le funzionalità aggiunte risiedono
in GEC_Scan e nei suoi plug in, mentre la libreria SyncUtils consente a
GEC di comunicare con GEC_Scan e di utilizzare tali funzionalità.
Si consideri inoltre la seguente nomenclatura:
Utente è l’utente finale di GEC e di GEC_Scan, colui che opera i pro-
grammi per archiviare documenti; si faccia attenzione alla differen-
za tra “utente finale” e l’utente di una libreria (sviluppatore) o di
un servizio (potrebbe essere un modulo software);
14. 8 2. Il caso di studio
Documento un insieme di più immagini corredate da meta dati;
ASP acronimo di Application Service Provider, è il sistema che permet-
te tramite un remote desktop di utilizzare dal PC dell’utente finale
un’istanza di GEC in esecuzione su un server remoto; da non con-
fondersi con Active Server Pages di Microsoft (di cui non si parla
mai in questo testo);
Plug in è un modulo software che consente di aggiungere funzionalità
a GEC_Scan senza la necessità di modificare o ricompilare il suo
codice sorgente;
Servizio esterno un qualsiasi servizio di archiviazione di documenti
estraneo sia a GEC che a GEC_Scan, probabilmente pubblicato
tramite un servizio web.
Sessione di acquisizione l’insieme di operazioni iniziate dall’utente
che portano all’acquisizione, riorganizzazione in documenti e archi-
viazione di un insieme di immagini con i loro meta dati associati
(punti da 2 a 9 in 2.2.1 nella pagina 10 e figura 2.3; si noti che tra il
punto 3 e il punto 4 il sistema rimane indefinitamente in attesa di
istruzioni dall’utente; quindi può essere un operazione che richiede
molto tempo).
In aggiunta—se non per esigenze particolari—si eviterà di seguito l’uti-
lizzo di termini come “server” e “client” per riferirsi a GEC o GEC_Scan,
poiché potrebbero essere causa di fraintendimenti; infatti nella sua ver-
sione ASP, il software GEC viene eseguito su una macchina che interpreta
il ruolo di server, ma per correttezza dovrebbe essere considerato client
del software di acquisizione che gli offre per l’appunto un servizio.
15. Architettura generale e definizioni 9
2.2.1 Flusso di un tipico caso di utilizzo
1.richiede inizio
sessione di acquisizione
Utente
2.Request 3.mostra form
principale
Acquisizione
(tempo
indefinito)
4.accetta o
annulla
(C): GEC_SCAN
(B): SyncUtils
(A): GEC
tempo
5.esegue il
plug in adeguato
6.sottomette
(E): Servizio esterno
documenti
(D): Plug in
7.fine del job
8.fine del job
9.Response
Figura 2.3: Flusso di esecuzione di una richiesta e relativa risposta; vede-
re 2.2.1 nella pagina successiva per una descrizione puntuale dei passi nume-
rati; la progettazione e creazione delle entità marcate come (B), (C) e (D)
costituiscono il caso di studio; le linee ondulate indicano il punto in cui l’utente
può causare un’attesa a tempo indeterminato del sistema; (B) risolve i proble-
mi di comunicazione tra (A) e (C) siano essi sulla stessa macchina oppure su
macchine diverse comunicanti tramite Internet.
16. 10 2. Il caso di studio
Un tipico caso di utilizzo del sistema—nel quale una singola istanza di
GEC comunica con una singola istanza di GEC_Scan—si svolge co-
me di seguito (i punti numerati si riferiscono a figura 2.3 nella pagina
precedente):
• il sistema dell’utente si avvia; parte automaticamente anche il soft-
ware di acquisizione e carica dalla cartella plugins le estensioni
di cui è stato dotato;
• l’utente carica e opera GEC (versione installabile o ASP), mentre
il programma di acquisizione (eseguito allo start up sul sistema
dell’utente) resta in attesa nascosto;
1. l’utente esegue un’operazione su GEC per la quale è prevista
l’acquisizione di un certo numero di documenti;
2. GEC—tramite una chiamata all’apposita libreria di comunicazione
SyncUtils—effettua una richiesta a GEC_Scan; ad esso (sia que-
sto in esecuzione sulla medesima macchina o su di una diversa)
viene segnalato di mostrare la sua finestra principale, inviandogli
nel contempo i meta dati da associare ai documenti che si andrà
ad acquisire ed una lista di azioni desiderate da intraprendere su
di essi; se la finestra era già aperta a seguito di una precedente
richiesta non ancora soddisfatta, il lavoro viene messo in coda;
3. GEC_Scan accetta la richiesta e la accoda ad una lista o la scarta
rispondendo con una lista di errori (ad esempio quando non è in
grado di gestire la richiesta);
4. l’utente usa le funzionalità del programma di acquisizione per scan-
sionare1 ed ordinare un certo numero di pagine inerenti la richiesta
accettata; l’utente può inserire dei separatori tra gruppi di immagi-
ni per organizzare il materiale acquisito in documenti: ad ogni do-
cumento vengono associati tutti i meta dati ricevuti; alla fine della
riorganizzazione e separazione dei documenti, l’utente sottomette
i dati o annulla la sessione con appositi comandi;
1
Sulla scelta tra gli equivalenti italiani dell’inglese “to scan” l’Accademia della
Crusca si è espressa nelle “Risposte ai quesiti” concludendo che sono accettabili tutte
le soluzioni (scandire, scannare, scannerare, scannerizzare, scansionare) [3].
17. Cenni di implementazione e tecnologie utilizzate 11
5. GEC_Scan cerca tra i plug in caricati quelli in grado di soddisfare
le richieste effettuate da GEC tramite la libreria di comunicazione
ed esegue ogni operazione ritenuta pertinente su ogni documento;
6. questo può comportare il dialogo con un ulteriore software di ar-
chiviazione, anche residente su una macchina diversa da quella su
cui è in esecuzione GEC e da quella su cui esegue il programma
di acquisizione (esempio: inviare tutti i documenti ad un servizio
web);
7. il software di acquisizione completa ogni elaborazione e compila un
rapporto con il dettaglio delle operazioni effettuate e un’eventuale
lista di errori;
8. il software di acquisizione invia la risposta così costruita a GEC
sempre tramite libreria di comunicazione;
9. GEC riceve la notifica che i suoi lavori richiesti sono stati
completati (o annullati);
• nel caso la coda di lavori del software di acquisizione non sia vuo-
ta, l’utente viene invitato a continuare il suo lavoro con un’altra
sessione di sottomissione documenti.
2.3 Cenni di implementazione e tecnologie
utilizzate
Il programma preesistente GEC è stato sviluppato in Visual Basic 6,
kit di sviluppo capace di generare file di codice eseguibile nativo; esso
permette anche una buona interazione con componenti COM.
Nei seguenti tre capitoli, viene trattato il software sviluppato ex novo
per aggiungere a GEC le funzionalità di acquisizione e archiviazione:
libreria di comunicazione (progetto di nome “SyncUtils”) che per-
mette ad un’istanza di GEC di effettuare richieste ad un’istanza di
GEC_Scan e riceverne risposta, in 3 nella pagina 13;
18. 12 2. Il caso di studio
software GEC_Scan che tramite interfaccia grafica permette l’acqui-
sizione di documenti, in 4 nella pagina 43;
plug in che permettono a GEC_Scan di accedere a servizi di
archiviazione di terze parti, in 5 nella pagina 73.
Tutti questi moduli software sono stati sviluppati nel linguaggio C# e
utilizzano quindi il dotNet framework (versione 2.0 o successive).
Con riguardo alla libreria di comunicazione, in 3.3.8 nella pagina 35
si parla della necessaria metodologia di interazione tra codice mana-
ged e codice nativo: l’utilizzo di oggetti dotNet come componenti COM
tramite software wrapper.
Quest’ultimo sistema è stato adottato per permettere a GEC di chia-
mare delle funzioni sviluppate con tecnologia dotNet; in questo modo la
libreria SyncUtils è richiamabile sia da codice nativo (come avviene per
GEC) sia da codice dotNet.
Le funzioni di comunicazione utilizzano un meccanismo di sincronia e
comunicazione basato sulla condivisione di un file system ( 3.2 nella pa-
gina 14) per scambiarsi messaggi XML (formato descritto in 3.3.6 nella
pagina 28) secondo il protocollo descritto in 3.3.4 nella pagina 24. La ge-
nerazione del codice XML avviene tramite meccanismo semi automatico
per serializzazione di oggetti ( 3.3.7 nella pagina 32).
Per l’interfacciamento di GEC_Scan con le periferiche di acquisizio-
ne immagini è stato usato TWAIN ( 4.2.1 nella pagina 50)—secondo
le specifiche versione 1.9 [5]—tramite l’apposito sviluppo della libreria
dotNetTwain. TWAIN si presenta come una DLL contenente codice
nativo a 32 bit; per l’utilizzo da parte di dotNet, è quindi necessa-
rio adottare ulteriori tecniche di interoperabilità con l’aiuto del package
System.Runtime.InteropServices ( 4.3.1 nella pagina 59).
Ogni plug in è stato sviluppato come una classe dotNet residente
in un assembly dotNet2 . Per permettere il rapido sviluppo di plug in
sono state sfruttate alcune caratteristiche del framework dotNet come
reflection e caricamento dinamico di classi.
2
Un assembly dotNet è una DLL contenente bytecode dotNet nella forma di una
o più classi appartenenti anche a diversi namespace, con i rispettivi meta dati di
contorno.
19. Capitolo 3
SyncUtils
3.1 Requisiti e scopi di SyncUtils
La parte del progetto che deve interagire più intimamente con GEC è la
libreria di comunicazione chiamata SyncUtils. Mentre le funzionalità di
archiviazione aggiuntive risiedono principalmente in GEC_Scan e nel-
l’insieme dei suoi plug in, esse non potrebbero essere utilizzate da GEC
senza l’ausilio di questa libreria: il suo scopo è quello di astrarre il meto-
do di comunicazione dalle modalità tecniche con le quali le comunicazioni
effettivamente avvengono.
L’ambiente nel quale il sistema progettato deve operare prevede:
• molti software di scansione (GEC_Scan) che hanno a disposizione
varie sorgenti di dati e vengono manovrati da operatori umani;
• uno o più software di controllo (GEC) che possano richiedere
ad uno dei software di scansione di cominciare una sessione di
acquisizione.
GEC_Scan deve essere in grado di accettare una richiesta di inizio proce-
dura di acquisizione, gestirla autonomamente e inviare alla fine la notifica
dell’avvenuto lavoro senza tenere GEC in sospeso, permettendogli così
di gestire nel frattempo eventuali altre comunicazioni.
13
20. 14 3. SyncUtils
Siamo perciò interessati ad un tipo di comunicazione nella quale—nel
caso peggiore (facendo riferimento alle figure 2.1 nella pagina 6 e 3.1):
• come attori, sono coinvolte m istanze di GEC in versione installa-
bile (al massimo una per macchina), n istanze remote di GEC in
versione ASP, i istanze di GEC_Scan (al massimo una per macchi-
na), con i, m ed n numeri imprecisati non necessariamente uguali,
maggiori di 1;
• ogni attore può prendere l’iniziativa di parola;
• ogni GEC in versione installata può parlare col GEC_Scan
presente sulla sua stessa macchina (se presente);
• ogni GEC in versione ASP può parlare con qualsiasi GEC_Scan;
• ogni GEC_Scan può parlare con GEC installato sulla sua stessa
macchina e con qualsiasi altro GEC in versione ASP.
Cioè: ogni utente col suo calcolatore deve poter usare la sua unica
copia di GEC_Scan facendola interagire con un GEC installato sulla sua
stessa macchina e/o con un certo numero di altri GEC remoti.
3.2 Architettura
Si assuma che ogni copia di GEC_Scan abbia accesso in lettura e scrit-
tura ad una porzione privata del file system dell’elaboratore sul quale
è installato; chiunque voglia dialogare con esso (ad es. GEC installato
o GEC versione ASP) dovrà poter avere accesso in lettura e scrittura
alla stessa porzione del file system (per brevità di seguito “file system” o
“FS”).
La comunicazione è dunque a mezzo condiviso, nel senso che gli attori
che dialogano tra loro di volta in volta devono condividere un file system
cui hanno accesso; per analizzare il caso più generale continueremo a
dire che ogni GEC condivide con l’i-esimo GEC_Scan il file system i (o
FS-i).
Le richieste vengono effettuate da un GEC scrivendo nel FS-i dei
file con estensione .IN contenenti i dettagli delle richieste in formato
21. Architettura 15
XML ( 3.3.6 nella pagina 28); le risposte al termine di una sessione di
acquisizione vengono fornite da GEC_Scan scrivendo nel FS-i dei file
con estensione .OUT e nome file uguale alla corrispondente richiesta.
GEC
ASP
ASP
GEC GEC
FS-i
GEC_Scan-i
Figura 3.1: Schema dell’utilizzo concorrente da più istanze di GEC del
file system i, associato alla i-esima istanza di GEC_Scan.
Naturalmente, più processi potrebbero accedere contemporaneamen-
te ad uno stesso file system; è tuttavia stato approntato un meccanismo
di mutua esclusione (descritto in 3.3.2 nella pagina 21):
• per fare in modo che ogni richiesta abbia un nome univoco sul
file system i;
• per garantire che più GEC concorrenti nell’effettuare una richiesta
allo stesso GEC_Scan non si intralcino a vicenda;
• per fare in modo che le richieste siano ordinabili—per istante di
arrivo—in una coda.
22. 16 3. SyncUtils
Un attore che voglia prendere possesso del mezzo comunicativo costitui-
to dal FS-i, per prima cosa utilizzerà detto meccanismo impedendo a
qualunque altro attore di impadronirsi a sua volta del file system.
Ovviamente non sempre un attore riesce a prenotare l’uso esclusivo
del file system, ad esempio quando questo è già in uso da un altro attore;
in seguito ( 3.3.2 nella pagina 21) si darà spiegazione dei dettagli del
meccanismo: si dica “tentativo di acquisizione del lock ” il tentativo di
impadronirsi del mezzo di comunicazione, e “acquisizione del lock ” il
provare reiteratamente ad acquisire il lock finché non si abbia successo.
La generazione di un nome file univoco nel FS-i, necessaria per la
scrittura dei file .IN dipende da una stringa originata a partire dalla da-
ta/ora della sua creazione: questa stringa e l’entità che essa rappresenta
assumono il nome di JobId. Definiamo quindi un JobId come l’iden-
tificativo univoco all’interno di un file system, utilizzato per identificare
esattamente richieste e relative risposte.
Ogni file di nome {JobId}.IN contiene delle informazioni organiz-
zate in un’entità chiamata Request; ogni file di nome {JobId}.OUT
contiene dati relativi ad un’entità di tipo Response.
Come si può osservare in figura 3.2 nella pagina successiva, ogni
Request contiene:
• una o più ActionRequest;
• uno e un solo AdditionalData;
• un Timestamp.
In ottica di programmazione ad oggetti, ActionRequest e
AdditionalData sono solo delle classi base astratte, atte a definire
l’archetipo dei campi contenuti in ogni richiesta: una Request ben for-
mata non conterrà mai direttamente una ActionRequest, bensì una
classe derivata da essa (similmente per AdditionalData ed altre clas-
si simili); d’ora in avanti per “una ActionRequest” ad esempio, si
intenderà una qualsiasi entità che derivi da ActionRequest e non un
oggetto di tipo ActionRequest, se non diversamente specificato.
23. Architettura 17
Response
Request Document
Page
ActionRequest ActionResponse
ResponsePage Page
ActionRequest ResponsePage
Page
ActionResponse
ResponsePage Page
AdditionalData
ResponsePage
Document
ActionResponse Page
ResponsePage
ActionResponse
ResponsePage
Figura 3.2: Esposizione grafica della struttura di Request e Response; le
frecce indicano che l’oggetto d’origine mantiene internamente un riferimento
all’oggetto puntato.
Le azioni intraprese da GEC_Scan alla ricezione di una Request
dipendono dal tipo specializzato di ogni ActionRequest contenuta;
AdditionalData contiene dei meta dati che devono essere interpreta-
ti da GEC_Scan per soddisfare correttamente ogni richiesta e possono
essere associati ai documenti acquisiti.
24. 18 3. SyncUtils
Per quanto riguarda Response essa contiene sempre:
• la sezione Documents;
• la sezione Errors, relativa agli errori generici di comunicazione.
Si ponga attenzione sul fatto che un documento è stato definito come
un’insieme di una o più immagini: finora non si è parlato di alcun limite
al numero di immagini acquisibili dall’utente, o di vincoli sul modo di
raggrupparle in documenti; quindi nè il numero di documenti che ver-
ranno elaborati nè il numero di pagine di ognuno di questi è predicibile
salvo casi particolari1 .
Per questi motivi, in una Response
• Documents contiene uno o più oggetti Document, entità
rappresentante un gruppo di immagini;
• ogni Document contiene una lista di oggetti Page, entità
rappresentanti le singole immagini scansionate dall’utente;
• ogni Document contiene una o più ActionResponse (con
considerazioni simili al caso di ActionRequest);
• ogni ActionResponse rappresenta il rapporto su una sola
azione intrapresa per il Document che la contiene in seguito
all’elaborazione di una ActionRequest;
• ogni ActionResponse contiene una lista di ResponsePage,
enumerazione delle azioni intraprese sulle singole Page del
Document.
Anche in questo caso l’esatto contenuto di una ActionResponse dipen-
de dalla classe specializzata che la estende. Si pensi al seguente esempio
pratico: si ha la necessità di archiviare una fattura del signor Mario Ros-
si presso un servizio di archiviazione remota chiamato “MyArchive”; a
tale scopo saranno stati precedentemente definiti alcuni tipi specializzati
come
1
In realtà GEC può richiedere un numerno minimo ed uno massimo di gruppi di
immagini (vedi 4.1.1 nella pagina 47).
25. Architettura 19
• SendToMyArchiveActionRequest;
• SendToMyArchiveActionResponse;
• SendToMyArchiveActionPerformer;
• SendToMyArchiveResponsePage;
derivanti rispettivamente da
• ActionRequest;
• ActionResponse;
• ActionPerformer;
• ResponsePage.
In più, per veicolare correttamente i dati relativi ad una fat-
tura, InvoiceAdditionalData è stato derivato—con l’ag-
giunta di appositi campi—da AdditionalData. A que-
sto punto è possibile costruire una Request contenente ad
esempio una sola SendToMyArchiveActionRequest ed un
InvoiceAdditionalData.
SendToMyArchiveActionRequest conterrà informazioni relative
l’indirizzo al quale raggiungere il servizio MyArchive ed
impostazioni simili;
InvoiceAdditionalData potrebbe contenere l’anagrafica del signor
Mario Rossi e ogni altro dato utile ai fini della compilazione dei
meta dati associati ai documenti veri e propri.
Se l’utente ha acquisito due documenti da tre pagine ciascuno, con tale ri-
chiesta è lecito aspettarsi una risposta per cui vi saranno due Document
contenenti tre Page e una SendToMyArchiveActionResponse cia-
scuno; ogni SendToMyArchiveActionResponse conterrà a sua volta
tre SendToMyArchiveResponsePage, ognuna delle quali—facendo
riferimento ad una singola Page—fornirà ad esempio informazioni sul
successo o meno dell’archiviazione, un link per recuperare l’immagine
corrispondente ecc. . .
26. 20 3. SyncUtils
Tutti i tipi specializzati, finalizzati a specifiche richieste, sono defi-
niti nei moduli aggiuntivi chiamati plug in, caricati in modo dinamico
all’avvio di GEC_Scan.
3.3 Dettagli implementativi e tecnologie
Posto che GEC_Scan è un modulo software a se stante, anche il solo
aggiungere a GEC le funzionalità di comunicazione con quest’ultimo ri-
chiede necessariamente la modifica del programma e l’aggiunta di molto
codice.
Integrare direttamente in GEC queste capacità sviluppandole in Vi-
sual Basic 6—lo stesso linguaggio in cui è stato scritto—sarebbe potuta
sembrare una buona idea: al contrario, aggiungere a del codice già ma-
turo una ulteriore complessità per quanto lieve, potrebbe portare a dei
problemi di manutenibilità.
Se si aggiunge il fatto che il kit di sviluppo di Visual Basic 6 è alla
fine del suo ciclo di vita, si capisce come sia stato preferibile comporre il
sistema di comunicazione con una tecnologia più moderna: si è scelto di
sviluppare con dotNet e la tecnologia COM del codice che—proprio dal
punto di vista del ciclo di vita—è autonomo e interfacciabile con GEC
con un ridotto numero di modifiche a quest’ultimo.
La libreria SyncUtils è utilizzabile da codice dotNet come un qualsiasi
altro assembly e (previa registrazione di alcuni tipi, 3.4 nella pagina 40)
come componente COM.
3.3.1 Perché il file system?
La comunicazione tra sistemi informatici è sempre un ambito insidioso
e ricco di difficoltà, spesso nemmeno troppo palesi; anche per questo
motivo, nell’affrontarlo si tenta quasi sempre di evitare di reinventare la
ruota: come in molte altre situazioni ci si affida più il possibile a soluzioni
già note ed affermate, almeno per i problemi più comuni.
Nel caso in esame, ci si trova nella situazione abbastanza tipica di un
software (GEC_Scan) che pur eseguendo sull’elaboratore di un utente
finale (ed essendo perciò molto probabilmente isolato dalla rete da un
27. Dettagli implementativi e tecnologie 21
firewall e da un sistema NAT/NAPT) deve comportarsi come server,
attendendo richieste e non iniziandole.
Le possibili soluzioni note che usino protocolli consueti come
TCP/IP, sarebbero comunque state tutte piuttosto complesse da mettere
in pratica: fortunatamente il sistema ASP—come già accennato—mette
a disposizione un file system condiviso tra i suoi utilizzatori.
L’utilizzo di un file system condiviso per la sincronia tra processi, la
regolamentazione di accesso esclusivo a risorse e lo scambio di informazio-
ni, è una pratica da tempo largamente diffusa e di dimostrata efficacia2 :
lo studio di alcune specifiche Microsoft [8] ed alcuni esperimenti condotti,
hanno consentito di giudicare tali metodologie idonee anche all’utilizzo
su un file system condiviso con una macchina remota tramite il sistema
ASP.
Ciò permette di delegare al gestore del file system alcune problemati-
che descritte in seguito come l’atomicità della creazione di un oggetto di
sincronia, la sicurezza del canale trasmissivo, la capacità di comunicare
in determinate condizioni.
3.3.2 Meccanismo di sincronizzazione
L’acquisizione del lock per il file system i, si effettua tramite la scrittura
in esso di un file—vuoto—di nome concordato che non possa collidere
con gli eventuali file .in e .out già presenti (attualmente esso si chiama
lockfile.lck). Si dice che tale lock viene rilasciato quando il file viene
cancellato.
Un attore che volesse acquisire il lock dovrebbe per prima cosa veri-
ficare che tale file non esista già e solo in tal caso provvedere a crearlo;
una volta creato, altri attori desiderosi di acquisire il lock rileverebbero
la presenza del file sopra citato e desisterebbero (o resterebbero in attesa
che il file venga rimosso, a seconda dei casi).
È di fondamentale importanza capire come l’operazione di verifica e
creazione del file di lock debba necessariamente essere atomica per gestire
le eventuali situazioni di concorrenza: non è accettabile alcuna situazio-
2
Basti pensare ai files di lock utilizzati da alcuni software di database o a quelli
usati del popolare Microsoft Word per regolare l’accesso ai suoi documenti.
28. 22 3. SyncUtils
ne di inconsistenza come quella riportata di seguito a titolo d’esempio:
nell’ordine
1. l’attore A vuole acquisire il diritto di parola, pertanto tenta di
segnalarlo, provando a creare il file di lock ;
2. in un istante di tempo ravvicinato ad (1) l’attore B vuole acquisire
anch’esso il diritto di parola, pertanto tenta di creare a sua volta
il file di lock ;
3. A verifica che il file di lock non esiste;
4. B verifica che il file di lock non esiste;
5. A crea fisicamente il file di lock ;
6. B—visto il punto 4—crede che il file di lock non esista e lo
sovrascrive.
Se il sistema di sincronia fosse prono ad un tale tipo di errore, due attori
potrebbero ritenere di essere ognuno l’unico autorizzato ad accedere al
file system in un dato istante di tempo, creando JobId non certamente
univoci e sovrascrivendo potenzialmente l’uno i file dell’altro, portando
così ad evoluzioni impredicibili nella comunicazione.
Il problema della atomicità delle operazioni di verifica e creazione
del file di lock viene risolto considerando che all’atto della creazione di
un nuovo file, in ambiente Microsoft Windows si può indicare al sistema
cosa fare nel caso in cui non sia possibile completare l’operazione (es:
perché il file esiste già): sovrascrivere il file, accodare al contenuto o
segnalare un’errore. Quando un attore desidera acquisire il lock, può
semplicemente provare a creare il file, istruendo il sistema operativo a
sollevare un’errore in caso di fallimento: se non si riceve alcun errore il
lock è acquisito, altrimenti no.
Al sistema operativo si delega la responsabilità della consistenza del
suo file system; in caso di file system remoti, il sistema operativo che
fornisce l’accesso remoto ad un file system da lui mantenuto si occupa di
garantire la consistenza quando più processi tentino di creare lo stesso
file [8].
29. Dettagli implementativi e tecnologie 23
Per impedire che altri processi come un antivirus o lo stesso uten-
te possano inavvertitamente interferire col meccanismo di sincronia, il
file viene mantenuto aperto in modalità esclusiva per tutto il tempo di
detenzione del lock : in questo modo è impossibile per chiunque altro
cancellarlo, rinominarlo o modificarlo.
Nel caso il processo detentore del lock venga terminato, il file resta
scritto sul file system, ma la modalità esclusiva viene a mancare: ogni
eventuale altro processo in attesa di rilascio del lock non avrà speranze
di acquisirlo fino al prossimo riavvio di GEC_Scan che causa la pulizia
dei file residui di vecchie esecuzioni.
3.3.3 Identificativi di richieste e risposte
Richieste e risposte vengono scambiate tramite dei file di estensione .IN
e .OUT, diversi dal file di lock ma residenti nel suo stesso file system.
Questi file hanno sempre il nome costituito da dodici cifre ed un trattino
orizzontale, che rappresenta il JobId del lavoro in questione.
Un JobId è stato definito come l’identificativo univoco all’interno
di un file system, utilizzato per identificare univocamente richieste e ri-
sposte. Esso viene generato a partire dalla data-ora della sua creazione;
nell’implementazione C# è in realtà un oggetto che conserva come stato
interno un timestamp, e permette di ricavare da questo una rappresenta-
zione stringa nel formato yyyyMMdd-hhmmss dove “y” sono le quattro
cifre corrispondenti all’anno, “M” quelle corrispondenti al mese, “d” al
giorno, “h” all’ora, “m” ai minuti e “s” ai secondi.
Per creare un JobId valido (avendo certezza della sua univocità per
un determinato file system) ed associarlo ad una richiesta si effettua la
seguente procedura:
• si acquisisce il lock ;
• si crea a partire da data e ora correnti la stringa
yyyyMMdd-hhmmss;
• si usa la stringa come nome file, considerando che l’estensione per
una richiesta dev’essere .IN;
30. 24 3. SyncUtils
• se tale nome file esiste già, si incrementa di uno il numero indi-
viduato graficamente da yyyyMMddhhmmss e si torna al punto
precedente (senza preoccuparsi del fatto che il numero corrisponda
ancora ad una data-ora valida; es: 800419170261 non corrisponde
ad una data-ora valida, ma è comunque valido come base per creare
un JobId);
• si crea il file;
• si scrive una richiesta valida nel file;
• si rilascia il lock.
Una risposta ad una richiesta ha il suo stesso nome file ma con estensione
.OUT; i file di richiesta e di risposta, contengono dati in formato che
vedremo in seguito (vedi 3.3.6 nella pagina 28).
Spesso una risposta fornisce anche un certo quantitativo di dati—
nel nostro caso, ad esempio le immagini catturate: formato e ubicazione
di questi dati sono indipendenti dal sistema di comunicazione, e deter-
minati dai singoli plug in che gestiscono l’archiviazione (vedi 5.2 nella
pagina 76), ma vengono comunque specificati in apposite sezioni nel file
.OUT.
3.3.4 Protocollo
Di seguito vengono riportate in pseudo codice alcune delle procedure che
costituiscono il protocollo di comunicazione3 . Le procedure con prefisso
GEC sono eseguite su iniziativa di GEC sulla macchina ove questo è in
esecuzione, mentre quelle con prefisso SCAN si riferiscono al software
di scansione GEC_Scan. FS sta per file system. L’indice i riferisce il
prefisso al file system i-esimo. “Lavoro” o “Job” è il termine generico per
indicare una richiesta, solitamente coincidente con la richiesta di inizio
sessione di acquisizione.
3
Protocollo studiato dal prof. Alberto Bartoli con l’aiuto della documentazione
prodotta dall’ing. Giorgio Davanzo; implementazione pratica in C#, sostituzione
dell’active poll con sistemi di notifica e cura di dettagli tecnici pratici a cura di
Giancarlo Todone.
31. Dettagli implementativi e tecnologie 25
Algorithm 3.1 Lock-CleanUp: Da eseguire all’avvio di GEC_Scan.
1: if EXISTS(lockfile-i) then
2: TIMEOUT = 10sec
3: BeginWait = now()
4: while now() BeginWait + TIMEOUT do
5: if NOT EXISTS(lockfile-i) then
6: break;
7: end if
8: end while
9: DELETE lockfile-i
10: end if
Algorithm 3.2 GEC-RequestJob: Da eseguire per richiedere un lavoro.
1: GET lock-i
2: GET NEW JobId-i
3: RELEASE lock-i
Algorithm 3.3 GEC-Abort: Da eseguire per annullare una richiesta di
lavoro pendente su iniziativa di GEC, dato il suo JobId.
1: GET lock-i
2: DELETE request-file (filename = JobId.IN) in FS-i
3: RELEASE lock-i
Algorithm 3.4 SCAN-CleanUp: Da eseguire all’avvio del programma
di scansione; FS-i viene riportato nello stato iniziale. Per semplicità,
non si cerca di recuperare eventuali lavori effettuati nella incarnazione
precedente ma non completati.
1: EXEC Lock-CleanUp
2: GET lock-i
3: DELETE ALL response, data, request files (in quest’ordine)
4: RELEASE lock-i
32. 26 3. SyncUtils
Algorithm 3.5 SCAN-Abort: Da eseguire per annullare (su iniziativa
del software di acquisizione) una richiesta di lavoro pendente, dato il suo
JobId.
1: GET lock-i
2: GENERATE EMPTY response-file (name = JobId.OUT) in FS-i
3: RELEASE lock-i
Algorithm 3.6 SCAN-CompleteJob Da usarsi per segnalare il
completamento (andato a buon fine o meno) di una richiesta di lavoro.
1: GET lock-i
2: if EXISTS(Input) then
3: CREATE data-files in FS-i
4: CREATE Output-file in FS-i
5: else
6: DISMISS data
7: end if
8: RELEASE lock-i
In pratica:
• Per effettuare una richiesta, il GEC deve:
acquisire il lock;
calcolare un JobId valido;
scrivere un file {JobId}.IN contenente la richiesta nel
corretto formato;
rilasciare il lock;
restare in attesa che venga scritto nella stessa posizione un
file con lo stesso nome ma estensione .OUT.
• Per recepire la richiesta ed effettuare una risposta, il GEC_Scan
deve:
restare in attesa finché sul file system predefinito non viene
creato un file con nome corrispondente ad un JobId valido
ed estensione .IN;
33. Dettagli implementativi e tecnologie 27
acquisire il lock;
leggere il contenuto del file di richiesta;
rilasciare il lock ;
elaborare la richiesta;
acquisire il lock ;
scrivere il file .OUT;
rilasciare il lock.
Come si può notare dall’ultima esemplificazione, l’elaborazione viene
fatta da GEC_Scan mentre il lock non è mantenuto, per permette-
re che altre comunicazioni avvengano mentre è in atto un processo di
archiviazione molto lungo.
Inoltre è visibile che se GEC_Scan notasse la presenza del file di
richiesta e tentasse di leggerlo prima che il GEC abbia finito di scriverlo,
non vi riuscirebbe semplicemente perché prima dovrebbe acquisire il lock
ancora detenuto dalla controparte. Un analogo ragionamento si può fare
per il file di risposta.
Se questo tipo di meccanismo da un lato permette una corretta evolu-
zione delle dinamiche di comunicazione, dall’altro introduce anche delle
situazioni in cui i processi comunicanti si intralciano a vicenda, spre-
cando delle risorse; per questo motivo nell’implementazione reale degli
algoritmi di comunicazione si sono previsti dei piccoli ritardi program-
mabili, impostati poi a valori dedotti in modo sperimentale. Questi non
alterano in alcun modo la logica della comunicazione, ma minimizzano i
tempi di attesa attiva di ciascuna parte.
3.3.5 Problematiche delle notifiche
Inizialmente si erano concepite ulteriori due procedure:
SCAN-CheckForRequests con la quale il software di acquisizione
controllava l’eventuale arrivo di nuove richieste;
GEC-CheckJobCompleted che si occupava di controllare—dal lato
di GEC—se una richiesta fatta in precedenza non fosse stata
soddisfatta.
34. 28 3. SyncUtils
Le due funzioni utilizzavano la tecnica dell’active poll, interrogando di
continuo il file system sulla presenza o meno di determinati file. Consi-
derato che questo caricava notevolmente i file system (e in minor parte
anche la rete, in caso di sistema acceduto da remoto) si è provveduto
a modificare il meccanismo in modo da utilizzare strumenti chiamati
FileSystemWatcher [9].
Questi consistono fondamentalmente in hook 4 di sistema alle funzioni
di base di accesso al disco, che sollevano un evento quando si presentano
determinate condizioni, come il tentativo da parte di un programma di
scrivere un nuovo file in una cartella.
Purtroppo, come rilevato anche da una nutrita schiera di utenti5 ,
il codice che implementa questa tecnica a volte ha dei comportamenti
inattesi quando eseguito in ambiente Microsoft Windows 2003 Server.
All’epoca della prima stesura del programma non erano disponibili
dei work around efficaci o soluzioni pubbliche: si è stati costretti a svi-
luppare una soluzione alternativa poi segnalata sulla pagina ufficiale di
bug report6 .
La soluzione consiste nel sopperire ai comportamenti inattesi con de-
gli snapshot della cartella ove avvengono gli scambi dei file: se tutto
funziona come da specifiche Microsoft, l’esecuzione procede normalmen-
te e le operazioni sul file system generano le notifiche attese; se invece
qualcosa dovesse andare male, viene richiamato un gestore d’errore con
del codice d’emergenza che confrontando il sotto albero della cartella al
momento dell’errore con quello stimato durante le esecuzioni corrette, lo
aggiorna e genera le notifiche di conseguenza.
3.3.6 Formati dei file di comunicazione
Il formato interno dei file di comunicazione si basa su XML. Una richiesta
tipo, contenuto di un file .IN si presenta come nel listato 3.1.
4
Tecnica di intercettazione e modifica al volo di dati comunicati tra funzioni di
sistema; può essere “installato” in una catena di messaggi o in mezzo ad una serie di
chiamate a routine [10, 13].
5
https://connect.microsoft.com/VisualStudio/feedback/
ViewFeedback.aspx?FeedbackID=337917
6
https://connect.microsoft.com/VisualStudio/feedback/
Workaround.aspx?FeedbackID=337917
35. Dettagli implementativi e tecnologie 29
Listing 3.1: Esempio di XML generato da SyncUtils per effettuare una
richiesta.
1 Request
2 ActionRequest xmlns:xsi=http://www.w3.org/2001/
XMLSchema-instance xmlns:xsd=http://www.w3.org
/2001/XMLSchema xsi:type=SaveToFileActionRequest
ARQID=0
3 Performer name=SaveToFileActionPerformer /
4 RequiredFileFormatpng/RequiredFileFormat
5 Pathc:lockpath/Path
6 /ActionRequest
7 AdditionalData xmlns:xsi=http://www.w3.org/2001/
XMLSchema-instance xmlns:xsd=http://www.w3.org
/2001/XMLSchema
8 OwnerID64/OwnerID
9 CustomerIDmyCustomerID/CustomerID
10 /AdditionalData
11 Timestamp2009-02-25T16:59:48.375+01:00/Timestamp
12 /Request
Il codice XML viene generato semi automaticamente per serializza-
zione di oggetti (vedi 3.3.7 nella pagina 32), quindi in questo frangente,
con un nome ci si potrà riferire indistintamente al tag o alla classe che
lo ha generato.
In 3.2 nella pagina 16 parlando della struttura del sistema di comu-
nicazione, è stato detto che Request e Response reali contengono solo
tipi specializzati di ActionRequest, ActionResponse ecc. . . Nel
listato di esempio è immediato però notare che i nomi dei tag di alcune
entità derivabili sono dati da quelli delle loro classi base; questo fa parte
del meccanismo di serializzazione: il nome della classe specializzata è
contenuto in questi casi dall’attributo xsi:type. Non si fa affidamen-
to a xsi:type per la corretta serializzazione del campo Performer
che contiene semplicemente il nome della classe preposta a gestire la
ActionRequest che lo contiene.
In 3.2 nella pagina seguente si può osservare un esempio di risposta,
contenuto nel file .OUT corrispondente ad un file .IN di richiesta.
37. Dettagli implementativi e tecnologie 31
da identificatori univoci per l’entità cui appartengono all’interno del
loro contenitore; in figura 3.2 nella pagina 17 le frecce indicano che
l’oggetto da cui partono conserva un identificativo dell’oggetto punta-
to, cui si riferiscono logicamente, come una ActionResponse indica
l’ActionRequest da cui è originata.
Il meccanismo di distribuzione degli identificativi è tale che un
identificativo sia univoco tra quelli degli oggetti contenuti nello stes-
so contenitore (ad esempio: non ci sono ripetizioni tra gli id del-
le ActionResponse in un medesimo Document, ma due id di
ActionResponse in due Document distinti possono essere uguali
poiché non è comunque possibile equivocare tra loro).
Dal punto di vista dell’implementazione, ogni oggetto che può funge-
re da contenitore per altri oggetti mantiene internamente un oggetto
di tipo IdFactory per la generazione consistente e la distribuzio-
ne degli identificativi; tutti gli oggetti che possono venire identificati
per qualche motivo implementano l’interfaccia IHasId; tutti gli oggetti
che possono fare riferimento ad un altro oggetto implementante IHasId
implementano a loro volta l’interfaccia IIdPointer.
È forse doveroso ribadire che normalmente per individuare precisa-
mente un oggetto manterremmo semplicemente una managed reference
a quest’ultimo; ma questo tipo di riferimento, nella situazione proposta
è di difficile espressione durante la serializzazione XML.
Listing 3.3: Riassunto dei meccanismi di distribuzione consistente degli
identificativi.
1 public interface IHasId
2 {
3 int Id { get; set; }
4 }
5
6 public interface IIdPointer
7 {
8 int PointedId { get; set; }
9 void PointTo(IHasId item);
10 }
11
12 public class IdFactory
13 {
38. 32 3. SyncUtils
14 int _count = 0;
15 ...
16 public virtual IHasId SetID(IHasId item)
17 {
18 item.Id = _count++;
19 return item;
20 }
21 ...
22 }
23
24 public class IdFactoryT : IdFactory where T : IHasId,
new()
25 {
26 ...
27 public override IHasId SetID(IHasId item)
28 {
29 ...
30 return base.SetID(item);
31 }
32 }
3.3.7 Serializzazione XML
Le tecniche di serializzazione XML in generale, e quelle utilizzate secon-
do le usanze del framework dotNet in particolare, sono estremamente
note in letteratura [12], ma è bene soffermarsi su certi loro aspetti per
gli interessanti risvolti scaturiti durante lo sviluppo di alcune parti del
software di interscambio dati.
La serializzabilità di un tipo in ambito dotNet è cosa diversa dalla
sua serializzabilità XML: ai nostri scopi tutti i tipi primitivi sono XM-
L-serializzabili e in aggiunta—grazie all’uso della reflection—anche molti
tipi complessi non espressamente pensati in ottica di serializzazione XML
sono comunque XML-serializzabili.
Nel package System.Xml.Serialization si trovano gli strumen-
ti per effettuare serializzazione e deserializzazione di oggetti secondo due
modalità che potremmo definire “esplicita” ed “implicita”:
39. Dettagli implementativi e tecnologie 33
• nella modalità esplicita, gli oggetti candidati alla serializ-
zazione devono implementare esplicitamente l’interfaccia
IXmlSerializable, che prescrive l’implementazione di tre
metodi per la serializzazione, la deserializzazione e la definizione
di uno schema;
• nella modalità implicita, il framework ispeziona tramite reflection
le classi degli oggetti da serializzare e considerando solo campi e
proprietà pubbliche genera al volo un oggetto serializzatore adatto.
Nella maggior parte dei casi la modalità implicita è più che sufficiente,
se si considera che è possibile istruire in certa misura il serializzatore su
alcuni dettagli come nomi dei tag, tipo dei nodi ecc. . . mentre con la mo-
dalità esplicita—che pur permette di risolvere problemi più complessi—è
necessario scrivere molto codice, introducendo problemi di leggibilità e
manutenibilità del sorgente.
Solitamente si fa uso di una sola tecnica per volta, ma accade anche
che le due vengano combinate, ad esempio quando si serializza un ogget-
to implicitamente serializzabile che però serba in alcuni dei suoi campi
oggetti esplicitamente serializzabili; ciò che accade è esemplificato nel
seguente algoritmo:
• se l’oggetto da serializzare è un tipo primitivo, allora è ben
conosciuto: si richiama una procedura standard per la sua
serializzazione e si termina la procedura;
• se l’oggetto da serializzare implementa IXmlSerializable, al-
lora si chiama il metodo IXmlSerializable.WriteXml() e si
termina la procedura;
• se l’oggetto non appartiene alle precedenti due categorie ma è
comunque XML-serializzabile, allora si itera l’algoritmo su ogni
campo.
Analogamente per la deserializzazione. È ovvio che nel caso di un og-
getto complesso con campi complessi tutti implicitamente serializzabili,
40. 34 3. SyncUtils
l’algoritmo itera finché non è stato analizzato l’intero albero7 ; è altresì
visibile che qualora venga incontrato un oggetto IXmlSerializable,
i suoi metodi WriteXml/ReadXml si occuperanno della sua intera
serializzazione/deserializzazione, fermando la ricorsione dell’algoritmo
summenzionato.
Nello sviluppo del progetto si sono affrontati dei casi in cui ciò rappre-
senta un problema: gli oggetti che gestiscono richieste e risposte utilizza-
no meccanismi di serializzazione complessi, poichè gli oggetti scambiati
durante una comunicazione non sempre sono ben conosciuti da entram-
bi gli interlocutori; quindi questi oggetti implementano esplicitamente i
meccanismi con IXmlSerializable. Nonostante ciò, per semplificare
lo sviluppo futuro di ulteriori oggetti contenuti in richieste e risposte, si
desidera che tali oggetti non debbano necessariamente implementare essi
stessi le loro procedure di serializzazione in maniera esplicita.
È stato quindi adottato un espediente: nel codice di serializzazione
personalizzato di Request e Response, ogni loro campo viene serializ-
zato/deserializzato istanziando di volta in volta un nuovo serializzatore,
che inizia nuovamente per ogni loro campo l’algoritmo descritto in pre-
cedenza; i flussi di codice XML prodotto nelle singole serializzazioni di
questi oggetti vengono poi fusi col flusso principale dell’oggetto padre a
posteriori (analogamente, durante la deserializzazione avviene l’estrazio-
ne di porzioni di XML dal flusso principale che generano oggetti reinseriti
negli appositi campi dell’oggetto padre a posteriori).
Tutti i tipi conosciuti da un’esecuzione della libreria di comunicazio-
ne, vengono mantenuti in un registro statico e pubblico, accessibile da
ogni serializzatore; l’insieme di queste tecniche permette la serializzazio-
ne/deserializzazione di tipi non noti a compile time, e la corretta gestio-
ne della loro ereditarietà, mantenendo comunque semplice lo sviluppo di
funzionalità aggiuntive.
7
Per semplicità e compattezza vengono taciute le problematiche di visita
come ad esempio riferimenti incrociati e similari, pur esistenti ed affrontati
dall’implementazione reale dell’algoritmo.
41. Dettagli implementativi e tecnologie 35
3.3.8 COM
COM è acronimo di Component Object Model, un’architettura che
permette l’interfaccia di componenti software di varie parti senza
che queste siano ricompilate in un progetto, al fine di promuoverne
l’interoperabilità.
Esso non è dipendente da un particolare linguaggio—ogni linguaggio
che sia in grado di chiamare funzioni tramite puntatori può accedere alle
sue funzionalità—e si basa sui concetti di componente ed interfaccia.
Tali componenti ed interfacce sono conservati in delle DLL struttu-
rate secondo un metodo prestabilito, e riferiti durante il loro utilizzo
secondo un peculiare meccanismo di doppia indirezione: si mantiene il
riferimento ad un componente tramite l’indice di una tabella—chiamata
“vtable”—che a sua volta conserva un’indirizzo reale alla struttura dati
desiderata: in questo modo le vtable possono essere condivise da più
istanze di un oggetto riducendo l’utilizzo di memoria.
Un componente COM somiglia in struttura a ciò che è una classe per
la programmazione ad oggetti.
In una gerarchia di classi, in qualsiasi contesto di programmazione
esiste un ancestor, ovvero il modello di un’entità di base con un insieme
minimo di caratteristiche e funzionalità di base che qualsiasi altro oggetto
deve possedere; in ambito COM, si dice che tale oggetto implementa
almeno l’interfaccia IUnknown.
Listing 3.4: Interfaccia IUnknown come appare in C++.
1 class IUnknown
2 {
3 virtual HRESULT QueryInterface(IID iid, void**
ppvObj) = 0;
4 virtual ULONG AddRef() = 0;
5 virtual ULONG Release() = 0;
6 }
Questa interfaccia prescrive l’implementazione di tre metodi:
42. 36 3. SyncUtils
QueryInterface permette di interrogare il componente imple-
mentante circa il supporto o meno di un’altra specifica
interfaccia;
AddRef viene chiamato per aumentare il conteggio interno degli uti-
lizzatori (insieme a Release implementa un primitivo Garbage
Collector);
Release decrementa il conteggio interno degli utilizzatori e libera la
memoria quando questo raggiunge lo 0.
Un componente COM può supportare un numero qualsiasi di interfacce
a partire da un minimo di una (IUnknown); le interfacce possono essere
prese dal programmatore tra alcune predefinite, derivate da esse o create
ex novo.
Per permettere la risoluzione degli identificativi univoci che contrad-
distinguono componenti ed interfacce COM a partire da nomi, tali ele-
menti devono necessariamente essere registrati, cioè iscritti ad elenchi
siti in determinate aree del registro di configurazione di Windows8 .
La tecnologia dotNet, con il suo proprio concetto di riusabilità sta
soppiantando di fatto il Component Object Model, nonostante que-
st’ultimo sia stato forse una delle tecnologie più usate dal 1993 ad
oggi9 .
Il passaggio da una tecnologia all’altra viene reso più facile dalla
prevista possibilità di interazione tra le due: questa opportunità si espli-
cita con il Runtime Callable Wrapper (RCW) necessario per eseguire
una chiamata a un server COM da un client dotNet, e il COM Callable
Wrapper (CCW) per eseguire viceversa una chiamata a un server dotNet
da client COM10 . Come suggerito dai nomi, queste due entità sono del
8
In realtà COM fu portato anche su sistemi operativi diversi da Windows e addi-
rittura su macchine diverse dai PC compatibili; in questi sistemi la risoluzione degli
identificativi avviene in modo analogo ma implementativamente diverso; l’uso più
esteso di COM rimane quello su piattaforme Windows, dal 3.x fino alle più moderne
XP, Vista e Seven.
9
Nata nel 1993, questa tecnologia è stata menzionata con enfasi da Microsoft solo
a partire dal 1997.
10
Chiamiamo “client COM” una porzione di un programma in grado di utilizzare un
servizio esposto da un oggetto COM; chiamiamo altresì “server COM” il componente
che espone tale funzionalità.
43. Dettagli implementativi e tecnologie 37
codice di contorno aggiunto automaticamente ai componenti di una del-
le due metodologie di sviluppo per essere interpretati ed utilizzati anche
dalla controparte tecnologica.
Component RCW Consumer
Unmanaged
Managed
Consumer CCW Class
Figura 3.3: Schema di funzionamento di RCW e CCW; nella prima riga un
componente dotNet richiama funzionalità da un provider COM; nella seconda,
del codice capace di richiamare funzionalità COM chiama codice dotNet tramite
il CCW.
Nonostante ogni CCW sia generato automaticamente dal runtime
dotNet, le classi da esporre come componenti COM devono venire ade-
guatamente preparate; l’ambiente integrato di sviluppo Visual Studio
2008 offre degli automatismi per assolvere a questo compito, ma resta
preoccupazione del programmatore decorare le classi dotNet con attributi
atti ad istruire il runtime nella creazione dei CCW ad esse dedicati.
Fondamentali ComVisible che abilita il processo di wrapping e
ProgId che assegna il nome al componente. Eventuali altri attributi
da applicare possono essere Guid, che specifica un identificativo univoco
altrimenti assegnato automaticamente e DispId che specifica in maniera
esplicita l’ordine in cui i metodi devono comparire in un’interfaccia11 .
11
Per la corretta compilazione del codice, se almeno un metodo di una classe è stato
decorato con DispId, allora lo devono essere tutti all’interno della stessa classe.
44. 38 3. SyncUtils
Listing 3.5: Esempio della decorazione minima di un componente da esporre
tramite COM.
1 [InterfaceTypeAttribute(ComInterfaceType.
InterfaceIsIDispatch)]
2 public interface _JobId
3 {
4 string ToString();
5 bool Equals(object value);
6 void Increment();
7 JobId Clone();
8 }
9
10 [ClassInterface(ClassInterfaceType.None)]
11 [ProgId(SyncUtils.JobID)]
12 [ComVisible(true)]
13 public class JobId : _JobId
14 {
15 ...
16 }
Una particolare menzione meritano la gestione degli eventi e quella
degli errori; mentre i secondi sono propagati automaticamente dal siste-
ma semplicemente assegnando un codice d’errore ad ogni eccezione non
gestita, l’utilizzo dei primi richiede del codice aggiuntivo.
Proprietà di un’interfaccia C# come potrebbe essere
1 event JobCompletedDelegate OnJobCompleted;
vengono viste in realtà dai client COM come una coppia di metodi
per l’aggiunta e la rimozione di gestori d’evento
1 AddJobCompletedDelegate();
2 RemoveJobCompleteDelegate():
ma per permettere ad un COM client di venire notificato da un
componente, è necessario assegnare esplicitamente a quest’ultimo an-
che un’interfaccia in cui si specifica il metodo da chiamare al verificarsi
dell’evento; del tipo
45. Dettagli implementativi e tecnologie 39
1 [InterfaceTypeAttribute(ComInterfaceType.
InterfaceIsIDispatch)]
2 public interface UserEvents
3 {
4 void OnJobCompleted(JobId job, Response response);
5 ...
6 }
Dal punto di vista dell’utilizzo con Visual Basic 6, l’utilizzo di un
oggetto COM richiede un file che ne specifichi le funzioni presenti: tale
file—di estensione .tlb—viene chiamato “type library”, ed è generato
automaticamente all’atto della registrazione di un componente. Impor-
tando la type library, è poi possibile cominciare ad usare qualsiasi dei tipi
ivi definiti, curandosi di dichiarare con la clausola WithEvents quelli
dei quali si voglia usare la capacità di sollevare eventi.
Nel progetto del sistema di archiviazione proposto, le classi ad essere
predisposte per l’utilizzo come componenti COM sono essenzialmente
quelle riguardanti la libreria della comunicazione, e in maggior dettaglio
quelle che permettono a GEC di richiedere un servizio a GEC_Scan:
ClientSideFileSync;
Request;
Response;
ActionRequest;
ActionResponse;
Document;
DocInfo;
Page;
ResponsePage;
Error
46. 40 3. SyncUtils
e classi da queste derivate. Lo sviluppatore che intendesse creare ulteriori
plug in aggiuntivi dovrà curarsi che le sue classi siano accessibili a client
COM per permetterne l’uso da parte di GEC.
3.4 Installazione e preparazione dell’ambiente di
esecuzione
Il software in tutte le sue parti è in fase di test, e non viene quindi ancora
distribuito al di fuori del contesto di sviluppo. Per questo motivo non è
fornito di un programma di installazione e di istruzioni user friendly, ma
solo di note tecniche, la maggior parte delle quali messe insieme durante
la soluzione di reali problematiche di set up, o collezione di alcuni brani
rilevanti dalla documentazione e dai commenti al codice sorgente.
I tre tipi di software prodotti eseguono in due ambienti eventualmente
coincidenti:
• il calcolatore che esegue GEC
• il personal computer dove viene eseguito il software di acquisizione
e i suoi plug in
Per quanto riguarda il lato controllore, devono essere distribuiti assieme a
GEC tutti gli assembly inerenti la libreria di comunicazione. Le seguenti
DLL contenenti codice dotNet racchiuso in oggetti COM vanno copiate
in una cartella apposita su un volume non rimovibile del PC e registrate
nell’ordine:
• CommonUtils.dll
• SyncUtils.dll
• SerializationSetupHelper.dll
• BasicPlugins.dll
• ClientSync.dll
che in buona parte dipendono da (e quindi richiedono anche)
SimpleLogger.dll
Per la registrazione, è possibile utilizzare il comando
47. Installazione e preparazione dell’ambiente di esecuzione 41
1 RegAsm.exe nomeDll
residente nella cartella
%WINDIR%Microsoft.NETFrameworkv2.X
Come si può notare, la cartella è parte integrante del framework dotNet
2.x (dove “x” sta per qualsiasi numero), palesando che l’installazione del
runtime dotNet 2.0 o superiore è un prerequisito.
Da osservare anche il fatto che gli assembly preparati per essere utiliz-
zati come oggetti COM hanno bisogno di un trattamento particolare, uti-
lizzando per la registrazione l’apposito regasm.exe al posto dell’usuale
regsvr32.exe
Molte di queste librerie sono utilizzate anche dal lato del software
di acquisizione: anche se questo dovesse essere installato sulla stessa
macchina di GEC, le librerie non possono essere condivise. Andranno
quindi replicate nella cartella dedicata solo al programma di scansione.
49. Capitolo 4
GEC_Scan
4.1 Requisiti e progetto dell’interfaccia utente
Il software di acquisizione GEC_Scan dev’essere funzionalmente inte-
grato con GEC. L’utente, una volta installato il sistema, non deve avere
coscienza che GEC_Scan è un programma diverso da GEC ma deve
essere portato a considerarlo come una sua estensione: per ottenere que-
sto risultato GEC_Scan deve essere eseguito all’avvio della macchina su
cui è installato e rimanere nascosto finchè non si presenti un determinato
evento (come l’arrivo di una comunicazione da GEC) nel qual caso dovrà
essere mostrata una schermata adatta a gestire l’evento.
In questo modo, la finestra di GEC_Scan si comporterà come se fos-
se un form dell’applicazione principale, lasciando trasparente all’utente
tutta la gestione delle comunicazioni tra un software e l’altro.
GEC_Scan deve utilizzare SyncUtils o essere compatibile con il suo
metodo di comunicazione a file system condiviso: deve quindi avere ac-
cesso in lettura e scrittura alla porzione del file system sul suo elaboratore
che viene acceduta da GEC tramite SyncUtils.
GEC_Scan deve poter accettare da GEC un numero qualsiasi di
richieste di inizio sessione di acquisizione a prescindere dal suo stato di
occupazione: se arrivano ulteriori richieste mentre l’utente sta operando
il programma per soddisfarne una, tali richieste vanno inserite in una
43
50. 44 4. GEC_Scan
coda di tipo First In First Out, e vanno presentate all’utente in ordine
una ogni volta che la precedente sia terminata.
L’utente deve essere posto in grado di valutare la lunghezza della
coda e di annullare una o tutte le richieste senza interrompere il suo
lavoro corrente. A tale scopo deve essere presente un form separato da
quello principale che permette di osservare in tempo reale l’occupazione
della coda.
GEC_Scan deve poter comunicare con il maggior numero possibile di
periferiche di acquisizione come scanner, fotocamere e basi di dati; tale
connettività deve però essere assolutamente trasparente, cioè: il com-
portamento e l’apparenza grafica del programma devono essere sempre
uguali e garantire un’esperienza di utilizzo consistente qualsiasi sia la
sorgente di dati scelta.
Le immagini acquisite singolarmente o in gruppi, devono essere
presentate tramite piccole anteprime che permettano quantomeno di
identificare in linea di massima ogni documento.
Non ci deve essere un limite—se non quello fisico della macchina
di esecuzione—al numero di immagini acquisibili e gestibili: allo sco-
po di facilitare la gestione delle immagini (operazioni di ispezione, se-
lezione, riordino, rotazione) il programma deve essere provvisto di un
visualizzatore integrato, che permetta di ingrandire le piccole anteprime
e presentare le immagini a più alta risoluzione a vari livelli di zoom.
4.1.1 Interfaccia grafica e usabilità
Normalmente il programma di acquisizione documenti viene eseguito al-
l’avvio del sistema dell’utente, ma la maggior parte delle sue funziona-
lità è preclusa finché GEC—a seguito di un’operazione dell’utente—non
inizia una sessione; per l’utente è tuttavia sempre possibile accedere tra-
mite icona nella barra dell’orologio ad un menu di opzioni che permette
di impostare:
• il dispositivo da utilizzare tra una lista di scanner, fotocamere ed
altre sorgenti TWAIN disponibili sul sistema;
51. Requisiti e progetto dell’interfaccia utente 45
Figura 4.1: Finestra di opzioni del programma di acquisizione.
• la risoluzione (impostata alla prima esecuzione sulla risoluzio-
ne disponibile più vicina—possibilmente per eccesso—a 300 dpi,
risoluzione richiesta dalla maggior parte dei software OCR);
• modalità di colore (impostata alla prima esecuzione sulla modalità
più semplice che si avvicini a RGB);
• orientamento pagine (impostato alla prima esecuzione a 0º);
• utilizzo dell’alimentatore automatico fogli (se disponibile, imposta-
to a vero alla prima esecuzione);
• utilizzo della scansione automatica fronte e retro (inizialmente
falso);
• utilizzo dell’eliminazione automatica pagine vuote (inizialmente
falso);
• utilizzo della rotazione automatica pagine (inizialmente falso);
52. 46 4. GEC_Scan
• utilizzo del rilevamento automatico delle dimensioni di una pagina
(se disponibile inizialmente vero);
Ogni controllo di impostazione risulta operabile se pertinente, e non
presente o disegnato in grigio se non disponibile o non applicabile.
Ogni impostazione si riferisce al dispositivo correntemente seleziona-
to: scegliere un’altra periferica causerà l’adattamento dei parametri alle
capacità della nuova sorgente scelta.
Alla chiusura della finestra delle preferenze, queste vengono rese
ufficiali e salvate su disco.
Figura 4.2: Schermata principale del programma di acquisizione.
Quando l’utente effettua in GEC un’operazione che causa l’inizio di
una sessione di acquisizione, la schermata principale del programma di
scansione compare in primo piano.
Tramite il tasto “Acquisisci” si inizia la scansione dalla periferica sele-
zionata di una o più pagine dipendentemente dalle preferenze impostate:
eventuali operazioni lunghe comporteranno la comparsa di un indicato-
re di avanzamento che consente anche di interrompere le operazioni in
corso.
Ad esempio, un’operazione di acquisizione molto lunga potrebbe pre-
sentarsi nel caso in cui si sia scelto di scansionare molti documenti con
53. Requisiti e progetto dell’interfaccia utente 47
un trascinatore automatico, oppure nel caso si sia scelto di utilizzare una
risoluzione molto alta.
Una volta raccolte delle immagini, queste compaiono sotto forma di
icone sullo sfondo grigio della finestra principale: passandoci sopra con
il puntatore esse si ingrandiscono per permettere di comprendere meglio
di che pagina si tratta e per consentire all’operatore di capire qual è il
foglio correntemente puntato. Aumentando le dimensioni della finestra,
aumentano anche quelle delle icone delle pagine.
Facendo doppio click su un’immagine, questa viene mostrata in una
finestra di anteprima, nella quale è possibile effettuare zoom (operando
la rotella del mouse o i tasti + e -) sulle sue varie parti a fini di ispezione.
Tenendo premuto il tasto sinistro del mouse e trascinando, l’imma-
gine puntata viene rimossa dalla sua sede per consentire di posizionarla
in altra locazione: rilasciando il tasto sinistro, essa verrà inserita su-
bito prima dell’immagine correntemente sotto il puntatore (locazione
evidenziata da una barra nera sfumata).
Una barra di posizionamento compare al di sotto delle immagi-
ni quando queste sono troppe per essere contenute in una sola scher-
mata: sia quando si scorrono semplicemente le immagini, sia duran-
te le operazioni di trascinamento, avvicinandosi al bordo sinistro o de-
stro il programma effettua automaticamente una carrellata—tanto più
velocemente quanto più si è vicini al bordo.
Tenendo premuto il tasto sinistro del mouse sull’area recante la di-
citura “inserisci separatore” e trascinando, viene creato un elemento se-
paratore (delle sembianze di una barra nera verticale) che è possibile
rilasciare tra due immagini secondo le modalità già viste: anche una
volta rilasciato un separatore, è sempre possibile riprenderlo e spostarlo
come una immagine qualsiasi.
Verrà considerato “documento” o “gruppo” l’insieme delle pagine con-
tenute fra due separatori (o tra un separatore e l’inizio/fine della lista):
il programma può essere forzato da GEC a richiedere un numero mini-
mo e un numero massimo di gruppi di pagine: è possibile sapere quali
sono i vincoli lasciando il puntatore sull’area di inserzione separatore e
aspettando la comparsa di un fumetto contenente tali informazioni.
Facendo click destro su un’immagine o un separatore, appare un
menu contestuale con diverse opzioni auto esplicative:
54. 48 4. GEC_Scan
• ruota in senso orario;
• ruota in senso antiorario;
• elimina.
La pressione del tasto “cancella immagini” causa la cancellazione di tutte
le immagini acquisite.
Una volta catturate, riordinate e divise le pagine è possibile annullare
tutto il lavoro o proseguire con l’archiviazione dei dati; la differenza tra
“cancella immagini” e “scarta” consiste proprio nel fatto che il primo co-
mando lascia la finestra aperta per effettuare ulteriori operazioni, mentre
il secondo chiude e manda contestualmente a GEC un messaggio di er-
rore comunicandogli che non è stato possibile completare correttamente
il lavoro per annullamento da parte dell’utente.
Se nel frattempo erano pervenute altre richieste di inizio sessione
(es: l’utente ha effettuato altre operazioni su GEC che hanno originato
altre richieste), il programma lo palesa restando in attesa di istruzioni,
altrimenti torna nel suo stato quiescente. In ogni momento è possibile
controllare e gestire lo stato della coda di richieste tramite l’apposita
finestra, richiamabile dalla tray icon.
Figura 4.3: Finestra di gestione della coda in caso di richieste multiple.
55. Composizione di GEC_Scan 49
Infine, chiudendo semplicemente la finestra principale (con la classi-
ca “x” in alto a destra) o tramite il tasto “Nascondi” senza scegliere di
memorizzare o scartare il materiale raccolto, si sospende la sessione di
lavoro nascondendo la finestra, recuperabile (senza perdere alcun dato)
tramite icona nella barra dell’orologio.
4.2 Composizione di GEC_Scan
Plug in
Servizi
Plug in manager
esterni
Plug in
codice principale
SyncUtils File System GEC
dotNetTwain TWAIN Periferiche
VisualSlideShow
WinForms
e interfaccia Utente
GDI
grafica
GEC_Scan
Figura 4.4: Composizione di GEC_Scan e sue relazioni con tecnologie ed
altre parti del progetto.
In figura 4.4, si può osservare l’architettura di GEC_Scan e le sue