Anda di halaman 1dari 68

ED I T O R I A L E online.infomedia.

it
n. 63 - maggio/giugno 2005
bimestrale - anno undicesimo

Direttore Responsabile
Marialetizia Mari (mmari@infomedia.it)
Direttore Esecutivo
La supremazia Francesco Balena (fbalena@infomedia.it)
Managing Editor

dei blog
Renzo Boni (rboni@infomedia.it)
Collaboratori
Marco Bellinaso
Andrea Benedetti
Gionata Aladino Canova

A lla fine non ce l’ho fatta. Alla fine, anche io ho inaugurato


il mio blog. Per essere più precisi, insieme ai collaboratori
fissi di www.dotnet2themax.it abbiamo deciso di aprire un
“team blog”, dove ognuno di noi può postare tip, piccoli pezzi di
codice, raccontare le proprie vicissitudini quotidiane o anche solo
Marco Caridi, Fabio Perrone
Paolo Pialorsi
Francesco Quaratino
Ingo Rammer, David Stanley
Lorenzo Vandoni

commentare quello che accade nel mondo della programmazione.


Devo dire che mi sono subito appassionato a questo strumento,
e di solito riesco a postare almeno 3-4 volte a settimana, con la
consolazione che quando non sono io a farlo c’è qualcun altro del
team che ha qualcosa di interessante da dire.
Non siamo stati certo i primi autori ad aprire un blog, nè in Italia nè tantomeno nel resto
del mondo. Oramai sembra che tutte le informazioni tecniche più interessanti siano di-
Direzione
sponibili su qualche blog, in particolare su quelli di qualche team di sviluppo in Microsoft Natale Fino (nfino@infomedia.it)
Corp. Spesso la qualità dei post sul blog supera quella degli articoli presenti su riviste
(cartacee o online) ed è l’unico modo per mantenersi aggiornati (esclusa naturalmente la
Marketing & Advertising
Segreteria: 0587/736460
lettura di Visual Basic & .NET Journal… :-). Se volete sapere cosa accade nel mondo che marketing@infomedia.it
ruota intorno a .NET, una visita a http://scoble.weblogs.com/ spesso è più fruttuosa della
Amministrazione
lettura di qualche seriosa analisi. Sara Mattei
Tutto bene, quindi? Non proprio. Perchè – anche a costo di andare controcorrente e di (amministrazione@infomedia.it)
smentire quanto ho appena detto – non sono affatto sicuro che i blog siano lo strumento Grafica
migliore per condividere la conoscenza nel settore IT in generale e della programmazione Manola Greco (mgreco@infomedia.it)
in particolare. Il fatto è che tutta questa enorme massa di informazioni è buttata lì sul
Technical Book
Web a disposizione di tutti, ma se non fosse per Google non riusciremmo mai a trovarla.
Lisa Vanni (book@infomedia.it)
E a volte Google non basta neanche, e mi è capitato spesso di trovare solo per puro caso
alcune “chicche” che avrebbero meritato di apparire al primo posto nei risultati dei motori Segreteria
Enrica Nassi
di ricerca. (info@infomedia.it)
Queste informazioni dovrebbero essere non solo indicizzate, ma anche organizzate in
qualche modo, per poterle recuperare velocemente. Un tentativo in questa direzione ar-
riva da Microsoft con l’iniziativa CodeZone (www.codezone.com), che quando arriverà a Stampa
maturità dovrebbe (il condizionale è d’obbligo) fungere da aggregatore di articoli tecnici e TIPOLITOGRAFIA PETRUZZI
Citta’ di Castello (PG)
altre risorse disponibili sul Web. Ma il limite di CodeZone, a mio parere, è che l’iniziativa
è lasciata ai singoli autori (che devono ricordarsi di inviare a CodeZone un link ai propri
Ufficio Abbonamenti
articoli). Tel. 0587/736460 - Fax 0587/732232
Non so se esiste una soluzione. Forse Microsoft dovrebbe investire seriamente in una specie e-mail: abbonamenti@infomedia.it
di index (stile Yahoo o Virgilio, per intenderci) combinato con un motore tipo MSN Search www.infomedia.it
per permettere di rintracciare velocemente quello che ci serve. Fino ad allora, continuerò Gruppo Editoriale Infomedia srl
a scrivere più spesso che posso sul mio piccolo blog e a consultare periodicamente i blog Via Valdera P., 116 - 56038 Ponsacco (PI) Italia
e i siti che più mi interessano. Tel. 0587/736460 - Fax 0587/732232
red_vbj@infomedia.it
Sito Web www.infomedia.it

Francesco Balena
fbalena@codearchitects.com
Manoscritti e foto originali anche se non pubblicati,
non si restituiscono. È vietata la riproduzione
anche parziale di testi e immagini.

Si prega di inviare i comunicati stampa e gli inviti stampa per


la redazione all’indirizzo: comunicatistampa@infomedia.it
Visual Basic Journal è una rivista di
Gruppo Editoriale Infomedia S.r.l. Via Valdera P, 116 Ponsacco - Pisa.
Registrazione presso il Tribunale di Pisa n. 20/1999
4 VBJ N. 63 - Maggio/Giugno 2005
SOMMARIO
M A G G I O / G I U G N O

N.63
SPECIALE

ASP.NET: alla base della sua sicurezza 8


Valutiamo alcuni aspetti portanti della infrastruttura di sicurezza di ASP.NET.
di Paolo Pialorsi

La validazione dell'input con ASP.NET 15


ASP.NET offre dei completi controlli lato server che gestiscono la validazione dell’input, rendendo non
più necessaria la scrittura di codice personalizzato lato client e server. In questo articolo vedremo i vari
controlli di questo tipo, e la loro applicazione pratica
di Marco Bellinaso

SOFTWARE ENGINEERING
I design pattern più famosi implementati in VB .NET (seconda puntata) 28
Il pattern Observer consente di notificare ad un insieme di ‘osservatori’ le modifiche apportate ad un oggetto
di Lorenzo Vandoni

Implementazione della logica applicativa in programmi VB.NET


(seconda puntata) 31
Mostriamo l’implementazione di alcune classi che consentono di incapsulare la logica applicativa
di Lorenzo Vandoni

DATABASE
Yukon in scena: si alza il sipario
Yukon, nome in codice della nuova release del motore di database di casa Microsoft, ovvero SQL Server 2005, sta prendendo
35
definitivamente forma.
di Andrea Benedetti

Log delle transazioni mediante trigger 41


In particolari contesti, è utile che l’applicazione software garantisca una risposta a domande del tipo: “Chi ha modificato il tale
attributo della tale tabella, e quando ciò è avvenuto?”. Un log delle transazioni garantisce una risposta adeguata a tali esigenze.
di Francesco Quaratino

MDAC 2.8 e Windows 98: problemi di compatibilità


In particolari casi, utilizzando MDAC 2.8 sotto Windows 98, si ottengono blocchi del sistema apparentemente inspiegabili.
46
La soluzione è l’MDAC 2.7!
di Gionata Aladino Canova

6 VBJ N. 63 - Maggio/Giugno 2005


RUBRICHE

Editoriale 4
Recensione libri 65

PRODOTTI
VBdocman - Documentazione automatizzata del codice 50
La documentazione del codice semplificata
di Fabio Perrone
C-Sharpener
Un originale add-in per Visual Studio che consente di convertire il codice VB.NET in C#
53
di Lorenzo Vandoni
Sharp Shooter 1.9
Non solo report: presentiamo uno dei migliori prodotti di reportistica e non solo, interamente pensato per essere integrato con .NET. 56
di Marco Caridi

ARCHITECT'S CORNER
Ottimizzare i lock sui database 58
Quattro cose da ricordare con SQL Server
di Ingo Rammer

ENTERPRISE
Dieci tecniche per controllare lo spam 62
CipherTrust rivela la propria top ten dei suggerimenti per controllare e combattere il frustrante afflusso
di spam nelle caselle aziendali.
di David Stanley

Codice allegato
All’indirizzo ftp.infomedia.it/pub/VBJ sono liberamente scaricabili tutti i listati relativi agli articoli pubblicati.
La presenza di questa immagine indica l’ulteriore disponibilità, allo stesso indirizzo, di un progetto software
relativo all’articolo in cui l’immagine è inserita. Il nome identifica la cartella sul sito ftp.

N. 63 - Maggio/Giugno 2005 VBJ 7


ASP.NET

ASP.NET: alla base


della sua sicurezza
Valutiamo alcuni aspetti portanti della infrastruttura di sicurezza di ASP.NET.

di Paolo Pialorsi

I
l motore di ASP.NET e il .NET Framework, sul qua- Il singolo utente viene associato
le esso si basa, forniscono diversi strumenti per dal sistema a un’identità e in .NET
garantire un’infrastruttura sicura di esecuzione del corrisponde a una classe che im-
codice. Molto spesso quando si pensa alla sicurezza plementa l’interfaccia IIdentity.
in ASP.NET vengono in mente la Forms Authentica- Una identità, unita ai gruppi/ruoli
tion, la Windows Authentication e Passport. Se poi ai quali appartiene, viene detta
si pensa ad ASP.NET 2.0 ricorrono anche concetti Principal e in .NET è rappresen-
come “Profiling”, “Personalization and Membership” tata da una classe che implemen-
e “Role Management”. In questo articolo parleremo ta l’interfaccia IPrincipal.
degli aspetti relativi alla sicurezza di ASP.NET che
sono alla base di tutti questi servizi. C#

Security Principal e Identity public interface IIdentity


Prima di addentrarci nei veri e propri contenuti del- {
l’articolo è opportuno chiarire alcuni concetti fonda- bool IsAuthenticated { get; }
mentali e imprescindibili. Ogni processo eseguito dal string AuthenticationType { get; }
sistema operativo Windows (penso a NT/2000/XP/ string Name { get; }
2003) è associato ad un Security Context che è rap- }
presentato da un token. Il token identifica credenziali
a livello di sistema. public interface IPrincipal
Queste credenziali vengono generalmente dette Se- {
curity Principal e possono rappresentare: un utente, bool IsInRole(string role);
una macchina o un servizio. IIdentity Identity { get; }
Inoltre, pensando per semplicità al solo concetto di }
utente, sappiamo che ogni utente appartiene a qual-
che gruppo. Nel .NET Framework il concetto di Se- Nel .NET Framework 1.1 ab-
curity Context è rappresentato in forma astratta da biamo già a disposizione alcu-
due interfacce: IIdentity e IPrincipal. ne implementazioni di queste in-
terfacce:

• WindowsIdentity e Windows-
Principal: rappresentano l’iden-
Paolo Pialorsi è un consulente e autore specializzato nello
tità di un utente Windows, di
sviluppo di Web Service e soluzioni Web con il Framework
.NET di Microsoft. Lavora nell’omonima società Pialorsi Sistemi
macchina o di dominio, e l’as-
S.r.l. e fa parte del gruppo DevLeap. Può essere contattato via sociazione tra l’identità Win-
email: paolo@devleap.it. Paolo mantiene un blog all’indirizzo: dows e i gruppi di Windows ai
http://blogs.devleap.com/paolo/ . quali essa appartiene.

8 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

te al token del processo che


lo ospita. Nel caso di proces-
si multi-thread di norma tutti i
thread sono eseguiti utilizzan-
do il Security Context del pro-
cesso ospite.
Nessuno ci vieta però di creare
dei thread che impersonifichino
delle identità differenti.
Questo spesso si verifica pro-
prio nelle applicazioni che im-
plementano dei servizi server.
In questo modo infatti noi pos-
siamo avere un processo server
che gira con determinate cre-
denziali e che poi impersonifi-
ca di volta in volta i vari client
che vi si connettono, utilizzan-
do dei thread dedicati alle sin-
Figura 1 Il processo di ASP.NET in Windows XP/2000 gole richieste.
Anche il motore di ASP.NET la-
vora in questo modo, ecco per-
chè ne abbiamo parlato.
• GenericIdentity e GenericPrincipal: rappresen-
tano una identità personalizzata, slegata dal Identità del processo ASP.NET
sistema e dall’eventuale dominio Windows, e Il motore di ASP.NET è di norma ospitato da
l’associazione tra tale identità ed eventuali ruo- Internet Information Services di Windows. A se-
li applicativi personalizzati, definiti come array conda della versione di Windows possono però
di stringhe. cambiare alcune configurazioni relative all’iden-
• FormsIdentity: costituisce l’identità di un tità del processo.
utente autenticato in ASP.NET utilizzando
la Forms Authentication. Questa identità
può essere associata a ruoli personalizzati
per dare origine a un GenericPrincipal. Ogni processo eseguito
• PassportIdentity: costituisce l’identità di un
dal sistema operativo
utente autenticato in ASP.NET utilizzando
Microsoft Passport. Windows è associato ad
Anche questa identità può essere associata
a ruoli personalizzati per sfociare in un Ge- un Security Context che è
nericPrincipal. rappresentato da un token
Durante l’esecuzione di un processo .NET
possiamo chiedere al Framework, invocando il
metodo WindowsIdentity.GetCurrent, di comu-
nicarci qual è il Security Context di esecuzione Partiamo da Windows 2000 Server e Windows
del thread corrente, ottenendo come risposta XP, cioè occupiamoci di IIS 5.0/5.1. Nel caso di
un oggetto di tipo WindowsIdentity. IIS 5.x il processo di ASP.NET è un unico pro-
Parlo di thread corrente in quanto ogni pro- cesso, che si chiama ASPNET_WP.EXE (Figu-
cesso, come ho già detto, viene lanciato con un ra 1) e che gira, per impostazione predefinita,
suo Security Context, ma all’interno del proces- utilizzando un Security Context associato al-
so sono i thread ad eseguire il codice. l’identità [Nome Macchina]\ASPNET.
Nella più semplice delle situazioni avremo Questa impostazione è dichiarata nel file di con-
un processo mono-thread, nel quale il singo- figurazione di .NET Framework (machine.config),
lo thread girerà usando le credenziali associa- nel tag processModel:

N. 63 - Maggio/Giugno 2005 VBJ 9


ASP.NET

di ASP.NET e IIS. La configurazione predefinita


di IIS prevede accesso anonimo e autenticazio-
ne integrata attivi. ASP.NET nel machine.config
(configurazione di .NET a livello di macchina) e
nel web.config (configurazione di ASP.NET a li-
vello di applicazione o directory virtuale) di nor-
ma prevede l’autenticazione Windows, senza al-
cun tipo di impersonificazione del client.
A questo punto se un browser richiede una pa-
gina al motore di ASP.NET, la richiesta passerà
prima di tutto attraverso IIS, il quale colleghe-
rà la richiesta all’account generico IUSR_[Nome
Macchina]. Tale account sarà fornito al moto-
re di ASP.NET come identità (WindowsIdentity)
della richiesta, marcata come non autenticata
(proprietà IsAuthenticated della WindowsIden-
tity pari a false). Il motore di ASP.NET eseguirà
la richiesta impersonificando l’utente associa-
Figura 2 Pannello di configurazione dell’autentica- to al Security Context del processo ASP.NET e
zione di IIS non l’identità del client, in quanto l’impersonifi-
cazione del client è disattivata nelle impostazioni
predefinite.
Ciò significa che sarà l’utente [Nome Macchina]\
MACHINE.CONFIG ASPNET o “NT AUTHORITY\NETWORK_SERVI-
CE” ad essere utilizzato per accedere qualunque
<processModel ... userName=”machine” tipo di risorsa di sistema. Eseguendo il seguen-
password=”AutoGenerate” ... te codice all’interno di una pagina:

Con queste impostazioni predefinite la pas- C#


sword dell’utente ASPNET viene autogenera-
ta, criptata e salvata nel registro di sistema al- private void Page_Load(object sender, System.EventArgs e)
l’interno della chiave HKLM\SECURITY\Policy\ {
Secrets\aspnet_WP_PASSWORD, cioè nel co- WindowsIdentity currentIdentity = WindowsIdentity.GetCur
siddetto LSA (Local Security Authority) Secret rent();
Store di Windows. In Windows Server 2003, WindowsIdentity userIdentity = (WindowsIdentity)User.Ide
grazie alle novità introdotte nel motore di IIS ntity;
6.0, possiamo avere più processi, di nome
W3WP.EXE, che girano in parallelo e che rap- System.Text.StringBuilder sb = new System.Text.StringBui
presentano differenti Application Pool. lder();
Ciascun Application Pool può essere configu- sb.Append(“<br><b>Current Process Identity</b>”);
rato per utilizzare una identità specifica; inoltre sb.Append(“<br>Username: “);
ogni Application Pool può sfruttare più proces- sb.Append(currentIdentity.Name);
si paralleli, consentendoci di avere un sempli- sb.Append(“<br>IsAuthenticated: “);
ce e rapido meccanismo di bilanciamento di sb.Append(currentIdentity.IsAuthenticated);
carico (load balancing) tra processi su di una sb.Append(“<br>IsAnonymous: “);
stessa macchina server. Di norma il processo sb.Append(currentIdentity.IsAnonymous);
W3WP.EXE gira con l’identità “NT AUTHORITY\ sb.Append(“<br>&nbsp;<br><b>Current User Identity</b>”);
NETWORK_SERVICE”. sb.Append(“<br>Username: “);
sb.Append(userIdentity.Name);
Identità del client sb.Append(“<br>IsAuthenticated: “);
A questo punto si presentano N possibili con- sb.Append(userIdentity.IsAuthenticated);
figurazioni relative all’identità del client che ri- sb.Append(“<br>IsAnonymous: “);
volge richieste al motore di ASP.NET. Esami- sb.Append(userIdentity.IsAnonymous);
niamo ad esempio la configurazione predefinita

10 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

securityInfos.Text = sb.ToString(); Impersonificare un’identità


} Attiviamo ora l’impersonificazione dell’uten-
te in ASP.NET.
Se pensiamo che la variabile securityInfos Possiamo farlo agendo sul file web.config del-
sia una Label, nel browser avremo il seguen- la nostra applicazione di prova, aggiungendo
te testo: o modificando il tag identity:

Current Process Identity WEB.CONFIG


Username: [Nome Macchina]\ASPNET
IsAuthenticated: True <identity impersonate=”true” />
IsAnonymous: False
Current User Identity Rieseguendo adesso la pagina, avremo anco-
Username: ra un diverso risultato:
IsAuthenticated: False
IsAnonymous: True Current Process Identity
Username: [Nome Macchina]\PaoloPi
Il codice è stato eseguito su un sistema Win- IsAuthenticated: True
dows XP. Come si vede l’utente associato al IsAnonymous: False
processo di ASP.NET è [Nome Macchina]\
ASPNET, mentre l’utente associato alla richie- Current User Identity
sta non ha nome, infatti IUSR_[Nome Macchina] Username: [Nome Macchina]\PaoloPi
non ha nome, e risulta non autenticato, quindi IsAuthenticated: True
anonimo. In questo caso le risorse di sistema IsAnonymous: False
accedute da ASP.NET, per esempio file, data-
base e gli stessi file ASPX, saranno verificate A questo punto il thread che esegue questa
rispetto ai diritti dell’utente ASPNET. singola richiesta, pur girando all’interno del pro-
Proviamo ora ad attivare l’autenticazione Win- cesso di ASP.NET, utilizzerà un Security Context
dows in IIS, cioè togliamo la spunta dal flag di specifico e relativo all’identità dell’utente Paolo-
accesso anonimo alla nostra applicazione (Fi- Pi, cioè quella dell’utente che sta eseguendo la
gura 2). Il risultato nel browser sarà: richiesta dal browser.
Nel caso in cui l’utente non abbia accesso ad
Current Process Identity eventuali risorse accedute (ricordo ancora una
Username: [Nome Macchina]\ASPNET volta che in queste sono comprese anche le pa-
IsAuthenticated: True gine ASPX stesse) avremo un errore di tipo “Ac-
IsAnonymous: False cess Denied” (Figura 3).

Current User Identity


Username: [Nome Macchina]\PaoloPi
IsAuthenticated: True L’impersonificazione in
IsAnonymous: False
Windows 2000 è consentita
Ecco che l’utente con il quale sto eseguen- solo se l’account del proces-
do la richiesta dal browser, sfruttando l’auten-
ticazione integrata di Windows, viene passato so ASP.NET ha il privilegio
al motore di ASP.NET, il quale esegue anco-
ra la richiesta nel Security Context dell’uten-
“Act as Operating System”
te associato al processo di ASP.NET, ma sarà
ora in grado di sapere che l’utente connesso
è PaoloPi.
Eventuali accessi a risorse, database e file, L’impersonifi cazione in Windows 2000 è
compresi gli ASPX, saranno comunque sempre consentita solo se l’account del processo
eseguiti dall’utente del processo di ASP.NET, ASP.NET ha il privilegio “Act as Operating
che in questo caso per noi è [Nome Macchina]\ System”, impostabile dalle Local Security
ASPNET. Policy della macchina (secpol.msc).

N. 63 - Maggio/Giugno 2005 VBJ 11


ASP.NET

In Windows Server 2003 e in Windows XP lito con privilegi maggiori e proprio per questo
questa esigenza è stata superata. Possiamo da usare solo temporaneamente.
anche decidere di impersonificare sempre e Una possibilità che abbiamo, ma della quale
comunque un particolare utente applicativo, non vedremo tutto il codice in questo articolo,
indicando nel web.config una specifica iden- è quella di impersonificare un utente specifico,
tità da impersonificare: utilizzando API di Windows per creare un token
relativo all’utente da impersonificare, creando
WEB.CONFIG poi un’istanza della classe WindowsImperso-
nationContext, tramite il metodo Impersonate
<identity impersonate=”true” userName=”[Nome Macchina]\Utente_ della classe WindowsIdentity.
Applicativo” password=”pwd_utente” />
C#
Con questa nuova configurazione avremo:
// Creo un token utilizzando l’API
Current Process Identity // LogonUser di advapi32.dll
Username: [Nome Macchina]\Utente_Appli- // ...
cativo
IsAuthenticated: True // Impersonifico il token
IsAnonymous: False WindowsImpersonationContext impersonationContext = Windows
Identity.Impersonate(tokenPtr);
Current User Identity // Qui eseguo codice che gira con
Username: [Nome Macchina]\PaoloPi // l’identità dell’impersonationContext
IsAuthenticated: True // ...
IsAnonymous: False
// Esco dal contesto di impersonificazione
Dovrebbe essere abbastanza chiaro il fatto che // e torno al Security Context standard
a questo punto il processo di ASP.NET girerà impersonationContext.Undo();
con il Security Context di ASPNET, la richie-
sta sarà identifi-
cata come pro-
veniente dal-
l’utente PaoloPi
e il thread che
esegue la richie-
sta sarà asso-
ciato all’identità
custom ([Nome
Macchina]\
Utente_Applica-
tivo) che abbia-
mo deciso di im-
personificare nel
web.config.
A volte è ne-
cessario ese-
guire la mag-
gior parte delle
richieste con il
Security Context
standard, tranne
quelle che vo-
gliamo eseguire Figura 3 Errore “Access Denied” in caso di utente non autorizzato
con un contesto
differente, di so-

12 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

Per ulteriori dettagli su tutte le possibili configu- • High: livello di permessi molto alto, consente
razioni di ASP.NET e IIS rimando alla lettura del comunque di fare quasi tutto sulla macchina.
capitolo 2 del libro “ASP.NET Full Contact” [2]. Rispetto al livello Full Trust per esempio non
consente l’esecuzione di codice unmanaged
Livelli di Trust (per es. chiamate a componenti COM).
Un altro aspetto fondamentale e portante del- • Medium: maggiormente restrittivo rispetto al
l’infrastruttura di sicurezza di ASP.NET, a par- precedente. Ad esempio non consente l’ac-
tire dalla versione 1.1, sono i livelli di trust per cesso al file system, tranne che per i folder
l’esecuzione del codice. dell’applicazione corrente, nei quali è consen-
Il .NET Framework basa la sua sicurezza sulla tito l’accesso in lettura, scrittura e aggiunta.
Code Access Security. Code Access Security Consente l’uso dell’IsolatedStorage [5].
prevede un meccanismo di identificazione de- • Low: restrizione del livello Medium che con-
gli assembly che devono essere caricati in me- sente l’accesso in sola lettura ai folder del-
moria ed eseguiti, al fine di stabilire se questi l’applicazione, non consente l’accesso a da-
hanno o meno il permesso di svolgere determi- tabase esterni. Consente l’uso dell’Isolated-
nate attività sul PC nel quale vengono esegui- Storage [5] con una quota di 1 Mbyte.
ti, a prescindere da quelli che sono i permes- • Minimal: consente solo l’esecuzione di codi-
si dell’utente correntemente autenticato sulla ce ASP.NET, ma impedisce l’accesso a da-
macchina. Per esempio io posso utilizzare il tabase, file system, isolated storage, socket,
mio PC con un utente che ha diritto di acces- web service, ecc.
so al disco C:\ della mia macchina, ma posso
impedire a tutti gli assembly che provengono Ciascuno di essi corrisponde a dei fi le
dalla rete Internet o Intranet di accedere al di- .confi g presenti nella cartella %windir%\
sco C:\, anche se sono io ad eseguirli. Microsoft.NET\Framework\v1.1.4322\
Questo consente di raggiungere dei livelli di CONFIG.
sicurezza maggiori rispetto alla classica ese- Nel file machine.config, piuttosto che nel
cuzione di un programma nello stesso conte- web.config di una particolare applicazione
sto di sicurezza di chi lo esegue, come acca- web, possiamo configurare un livello di trust
de per esempio con un programma Visual Ba- nel modo seguente:
sic 6, con uno script VBS/JS o anche con un
programma C++ unmanaged. Generalmente i C#
criteri di identificazione degli assembly .NET si
basano sulla loro provenienza fisica (local ma- <system.web>
chine, Intranet, Internet, URL specifiche), sul <trust level=”Minimal” originUrl=”” />
produttore (eventualmente tramite Authentico- </system.web>
de), sullo strong name [4], ecc.
Una volta identificata la provenienza e le ca- Il parametro originUrl indica una eventuale
ratteristiche di un assembly (si parla di “evi- URL da considerare fruibile nel caso di per-
dence”, cioè “prove”) si costruisce un elenco messi di accesso a risorse via rete, come per-
di permessi associati all’assembly da caricare messi relativi ai Socket e alle WebRequest.
in memoria ed eseguire, applicando un mec- Una buona regola da seguire, in particolare
canismo di policy a più livelli, il cui risultato quando si svolge attività di hosting di appli-
sono i permessi complessivi per quell’assem- cazioni ASP.NET di terzi, sarebbe abbassa-
bly [5]. Un livello di trust non è altro che un re al minimo indispensabile il livello di trust
insieme di permessi ai quali deve sottostare delle applicazioni.
un’applicazione ASP.NET durante la sua ese- Questo per evitare che eventuali “code injec-
cuzione. Riferendosi a questi concetti si par- tion” possano svolgere attività da noi non con-
la spesso di “sandboxing”. La configurazione template, ma potenzialmente molto rischiose
predefinita di ASP.NET 1.1 prevede i seguen- per il nostro server e/o per la sicurezza delle
ti livelli di trust: altre applicazioni ospitate.
Pensate che cosa potrebbe accadere, se do-
• Full: è il livello predefinito (purtroppo!) e pre- vessimo pubblicare su di un server che svolge
vede qualsiasi tipo di permesso in quanto, attività di web hosting di massa, una pagina
di fatto, spegne la verifica dei permessi. ASPX che si mette a sfogliare il contenuto del

N. 63 - Maggio/Giugno 2005 VBJ 13


ASP.NET

file system del server, magari consentendoci Windows SharePoint Services 2003 per
di cancellare dei file o mostrando il contenu- esempio sfrutta livelli di trust personalizzati,
to dei web.config di tutte le altre applicazio- costruiti proprio in questo modo, utilizzan-
ni web in hosting su quel server. Potenzial- do anche permessi personalizzati.
mente, in assenza di controlli tramite le ACL Quando abbiamo l’esigenza di esegui-
(Access Control List) di Windows, potremmo re minime porzioni di codice con un livel-
creare dei seri problemi a quel server e alle lo di trust maggiore, rispetto a quello stan-
sue applicazioni. dard e restrittivo da noi previsto, possiamo
D’altra parte impostare le ACL su ogni fol- personalizzare il livello di trust, definendo
der applicativo sarebbe molto oneroso e ri- per esempio un gruppo di permessi custom
chiederebbe l’intervento di un amministratore per gli assembly firmati con la nostra chia-
della macchina. Impostando un livello di trust ve privata, oppure possiamo anche inserire
che non consente l’accesso fisico al file sy- nella GAC gli assembly, rendendoli in que-
stem, se non eventualmente alle sole cartel- sto modo dotati di Full Trust e dichiarando
le e file di nostro interesse (per es. minore o che consentiamo a livelli di trust inferiori di
uguale a Medium), potremmo impedire simili invocarli, utilizzando l’attributo AllowPartial-
attività, senza nemmeno richiedere un inter- lyTrustedCallers.
vento di tipo sistemistico sul server, per con-
figurare le ACL. Conclusioni
Ci limiteremmo a ridurre o “spegnere” l’ac- Abbiamo potuto capire che il motore di
cesso al file system.Se poi i cinque livel- ASP.NET è molto maturo dal punto di vista
li di trust predefiniti non fanno al caso no- della sicurezza.
stro, possiamo definire dei nostri file di con- È di fondamentale importanza per scrive-
figurazione personalizzati e configurarli nel re applicazioni sicure e controllabili ave-
machine.config nel modo seguente: re presente le dinamiche di impersonifica-
zione e di esecuzione del codice associa-
C# to ai Security Context, così come è altret-
tanto importante considerare i livelli di trust
<system.web> personalizzati e non eseguire tutto il codice
<securityPolicy> come Full Trust.
<trustLevel name=”Full” policyFile=”internal” />
<trustLevel name=”High” policyFile=”web_ Bibliografia e Riferimenti
hightrust.config” /> [1] Autori vari - “ ASP.NET Security”, Wrox
<trustLevel name=”Medium” policyFile=”web_ Press, 2002
mediumtrust.config” /> [2] Luca Regnicoli e Roberto Brunetti -
<trustLevel name=”Low” policyFile=”web_ “ASP.NET Full Contact”, Mondadori Infor-
lowtrust.config” /> matica, 2003
<trustLevel name=”Minimal” policyFile=”web_ [3] Fritz Onion - “Essential ASP.NET”, Addison-
minimaltrust.config” /> Wesley, 2003
<trustLevel name=”Custom” policyFile=”web_ [4] Keith Brown - “ The .NET Developer’s
customtrust.config” /> Guide to Windows Security”, Addison-
</securityPolicy> Wesley, 2004
<trust level=”Custom” originUrl=”” /> [5] Paolo Pialorsi - “ La sicurezza del codice
</system.web> managed”, Visual Basic Journal n. 60, Nov/
Dic 2004
I file di definizione dei livelli di trust non sono [6] http://msdn.microsoft.com/aspnet/
altro che file XML che elencano i permes- [7] http://www.devleap.com/Default.aspx?IdC
si consentiti e i criteri in base ai quali sono ategoria=ASPNET
consentiti. Il file web_customtrust.config può [8] http://msdn.microsoft.com/asp.net/using/
quindi essere creato a partire da uno di quelli understanding/security/default.aspx
già configurati, semplicemente personalizzan- [9] http://www.pluralsight.com/keith/book/
done il contenuto, aggiungendo o togliendo html/book.html
qualche permesso e condizione di assegna- [10] h t t p : / / s u p p o r t . m i c r o s o f t . c o m/
zione degli stessi. default.aspx?scid=kb;en-us;329290

14 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

La validazione
dell'input Validazione

con ASP.NET
ASP.NET offre dei completi controlli lato server che gestiscono la validazione dell’input,
rendendo non più necessaria la scrittura di codice personalizzato lato client e server. In
questo articolo vedremo i vari controlli di questo tipo, e la loro applicazione pratica

di Marco Bellinaso

I
compiti più comuni per le applicazioni web sono Ciò che deriva da questa in-
la consultazione e l’aggiornamento di un data- troduzione è che per fare una
base, ossia la raccolta di informazioni. Vengo- cosa semplice come la raccol-
no così utilizzate form e controlli textbox o di altro ta di dati bisogna scrivere pa-
tipo che l’utente deve compilare e inviare al server recchio codice per il controllo
premendo un pulsante Submit. client e server, riempiendo le
Nella quasi totalità dei casi è necessario un qual- pagine di righe spesso uguali e
che livello di validazione dell’input, per fare in modo andando comunque incontro a
che nel database non vengano inseriti valori errati possibili errori se non si è abi-
che possano causare errori. tuati a lavorare con JavaScript
I controlli necessari devono essere fatti direttamen- (necessario per la compatibilità
te sul lato client, in modo che il form non venga col client).
inviato e poi ripresentato in caso di errore, provo- Qualcuno sicuramente sta-
cando così un round-trip inutile al server. rà obiettando che basta rag-
Devono però essere presenti anche sul lato ser- gruppare le routine necessarie
ver, come ulteriore conferma, perché un utente in file esterni da includere dove
potrebbe in teoria salvare la pagina HTML, modi- serve riutilizzando il codice già
ficare il sorgente e usarla per inviare dati non va- scritto, ma quanti sono in real-
lidi. Infine altro codice deve effettivamente infor- tà riusciti ad ottenere delle rou-
mare l’utente degli errori commessi nella compila- tine veramente flessibili e un ef-
zione della scheda. fettivo riuso che non costringa a
personalizzare ogni volta qual-
cosa?
Marco Bellinaso lavora come trainer, consulente e sviluppatore E comunque un po’ di codice bi-
di tool per programmatori per conto di Code Architects S.r.l. sogna comunque sempre scri-
(www.codearchitects.com), società specializzata in .NET. Fa verlo per chiamare le routine di
parte del Team di VB-2-The-Max (www.vb2themax.com) e si
controllo per i vari campi.
occupa con particolare interesse di soluzioni web distribuite
con il framework .NET, sia con VB che C#. È coautore di
ASP.NET viene fornito di serie
quattro libri su .NET per Wrox Press, tra cui “ASP.NET Website con un gran numero di control-
Programming” (tradotto in italiano da HOEPLI) e “Fast Track li lato server che aiutano il pro-
ASP.NET”. Può essere contattato tramite e-mail all’indirizzo grammatore nei modi più dispa-
mbellinaso@infomedia.it. rati: creano tabelle, griglie avan-

N. 63 - Maggio/Giugno 2005 VBJ 15


ASP.NET

La classe base dei controlli validatori


Sono presenti controlli diversi, ognuno dei
quali svolge un controllo diverso, ed è possi-
bile sommarli per sommare i controlli effettuati
sullo stesso campo.
Tutti questi componenti sono però derivati da
una classe di base, BaseValidator, che espone
le seguenti proprietà comuni:

• ControlToValidate: proprietà che indica il


controllo il cui input deve essere valida-
to;
• Display: proprietà che specifica come vi-
sualizzare il messaggio di errore.
Se “static” lo spazio necessario al testo
di notifica verrà calcolato e aggiunto alla
pagina in anticipo, se “dynamic” lo spazio
verrà ricavato in modo dinamico al mo-
mento di mostrare gli errori. Attenzione
che sebbene la seconda possibilità pos-
sa sembrare attraente, in alcuni casi po-
trebbe cambiare di molto il layout della
pagina, spaesando l’utente;
• EnableClientScript: proprietà booleana
che indica se la validazione lato client
deve essere effettuata o meno;
• Enabled: proprietà booleana che specifi-
ca se il controllo è attivo o meno, ossia
se il campo di input associato verrà vali-
dato o no;
• ErrorMessage: stringa di errore che ver-
rà mostrata nel sommario degli errori da
Figura 1 La pagina di esempio mostra il report un altro controllo, ValidationSummary;
degli errori • ForeColor: è il colore per il testo del mes-
saggio che comparirà accanto o sotto un
campo di input quando la sua validazione
darà esito negativo. Di default è rosso;
• IsValid: proprietà booleana che indica se
zate ed editabili, calendari, mostrano banner il contenuto del campo di input associa-
e molto altro. to è valido o meno;
Poiché la validazione dell’input è un compito • Validate: metodo che compie la ri-vali-
così diffuso, un set di questi controlli si oc- dazione dell’input e aggiorna la proprie-
cupa proprio di questo, liberando il program- tà IsValid di conseguenza.
matore da questo noioso onere.
Tutto ciò che bisogna fare è dichiarare un La classe BaseValidator ha in realtà anche al-
nuovo controllo e senza scrivere una riga di tre proprietà o metodi, come BackColor, Font
codice per la validazione questa verrà effet- e altri, ma sono tutti ereditati dalle classi La-
tuata sia sul client che sul server, controllan- bel e WebControl. BaseValidator è una classe
do che i campi di input rispettino i vari tipi di astratta (dichiarata con abstract dal punto di
regole definite dai diversi tipi di controllo. vista dei programmatori C#, o MustInherit per
Se poi il tipo di controllo che serve non è chi usa VB.NET), ossia una classe che non
fornito di default, è allora possibile esten- può essere usata direttamente ma che può
derli con una qualsiasi logica di validazio- essere solo ereditata da altre classi, queste
ne custom. ultime usufruibili.

16 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

Tabella 1 I possibili valori per la proprietà Operator

Valore Confronto tra il valore dell’input e quello di un altro controllo o valore costante

Equal I due valori devono essere uguali

NotEqual L’input deve essere diverso dal secondo valore


GreaterThan L’input deve essere maggiore del secondo valore
GreaterThanEqual L’input deve essere maggiore o uguale del secondo valore

LessThan L’input deve essere minore del secondo valore

LessThanEqual L’input deve essere minore o uguale del secondo valore

DataTypeCheck Viene controllato solo che l’input sia del tipo specificato dalla proprietà Type

Il senso è che oltre ai membri di base, ogni Il campo “Name” è quello da controllare, il
classe derivata aggiunge delle nuove pro- carattere * verrà mostrato accanto alla casel-
prietà che cambiano le regole di validazio- la di testo in caso di errore alla pressione del
ne utilizzate. pulsante Submit o anche quando il controllo
Cominciamo a vedere controllo per controllo, perde il focus se si sta usando Internet Explo-
presentando per ognuno un esempio. rer 5 o superiore.
Contrariamente a quanto si potrebbe pen-
I controlli per la validazione di base sare ad intuito, la stringa per ErrorMessage
Il controllo più semplice è RequiredFieldVali- non viene mostrata accanto al controllo, ma
dator, il cui unico scopo è verificare che il con- verrà usata da un altro controllo che vedre-
tenuto di una textbox non sia nullo (una serie mo tra breve.
di spazi e basta vengono considerati nulli). Un’altra cosa da notare è che è stato spe-
L’unica proprietà aggiuntiva si chiama Ini- cificato l’ID per il controllo: in realtà dare un
tialValue ed esprime il valore iniziale del- nome al controllo è necessario solo quando
l’input, che se non cambiato verrà conside- si deve accedere ad esso tramite codice per
rato come errore. cambiare o leggere le sue proprietà.
Spesso comunque viene usato nella sua for- Il secondo controllo è il RangeValidator, e ve-
ma più semplice: rifica che l’input sia compreso in un interval-
lo predefinito.
Il bello di questo controllo è che non control-
la solo numeri interi, ma anche valori Double,
Con le regular String, Currency e Date.
Il tipo di dato viene specificato tramite la
expression si possono proprietà Type, mentre MinimumValue e Ma-
ximumValue definiscono l’intervallo. Il seguente
definire regole esempio controlla che la data specificata sia
molto complesse compresa tra il 5 e il 20 agosto 2001:

<asp:TextBox runat=”server” Width= ”200px” ID=”DayOff” />


<asp:RangeValidator runat= ”server” ID=”ValidateDayOff2”
ControlToValidate=”DayOff”
<asp:TextBox runat=”server” Width=”200px” ID=”Name” /> MinimumValue=”08/05/2001”
<asp:RequiredFieldValidator runat=”server” MaximumValue=”08/20/2001”
ID=”ValidateName” Type=”Date”
ControlToValidate=”Name” ErrorMessage=”Il giorno di ferie non &egrave; nell’inter-
ErrorMessage= ”Il Nome deve essere specificato” vallo consentito”
Display=”dynamic”>* Display=”dynamic”>*
</asp:RequiredFieldValidator> </asp:RangeValidator>

N. 63 - Maggio/Giugno 2005 VBJ 17


ASP.NET

Da notare che le date vengono specificate ErrorMessage=”La password di conferma non corrisponde”
nel formato dettato dalla versione del siste- Display=”dynamic”><img src=”imgError.gif” border=”0”>
ma operativo installata, quindi mm/dd/aaaa </asp:CompareValidator>
nel caso di Windows 2000 inglese.
Un controllo simile a quello appena visto è Nell’ultimo esempio c’è un’altra cosa da no-
CompareValidator, che confronta il contenuto tare: prima del tag di chiusura del controllo
di un controllo di input con un altro controllo non c’è il solito asterisco degli esempi pre-
o con un altro valore stabilito a priori. cedenti, ma un tag HTML <IMG> per mostra-
re un’immagine.
Il risultato è rappresentato in Figura 1, ac-
canto alle ultime tre caselle di testo. Un altro
La convalida controllo è RegularExpressionValidator, che
verifica se l’input rispetta la regular expres-
dell’input fa parte sion specificata dalla proprietà ValidationEx-
di quasi tutte pression.
Questo controllo offre molta potenza, per-
le applicazioni web ché le espressioni possono essere anche
molto complicate e si adattano a molti tipi
di verifiche.

È simile a RangeValidator perché ha la stes-


sa proprietà Type che lo rende flessibile.
Nel caso si voglia validare l’input con il con-
tenuto di un altro controllo, questo secondo
controllo dovrà essere specificato dalla pro-
prietà ControlToCompare, mentre si usa Va-
lueToCompare se si vuole fare il confronto
con un valore.
Il componente supporta diversi tipi di con-
fronto, quello da effettuare deve essere spe-
cificato tramite la proprietà Operator, che ac-
cetta i valori specificati in Tabella 1.

Nell’esempio che segue viene controllato che


l’età inserita sia di almeno 18 anni:

<asp:TextBox runat=”server” Width=”200px” ID=”Age” />


<asp:CompareValidator runat=”server” ID=”ValidateAge”
ControlToValidate=”Age”
ValueToCompare=”18”
Type=”Integer”
Operator=”GreaterThanEqual”
ErrorMessage=”Per iscriverti devi essere maggiorenne”
Display=”dynamic”>*
</asp:CompareValidator>

Mentre questo assicura che l’utente abbia


specificato la stessa password in due cam-
pi textbox:

<asp:CompareValidator runat=”server”
ControlToValidate=”Password2” Figura 2 La pagina di esempio mostra la lista de-
ControlToCompare=”Password” gli errori in una message box
Type=”String”

18 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

Listato 1 Il codice completo della pagina di esempio (continua)

<%@ Page Language=”C#” %>

<html>
<head>
<title>ASP.NET Validators</title>

<script language=”JavaScript”>
function EmpIDClientValidate(ctl, args)
{
args.IsValid=(args.Value%5 == 0);
}
</script>
</head>

<body>

<form method=post runat=”server” ID=”FormValidators”>


<asp:table runat=”server”>
<asp:TableRow>
<asp:TableCell Width=”50px” Text=”Descrizione”
Font-Bold=”true” ForeColor=”blue” />
<asp:TableCell Width=”200px” Text=”Valore”
Font-Bold=”true” ForeColor=”blue” />
</asp:TableRow>

<asp:TableRow>
<asp:TableCell Text=”Nome:”/>
<asp:TableCell>
<asp:TextBox runat=”server” Width=”200px” ID=”Name” />
<asp:RequiredFieldValidator runat=”server” ID=”ValidateName”
ControlToValidate=”Name”
ErrorMessage=”Il Nome deve essere specificato”
Display=”dynamic”>*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator runat=”server” ID=”ValidateName2”
ControlToValidate=”Name”
validationExpression=”[a-z A-Z]*”
ErrorMessage=”Il nome non pu&ograve; contenere cifre”
Display=”dynamic”>*
</asp:RegularExpressionValidator>
</asp:TableCell>
</asp:TableRow>

<asp:TableRow>
<asp:TableCell Text=”ID (multiplo di 5):”/>
<asp:TableCell>
<asp:TextBox runat=”server” Width=”200px” ID=”EmpID” />
<asp:RequiredFieldValidator runat=”server” ID=”ValidateEmpID”
ControlToValidate=”EmpID”
ErrorMessage=”L’ID deve essere specificato”
Display=”dynamic”>*
</asp:RequiredFieldValidator>
<asp:CustomValidator runat=”server” ID=”ValidateEmpID2”
ControlToValidate=”EmpID”
ClientValidationFunction=”EmpIDClientValidate”
OnServerValidate=”EmpIDServerValidate”
ErrorMessage=”L’ID deve essere un multiplo di 5”
Display=”dynamic”>*
</asp:CustomValidator>

N. 63 - Maggio/Giugno 2005 VBJ 19


ASP.NET

Listato 1 (segue) Il codice completo della pagina di esempio

</asp:TableCell>
</asp:TableRow>

<asp:TableRow>
<asp:TableCell Text=”Giorno di ferie <br>(dal 5 al 20 luglio):”/>
<asp:TableCell>
<asp:TextBox runat=”server” Width=”200px” ID=”DayOff” />
<asp:RequiredFieldValidator runat=”server” ID=”ValidateDayOff”
ControlToValidate=”DayOff”
ErrorMessage=”Il giorno di ferie deve essere specificato”
Display=”dynamic”>*
</asp:RequiredFieldValidator>
<asp:RangeValidator runat=”server” ID=”ValidateDayOff2”
ControlToValidate=”DayOff”
MinimumValue=”08/05/2001”
MaximumValue=”08/20/2001”
Type=”Date”
ErrorMessage=”Il giorno di ferie non &egrave; nell’intervallo consentito”
Display=”dynamic”>*
</asp:RangeValidator>
</asp:TableCell>
</asp:TableRow>

<asp:TableRow>
<asp:TableCell Text=”Et&agrave;( >= 18 ):”/>
<asp:TableCell>
<asp:TextBox runat=”server” Width=”200px” ID=”Age” />
<asp:RequiredFieldValidator runat=”server”
ControlToValidate=”Age”
ErrorMessage=”L’et&agrave; deve essere specificata”
Display=”dynamic”>*
</asp:RequiredFieldValidator>
<asp:CompareValidator runat=”server” ID=”ValidateAge”
ControlToValidate=”Age”
ValueToCompare=”18”
Type=”Integer”
Operator=”GreaterThanEqual”
ErrorMessage=”Per iscriverti devi essere maggiorenne”
Display=”dynamic”>*
</asp:CompareValidator>
</asp:TableCell>
</asp:TableRow>

<asp:TableRow>
<asp:TableCell Text=”Email:”/>
<asp:TableCell>
<asp:TextBox runat=”server” Width=”200px” ID=”Email” />
<asp:RequiredFieldValidator runat=”server”
ControlToValidate=”Email”
ErrorMessage=”L’Email deve essere specificata”
Display=”dynamic”>*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator runat=”server” ID=”ValidateEmail”
ControlToValidate=”Email”
validationExpression=”.*@.{2,}\..{2,}”
ErrorMessage=”L’Email non &egrave; nella forma corretta”
Display=”dynamic”>*
</asp:RegularExpressionValidator>
</asp:TableCell>
</asp:TableRow>

20 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

Listato 1 (segue) Il codice completo della pagina di esempio

<asp:TableRow>
<asp:TableCell Text=”Nickname:”/>
<asp:TableCell>
<asp:TextBox runat=”server” Width=”200px” ID=”Nick” />
<asp:RequiredFieldValidator runat=”server” ID=”ValidateNick”
ErrorMessage=”Il Nickname deve essere specificato”
ControlToValidate=”Nick”
Display=”dynamic”><img src=”imgError.gif” border=”0”>
</asp:RequiredFieldValidator>
</asp:TableCell>
</asp:TableRow>

<asp:TableRow>
<asp:TableCell Text=”Password:”/>
<asp:TableCell>
<asp:TextBox runat=”server” Width=”200px” ID=”Password” />
<asp:RequiredFieldValidator runat=”server”
ControlToValidate=”Password”
ErrorMessage=”Ia Password deve essere specificato”
Display=”dynamic”><img src=”imgError.gif” border=”0”>
</asp:RequiredFieldValidator>
</asp:TableCell>
</asp:TableRow>

<asp:TableRow>
<asp:TableCell Text=”Ripeti Password:”/>
<asp:TableCell>
<asp:TextBox runat=”server” Width=”200px” ID=”Password2” />
<asp:RequiredFieldValidator runat=”server”
ControlToValidate=”Password2”
ErrorMessage=”Ia Password di conferma deve essere specificata”
Display=”dynamic”><img src=”imgError.gif” border=”0”>
</asp:RequiredFieldValidator>
<asp:CompareValidator runat=”server”
ControlToValidate=”Password2”
ControlToCompare=”Password”
Type=”String”
ErrorMessage=”La password di conferma non corrisponde”
Display=”dynamic”><img src=”imgError.gif” border=”0”>
</asp:CompareValidator>
</asp:TableCell>
</asp:TableRow>

<asp:TableRow>
<asp:TableCell />
<asp:TableCell>
<asp:Button runat=”server” Text=”Invia” ID=”Submit” OnClick=”Submit_Click” />
</asp:TableCell>
</asp:TableRow>
</asp:Table>

<br>
<asp:CheckBox runat=”server” ID=”EnableValidators”
Checked=”true” AutoPostBack=”true”/>Validatori attivati
<br>
<asp:CheckBox runat=”server” ID=”EnableClientSide”
Checked=”true” AutoPostBack=”true”/>Validatori lato client
<br>
<asp:CheckBox runat=”server” ID=”ShowSummary”
Checked=”true” AutoPostBack=”true”/>Mostra riassunto

N. 63 - Maggio/Giugno 2005 VBJ 21


ASP.NET

Listato 1 (segue) Il codice completo della pagina di esempio

<br>
<asp:CheckBox runat=”server” ID=”ShowMsgBox”
Checked=”false” AutoPostBack=”true”/>Mostra MessageBox
<br><br>

<asp:ValidationSummary runat=”server” ID=”ValidationSum”


DisplayMode=”BulletList”
HeaderText=”<b>La pagina contiene i seguenti errori:</b>”
ShowSummary=”true”
/>

</form>

<asp:Label runat=”server” ID=”Result” ForeColor=”magenta” Font-Bold=”true”/>

</body>
</html>

<script language=”C#” runat=”server”>

void Page_Load()
{
Result.Text=””;
foreach (BaseValidator valCtl in Page.Validators)
{
valCtl.Enabled=EnableValidators.Checked;
valCtl.EnableClientScript=EnableClientSide.Checked;
}
ValidationSum.ShowMessageBox=ShowMsgBox.Checked;
ValidationSum.ShowSummary=ShowSummary.Checked;
}

void EmpIDServerValidate(object sender, ServerValidateEventArgs args)


{
try
{
args.IsValid = (int.Parse(args.Value)%5 == 0);
}
catch
{
args.IsValid = false;
}
}

void Submit_Click(object sender, EventArgs e)


{
if (Page.IsValid)
Result.Text=”Grazie per aver inviato i tuoi dati”;
else
Result.Text=”Ci sono degli errori! Correggi subito!!!”;
}

</script>

22 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

Per esempio di seguito è dichiarato un con- ErrorMessage=”Il nome non pu&ograve; contenere cifre”
trollo che verifica che il campo Nome conten- Display=”dynamic”>*
ga solo lettere minuscole o maiuscole o spa- </asp:RegularExpressionValidator>
zi, ma niente cifre o altri caratteri:
mentre l’espressione che segue controlla che
<asp:RegularExpressionValidator runat=”server” il campo Email contenga un indirizzo dal for-
ID=”ValidateName2” mato corretto (alcuni caratteri)
ControlToValidate=”Name” …
validationExpression=”[a-z A-Z]*” validationExpression=”.*@.{2,}\..{2,}”

Listato 2 Alcune routine del file WebUIValidation.js per la


validazione lato client
Questa espressione impone che ci
sia un numero di caratteri qualsiasi
function ValidatorCompare(operand1, operand2, operator, val) { (“.*”) seguiti da una ‘@’, almeno due
var dataType = val.type; caratteri (“.{2,}”), un punto e alme-
var op1, op2; no altri due caratteri. In realtà que-
if ((op1 = ValidatorConvert(operand1, dataType, val)) == null)
return false;
sta espressione non è perfetta per-
if (operator == “DataTypeCheck”) ché l’indirizzo è considerato valido
return true; anche se si inseriscono caratteri in-
if ((op2 = ValidatorConvert(operand2, dataType, val)) == null) validi come ^ o altri.
return true;
switch (operator) {
È comunque possibile ottenere
case “NotEqual”: un’espressione molto più comple-
return (op1 != op2); ta, per maggiori informazioni riguar-
case “GreaterThan”: do la sintassi da usare potete con-
return (op1 > op2);
case “GreaterThanEqual”: sultare [1].
return (op1 >= op2);
case “LessThan”: Un controllo per la validazione
return (op1 < op2); personalizzata
case “LessThanEqual”:
return (op1 <= op2); I tre controlli visti finora probabil-
default: mente rendono molto soddisfatti
return (op1 == op2); la maggior parte dei programma-
}
tori ASP, ma non è tutto qui. C’è
}
un altro controllo, CustomValidator,
function CompareValidatorEvaluateIsValid(val) { al quale possono essere associate
var value = ValidatorGetValue(val.controltovalidate); due routine personalizzate di verifi-
if (value == “”)
return true;
ca, per controllare l’input secondo
var compareTo = “”; una qualsiasi logica.
if (null == document.all[val.controltocompare]) { Una procedura serve per la verifi-
if (typeof(val.valuetocompare) == “string”) { ca lato client (opzionale), l’altra lato
compareTo = val.valuetocompare;
}
server, e vengono associate tramite
} la proprietà ClientValidationFunction
else { e il gestore di evento OnServerVali-
compareTo = ValidatorGetValue(val.controltocompare); date, rispettivamente.
}
return ValidatorCompare(value, compareTo, val.operator, val); Questo controllo è utile quando
} si deve convalidare un valore che
deve seguire delle regole partico-
function RegularExpressionValidatorEvaluateIsValid(val) { lari, ad esempio un numero di car-
var value = ValidatorGetValue(val.controltovalidate);
if (value == “”) ta di credito.
return true; Iniziamo vedendo come deve esse-
var rx = new RegExp(val.validationexpression); re dichiarato il controllo:
var matches = rx.exec(value);
return (matches != null && value == matches[0]);
} <asp:TextBox runat=”server” Width=”200px”
ID=”EmpID” />

N. 63 - Maggio/Giugno 2005 VBJ 23


ASP.NET

<asp:CustomValidator runat=”server” ID=”ValidateEmpID2”


ControlToValidate=”EmpID”
ClientValidationFunction=”EmpIDClientValidate”
OnServerValidate=”EmpIDServerValidate”
ErrorMessage=”L’ID deve essere un multiplo di 5”
Display=”dynamic”>*
</asp:CustomValidator>

La due funzioni di controllo sono dichiarate


nello stesso modo, salvo ovviamente che una
è in JavaScript (per ottenere la massima com-
patibilità con i browser) e la seconda in C#.
Hanno due parametri, il primo è un oggetto che
fa riferimento al controllo validatore chiamante,
e il secondo è un oggetto contenente l’attuale
valore del controllo di input (proprietà Value) e
una proprietà, IsValid, il cui valore verrà impo-
stato come risultato della verifica.
Nell’esempio preparato le due funzioni con-
trollano che il numero specificato nell’input sia
un multiplo di 5.
Ecco la versione lato client:

<script language=”JavaScript”>
function EmpIDClientValidate(ctl, args)
{
args.IsValid=(args.Value%5 == 0);
}
</script> Figura 3 I validatori sono disabilitati, quindi
l’input non viene controllato e la pagina
viene inviata con successo
Ed ecco quella molto simile in versione C#
per il lato server:

void EmpIDServerValidate(object sender, Le proprietà caratteristiche di questo compo-


ServerValidateEventArgs args) nente sono:
{
try • HeaderText: il titolo del report;
{ • DisplayMode: lo stile con il quale saranno
args.IsValid = (int.Parse(args.Value)%5 == 0); visualizzati tutti gli errori.
} Le possibili scelte sono SingleParagraph,
catch che mostra tutti i messaggi sulla stessa riga
{ e separati solo da uno spazio, List che ne
args.IsValid = false; mostra uno per riga o BulletList che ne mo-
} stra uno per riga con un pallino accanto
} (come con il tag <LI>);
• ShowSummary: se true, il report viene mo-
Un resoconto degli errori strato direttamente nella pagina con lo stile
L’ultimo controllo della serie è dedicato alla indicato dalla proprietà precedente;
creazione di un rapporto sugli errori incontrati • ShowMessageBox: se vale true e se è attiva
al momento dell’invio dei dati al server. la validazione client side (proprietà Enable-
Questo controllo si chiama ValidationSum- ClientScript, true di default) gli errori ven-
mary, e mostra i messaggi di errore (quelli spe- gono mostrati tramite una message box,
cificati dalla proprietà ErrorMessage) di tutti gli una di quelle che si ottengono con Alert di
altri validatori la cui proprietà IsValid è false. JavaScript e raffigurata in Figura 2.

24 VBJ N. 63 - Maggio/Giugno 2005


ASP.NET

Nella pagina di esempio ci sono delle che-


ckbox che permettono di abilitare o meno
la validazione totale, solo quella client side,
l’apertura della message box e il report nella
pagina. Quando una di queste checkbox vie-
ne cliccata, l’evento causa un postback della
pagina (per farlo il controllo deve essere di-
chiarato con la proprietà AutoPostBack ugua-
le a true), ossia la pagina viene inviata a se
stessa e ricaricata.
Nell’evento Page_Load i nuovi valori ven-
gono letti e le proprietà cambiate di conse-
guenza. Ciò che è interessante è la possibi-
lità di accedere a tutti i controlli con un solo
ciclo grazie al costrutto foreach di C# (o for
each in VB.NET), quindi senza la necessità
di specificare e conoscere gli ID di ciascun
componente.

Ecco l’esempio:

foreach (BaseValidator valCtlin Page.Validators)


{
valCtl.Enabled=EnableValidators.Checked;
valCtl.EnableClientScript=EnableClientSide.Checked;
Figura 4 Un esempio di input corretto }

Le altre due proprietà si riferiscono invece al


solo controllo ValidationSummary:
Questa proprietà non esclude la preceden-
te, entrambe possono essere true e gli erro- ValidationSum.ShowMessageBox=ShowMsgBox.Checked;
ri verranno mostrati in entrambi i modi. Ecco ValidationSum.ShowSummary=ShowSummary.Checked;
un esempio per la dichiarazione:

<asp:ValidationSummary runat=”server” ID=”ValidationSum”


DisplayMode=”BulletList” Ciò che viene
HeaderText=”<b>La pagina contiene i seguenti errori:</b>”
ShowSummary=”true” prodotto per il client
/>
è semplice HTML
Una sola nota particolare su questo controllo: il e JavaScript
report nella pagina viene visualizzato anche se il
controllo è stato dichiarato all’esterno del bloc-
co di tag <form>…</form>, ma se si vogliono
mostrare gli errori tramite message box allora In Figura 3 si vede che quando i validatori
deve essere necessariamente all’interno. sono disabilitati viene mostrato il messaggio
di conferma anche se l’input è in gran parte
Modificare le proprietà a runtime invalido, mentre in Figura 4 si vede la stessa
Una delle cose più belle di ASP.NET è che a schermata ma con i validatori attivati e l’input
runtime, all’interno delle procedure di evento, completamente corretto.
è possibile accedere a tutti i controlli ai quali Ultima domanda è come venga mostrato quel
era stato assegnato un ID, per leggere o mo- messaggio.
dificare qualsiasi loro proprietà modificando di Quando il pulsante “Invia” viene premuto esso
conseguenza il loro comportamento. genera un evento Click che può essere gestito

N. 63 - Maggio/Giugno 2005 VBJ 25


ASP.NET

per controllare la proprietà IsValid della pagina: no del file JavaScript incluso, la quale usa
il valore sarà true solo se sarà tale la proprietà un ciclo per processare ogni elemento del-
IsValid di tutti i validatori sulla pagina. l’array controllandolo ed eventualmente as-
Da notare che se è attivato il controllo lato sociandolo a delle procedure di evento, tut-
client e se il browser è di alto livello con il sup- to tramite routine secondarie.
porto DHTML questo evento non verrà solle- Tanto per farsi un’idea, nel Listato 2 sono
vato finché la pagina non viene inviata cor- riportate le funzioni che implementano i con-
rettamente. trolli CompareValidator e RegularExpression-
Per vedere il messaggio di errore generato sul Validator.
server bisogna necessariamente disabilitare gli
script sul client, come da Figura 1.
Nel Listato 1 (disponibile sul sito ftp di In-
fomedia) trovate tutto il codice della pagina, I controlli sono oggetti
compresa quest’ultima parte sulla program- ed è possibile cambiare
mazione server side.
Infine, ricordate che la validazione dell’input le loro proprietà
avviene ogni volta che si tenta di fare un post-
back della pagina, e questo accade anche
a runtime
quando si preme un altro bottone, ad esem-
pio un eventuale Cancella o Elimina Record.
Per questi pulsanti ovviamente non si vuo- Infine, le variabili globali Page_IsValid e
le che l’input venga controllato, e allora nella Page_BlockSubmit indicano se la pagina è
loro dichiarazione basta impostare la proprie- risultata valida o se l’invio al server deve es-
tà CausesValidation su false. sere bloccato.

Un’occhiata dietro le quinte Conclusioni


Prima di concludere è interessante vedere Sebbene ASP.NET non faccia cose veramen-
come funziona veramente il procedimento di te magiche, tutto quello che arriva al brow-
validazione, ossia qual è il trucco per rendere ser è semplice HTML e codice di scripting
automatico il tutto. client side, è quasi magia poter creare appli-
La validazione viene effettuata anche sul cazioni significative in molto meno tempo ri-
client, quindi vuol dire che viene prodotto spetto a quello che occorrerebbe con l’ASP
normale codice JavaScript per il controllo di classico.
tutti i valori. Il set di componenti di validazione fanno la
Dando un’occhiata al codice HTML prodot- loro bella parte come si è visto, tanto più che
to per la pagina mostrata si vede che all’inizio verranno usati in modo più o meno estensivo
viene incluso il seguente file .JS: in praticamente tutte le applicazioni.
Oltre alla semplicità della dichiarazione, alla
<script language=”javascript” possibilità di personalizzarli e cambiare il loro
src=”/aspnet_client/system_web/1_0_2914_16/ comportamento a runtime con poche righe,
WebUIValidation.js”> riducendo il tempo di sviluppo, viene ridot-
</script> to quasi a zero anche il tempo di debug per
quest’aspetto delle applicazioni, infatti il co-
Nel seguito viene definito un array con tutti i dice JavaScript prodotto – spesso fonte di
controlli validatori, come segue: errori per i programmatori ASP non abitua-
ti alla programmazione lato client – sarà sta-
var Page_Validators = new Array( to sicuramente testato in lungo e in largo. E
document.all[“ValidateName”], pensare che tutto ciò è solo un millesimo del-
document.all[“ValidateName2”], la potenza di ASP.NET.
document.all[“ValidateEmpID”],
document.all[“ValidateEmpID2”], …etc…) Bibliografia
[1] M. Merlano – “Utilizzare le regular expres-
e poco dopo c’è una chiamata a Validato- sion”, VBJ n. 33 Mag/Giu 2000, Gruppo Edi-
rOnLoad, una funzione che si trova all’inter- toriale Infomedia.

26 VBJ N. 63 - Maggio/Giugno 2005


SOFTWARE ENGINEERING

I design pattern DP2

più famosi
implementati in VB .NET Seconda puntata

Il pattern Observer consente di notificare ad un insieme di ‘osservatori’


le modifiche apportate ad un oggetto

di Lorenzo Vandoni


N
el primo articolo di questa serie è stata presen- Motivation. Il classico esempio
tata un’introduzione al movimento dei pattern, che viene fatto per spiegare il
ed è stato fornito un esempio di implementa- problema che il pattern inten-
zione VB.NET di uno tra i pattern più famosi tra quel- de risolvere è quello di un’appli-
li presentati nel libro “Design Patterns” di Gamma, cazione a documenti multipli, in
Helm, Johnson e Vlissides. In questa puntata verrà cui ci sono diverse finestre aper-
preso in considerazione un altro dei pattern presen- te che mostrano viste differen-
tati in questo testo, denominato Observer. La descri- ti degli stessi dati. Ad esempio,
zione di questo pattern verrà effettuata utilizzando la una finestra potrebbe mostrare i
convenzione presentata nella prima puntata, costitui- dati delle vendite in una griglia,
ta da un insieme di proprietà associate ad una de- mentre un’altra finestra potreb-
scrizione testuale che permettono di presentare se- be mostrare gli stessi dati in un
paratamente il problema, i vincoli e la soluzione del grafico a torta. In casi del ge-
pattern. Anche in questo caso, infine, verrà fornito nere, tipicamente, si vuole fare
un esempio di implementazione VB.NET. in modo che le modifiche ap-
portate in una delle finestre
Il pattern Observer, descrizione (ad esempio, la selezione di un
La descrizione del pattern è costituita dai paragrafi mese diverso) vengano auto-
seguenti, che ne evidenziano lo scopo, le motivazioni, maticamente rispecchiate dal-
i problemi affrontati e la soluzione suggerita. le altre. Questa necessità può
però portare ad una progettazio-
• Intent. Observer è un pattern che permette di as- ne sbagliata della struttura del
sociare ad un oggetto un insieme di osservatori, programma, in cui ogni classe
a cui viene inviata una notifica ogni volta che al- risulta a conoscenza delle altre,
l’oggetto vengono apportate delle modifiche. pregiudicando così sia la riusa-
bilità delle stesse, sia la possi-
bilità di aggiungere nuove clas-
si, ovvero nuovi tipi di viste sui
Lorenzo Vandoni è laureato in Informatica, ed è uno spe- dati. La soluzione proposta dal
cialista di progettazione e sviluppo con tecniche e linguaggi
pattern è quella di distinguere
object-oriented. Ha collaborato alla realizzazione di framework,
strumenti di sviluppo e software commerciali in C++, Java e gli oggetti osservatori, interessa-
Visual Basic. Può essere contattato tramite e-mail all’indirizzo ti a rispecchiare immediatamen-
vandoni@infomedia.it. te le modifiche apportate, dagli

28 VBJ N. 63 - Maggio/Giugno 2005


SOFTWARE ENGINEERING

cui istanze dovranno essere gli oggetti os-


servati, dovrà implementare la prima inter-
faccia, mentre ogni classe usata per imple-
mentare un osservatore dovrà implementa-
re la seconda. Nel diagramma, queste clas-
si sono rappresentate da ConcreteSubject e
ConcreteObserver, ma in un caso reale po-
tranno esistere molte implementazioni per
ognuna delle due interfacce.

• Participants. Vengono di seguito descritte le


Figura 1 Architettura del pattern Observer responsabilità delle interfacce e delle classi
precedentemente introdotte:

o l’interfaccia Subject mentiene una lista di


oggetti osservati, quelli cioè su cui tali modi- Observer, e fornisce un metodo Add tra-
fiche vengono effettuate. Nel seguito dell’ar- mite il quale un Observer può registrarsi.
ticolo supporremo, per semplicità, che esista Il metodo NotifyAll serve per notificare a
un unico oggetto osservato ed uno o più os- tutti gli Observer che si sono registrati,
servatori, ma la soluzione che vedremo si può e che sono mantenuti nella lista, un’av-
applicare anche ai casi più complessi in cui gli venuto cambiamento di stato.
oggetti osservati siano più d’uno. Questo tipo o la classe ConcreteSubject fornisce un’im-
di interazione è anche nota col termine publish- plementazione dell’interfaccia, e imple-
subscribe. L’oggetto osservato, cioè, può es- menta un metodo GetState che permet-
sere assimilato a un fornitore di servizi, men- te agli Observer di conoscere lo stato at-
tre gli osservatori possono essere visti come tuale dell’oggetto osservato.
i sottoscrittori di una sorta di abbonamento. Il o l’interfaccia Observer contiene un meto-
sottoscrittore avvisa il publisher che è interes- do Update che viene utilizzato da parte
sato a ricevere informazioni aggiornate ogni del metodo NotifyAll del subject per in-
volta che al publisher succede qualcosa, ma formare i singoli Observer di un avvenu-
è poi compito di quest’ultimo avvisare i sotto- to cambiamento di stato.
scrittori ogni qual volta si verifica qualcosa di o la classe ConcreteObserver implementa
interessante. l’interfaccia e ha la responsabilità di ef-
fettuare un aggiornamento della visua-
• Applicabilità. Il pattern è applicabile in tutti lizzazione, richiamando il metodo Get-
quei contesti in cui le modifiche apportate State del ConcreteSubject osservato,
ad alcuni oggetti o dati dell’applicazione de- per conoscerne lo stato attuale.
vono essere note ad altre parti dell’applica-
zione, soprattutto se il numero di oggetti o • Collaborations. La collaborazione tra gli ogget-
dati variati, e il numero di sezioni dell’appli- ti che fanno parte del sistema è di fatto defini-
cazione interessate ad essere informate di ta dalle responsabilità dei partecipanti, ma può
tali modifiche non sono noti a priori o pos- essere utile chiarire questo aspetto mostrando
sono variare nel tempo. la sequenza temporale di tale interazione:

Soluzione del problema o come prima cosa, due oggetti Observer A


La soluzione del problema è costituita dal dia- e B notificano il proprio interesse ad es-
gramma di classi mostrato in Figura 1. I pa- sere informati dei cambiamenti di stato ad
ragrafi seguenti ne forniscono una descrizione un Subject S utilizzando il metodo Add.
più dettagliata. o nel momento in cui avviene un cambia-
mento di stato, ad esempio a seguito di
• Structure. Il cuore della soluzione è costituito un’operazione dell’utente, il Subject uti-
dalle due interfacce Subject e Observer, che lizza il proprio metodo NotifyAll per notifi-
rappresentano un generico oggetto osserva- care questo cambiamento ai vari Observer.
to e un generico osservatore. Ogni classe, le Questo metodo, di fatto, richiama il meto-

N. 63 - Maggio/Giugno 2005 VBJ 29


SOFTWARE ENGINEERING

do Update dei due Observer. Implementazione del pattern in VB.NET


o ognuno dei due Observer mantiene un rife- L’esempio fornito è costituito da un’applicazione
rimento al Subject a cui è interessato, e a web, in cui è presente un piccolo banner, imple-
cui ha inviato il messaggio Add, e una volta mentato tramite uno user control, che permette
che gli è stato notificato un cambiamento all’utente di selezionare la lingua utilizzata. Si in-
di stato, utilizza il metodo GetState di que- tende costruire questo banner in modo che pos-
st’ultimo per conoscerne lo stato attuale. sa essere riusato in più applicazioni. Ovviamente,
o una volta conosciuto lo stato attuale, ognu- non è possibile prevedere a priori quali saranno,
no degli Observer aggiorna il proprio stato in queste applicazioni, gli elementi di interfaccia
o la propria interfaccia grafica, per rispec- che dovranno variare a seconda della lingua se-
chiare il nuovo stato del Subject. lezionata, e in che modo. Questo banner è quin-
di un ottimo candidato per diventare un Subject
Conseguenze e benefici del pattern.
I paragrafi seguenti descrivono i punti di for- Nell’esempio, le due interfacce, che si possono
za della soluzione e mostrano alcune sue pos- vedere anche nel Listato 1, sono definite all’in-
sibili applicazioni pratiche: terno del file Interfaces.vb.
L’esempio è costituito da una pagina principale,
• Consequences. Il principale vantaggio che si WebForm1.aspx, al cui interno vengono posiziona-
ottiene è quello di svincolare totalmente il Su- ti, con l’aiuto di una tabella, tre user control, de-
bject dagli Observer che lo utilizzano. In que- nominati rispettivamente choose_language.ascx,
sto modo si possono creare una o più classi left_menu.ascx e page_body.ascx. Il control choo-
ConcreteSubject che non devono conoscere se_language.ascx implementa l’interfaccia Su-
nulla degli oggetti che verranno utilizzati per la bject. Per farlo definisce una variabile di istan-
loro visualizzazione, e saranno così facilmente za myObservers, dove mantenere la lista di tut-
riusabili in diverse applicazioni. ti gli Observer, e implementa i due metodi Add
e NotifyAll.
• Known uses. Questo pattern è utilizzato in I due control left_menu.ascx e page_body.ascx
molte applicazioni e librerie. Lo stesso mo- implementano l’interfaccia Observer, fornendo un
dello asincrono di gestione degli eventi, co- metodo Update, che viene utilizzato per aggior-
mune a tutte le applicazioni Windows, può nare il contenuto del control stesso.
essere considerato come un’applicazione All’interno di questo metodo lo stato del Subject
del pattern, in quanto l’oggetto che attiva viene interrogato in maniera indiretta, utilizzando il
l’evento può non sapere nulla degli oggetti contenuto di una variabile di sessione. Il compito
che andranno a gestirlo. Personalmente ho di assegnare al Subject l’elenco degli Observer
applicato il pattern in vari contesti, uno dei viene implementato all’interno dell’evento Page_
quali, semplificato, costituisce l’esempio al- Load della pagina principale. Si può facilmente
legato a questo articolo. notare, dal codice, come il componente choose_
language.ascx risulti del tutto indipendente dagli
Listato 1 Implementazione delle interfacce del
altri. Risulterà facile, quindi, riutilizzarlo all’interno
pattern in VB.NET di altre applicazioni.

Conclusioni
‘’’’’’’’’’’’’’’’’’’’’’’’’’’’ Observer è un pattern piuttosto semplice ma,
‘’’ Interfaccia Observer ‘’’ come spesso capita coi pattern, spesso risul-
‘’’’’’’’’’’’’’’’’’’’’’’’’’’’
Public Interface Observer ta difficile riconoscere nel proprio problema
Sub Update() applicativo un caso in cui esso sia applica-
End Interface bile. Il grosso vantaggio di Observer è quello
di consentire di creare un Subject riusabile,
‘’’’’’’’’’’’’’’’’’’’’’’’’’’
‘’’ Interfaccia Subject ‘’’ con evidenti vantaggi anche in fase di manu-
‘’’’’’’’’’’’’’’’’’’’’’’’’’’ tenzione. Il mancato utilizzo del pattern può
Public Interface Subject provocare problemi a lungo termine, in quan-
Sub Add(ByVal oObs As Observer)
Sub NotifyAll()
to spesso porterà a una progettazione in cui
End Interface i vari componenti dell’applicazione risulteran-
no strettamente connessi tra loro.

30 VBJ N. 63 - Maggio/Giugno 2005


SOFTWARE ENGINEERING

Implementazione
della logica applicativa
in programmi VB.NET
Seconda puntata
Mostriamo l’implementazione di alcune classi che consentono di
incapsulare la logica applicativa

Logica 2
di Lorenzo Vandoni

P
roseguiamo in questo articolo la discussione mostra come strutturare un insie-
iniziata in [1], dove era stata mostrata una pos- me di classi .NET che implementa-
sibile soluzione per la realizzazione di classi no la logica applicativa di un pro-
.NET che implementino la logica applicativa del pro- gramma, evitando di scrivere co-
gramma. La puntata precedente è stata dedicata al dice ripetitivo e ridondante.
trattamento delle problematiche progettuali. In que- L’idea è quella di utilizzare la clas-
sto articolo ci dedicheremo invece ai problemi legati se DataRow di ADO.NET come
all’implementazione. base da cui ereditare un insieme
di classi applicative, come Auto-
mobile o Fattura. Tali classi saran-
no implementate solo quando real-
L’idea è quella di utilizzare mente necessarie, scegliendo di
la classe DataRow di utilizzare semplici istanze di Da-
taRow ogni qualvolta la derivazio-
ADO.NET come base ne di una classe specifica si dimo-
strerà inutile.
da cui ereditare un insieme Per ognuna di queste classi ap-
di classi applicative plicative verrà inoltre realizzata una
classe derivata da DataSet, che
avrà il compito di incapsulare uno
specifico DataAdapter. Quest’ulti-
Il progetto da realizzare mo implementerà la logica di map-
Le considerazioni riportate in [1] ci hanno portato alla ping necessaria per creare, a par-
soluzione descritta in Figura 1. Questo diagramma tire dai dati del DBMS, un’istanza
della classe applicativa ed even-
tuali istanze di classi accessorie,
Lorenzo Vandoni è laureato in Informatica, ed è uno spe- come ad esempio Carrozzeria e
cialista di progettazione e sviluppo con tecniche e linguaggi
Motore.
object-oriented. Ha collaborato alla realizzazione di framework,
strumenti di sviluppo e software commerciali in C++, Java e Questa struttura risulta forte-
Visual Basic. Può essere contattato tramite e-mail all’indirizzo mente dipendente dall’architet-
vandoni@infomedia.it. tura di ADO.NET, e quindi difficil-

N. 63 - Maggio/Giugno 2005 VBJ 31


SOFTWARE ENGINEERING

mente portabile su altri sistemi. Proprio per que- do quindi il numero di righe di codice da scri-
sto motivo, però, permette di soddisfare il princi- vere manualmente.
pale obiettivo che ci eravamo inizialmente posti, Per creare un DataSet tipizzato con Visual
ovvero quello di riuscire ad incapsulare la logica Studio si può procedere in questo modo:
applicativa in uno specifico strato di software in-
termedio, senza per questo provocare la creazio- • Anzitutto, si trascina su una form un ogget-
ne di un insieme di classi banali e strutturalmen- to Data Adapter. Nel nostro esempio vie-
te identiche tra loro. In tutti i casi in cui l’oggetto ne utilizzato un piccolo database Access,
applicativo risulterà strutturalmente semplice, in- e per questo motivo è stato scelto un Ole-
fatti, sarà sufficiente continuare ad utilizzare og- DbDataAdapter. Le stesse operazioni, però
getti DataSet e DataRow, senza implementare al- possono essere compiute con gli altri Data
cuna classe derivata. Adapter disponibili.
• Utilizzando il wizard che viene avviato auto-
DataSet tipizzati maticamente, impostare le caratteristiche del
Per implementare le classi Automobile e Auto- Data Adapter, andando in particolare a spe-
mobileSet ci avvarremo di una importante ca- cificare le tabelle di database da cui estrarre
ratteristica di Visual Studio, ovvero della pos- i dati. Nell’esempio allegato, viene utilizzata
sibilità di generare automaticamente il codice una semplice tabella Automobile.
di un DataSet tipizzato. • Infine, utilizzando il menu contestuale asso-
Un DataSet tipizzato non è altro che una sot- ciato al nuovo Data Adapter, si seleziona il
toclasse di DataSet, con membri pubblici ag- comando Generate DataSet, che consente
giuntivi che permettono di accedere a tabelle di specificare il nome del DataSet tipizzato,
e colonne utilizzando metodi specifici, generati nel nostro caso AutomobileSet, e lo si alle-
automaticamente da Visual Studio. ga al progetto.

Per esempio utilizzando un DataSet tipizzato Questa operazione si traduce visivamente


si potrà scrivere: nella creazione di un file AutomobileSet.xsd,
ovvero di uno schema XML che mantiene la
MyDataSet.Clienti.RagioneSociale struttura del DataSet corrispondente.
Oltre a questo file, però, viene creato anche
invece di: un file “nascosto” AutomobileSet.vb, che può
essere ispezionato passando alla visualizza-
MyDataSet.Tables(“clienti”).Columns(“RagioneSociale”) zione di tipo Class View. Questo file contiene
quattro classi. La principale è AutomobileSet,
Un DataSet tipizzato consente una maggiore derivata da DataSet.
tranquillità in fase di codifica, in quanto permet- Le altre sono AutomobileDataTable, Automo-
te di evitare errori nell’utilizzo dei nomi e dei bileRow e AutomobileRowChangeEvent, deri-
tipi dei campi, che nel caso di
un normale DataSet non posso-
no essere intercettati dal com-
pilatore.
Lo svantaggio, in questo caso,
è dato da una eccessiva pro-
liferazione di classi, e soprat-
tutto dalla necessità di man-
tenerle a seguito di eventua-
li modifiche alla struttura della
base dati.
In questo contesto, vedre-
mo come sfruttare un Data-
Set tipizzato per implementa-
re la logica applicativa, sfrut- Figura 1 Architettura delle classi necessarie per implementare la logica
tando il generatore di codice applicativa
di Visual Studio e minimizzan-

32 VBJ N. 63 - Maggio/Giugno 2005


SOFTWARE ENGINEERING

Gli oggetti applicativi


La classe AutomobileRow
rappresenta in questo esem-
pio l’elemento che ha il compi-
to di mantenere la logica appli-
cativa. Ogni sua istanza rappre-
senta il progetto di un’automo-
bile, al quale devono poter es-
sere applicate operazioni grafi-
che complesse, come Capovol-
gi e Ruota.
A titolo di esempio, il codice
allegato implementa un sempli-
ce metodo Sposta, che permet-
te di traslare l’oggetto a sinistra
o a destra di un numero speci-
ficato di unità :

Public Sub Sposta(ByVal x As Integer)


Me.x1 = Me.x1 + x
Me.x2 = Me.x2 + x
End Sub

Grazie al fatto che questa


classe è derivata da DataRow,
Figura 2 Il Query Builder permette di specificare interattivamente le carat- sarà possibile utilizzare con-
teristiche di un Data Adapter temporaneamente sia i metodi
che ne implementano la logica
applicativa specifica, esempli-
ficati da Sposta, sia quelli che
vate rispettivamente da DataTable, Data- consentono di sfruttare l’oggetto nella sua ac-
Row e EventArgs, e implementate come cezione generica di riga di una tabella.
classi innestate di AutomobileSet.
Il codice di queste classi, generato au-
tomaticamente dal tool, è strutturalmente
piuttosto semplice. La classe Automobi-
La scelta di sfruttare
leSet contiene due costruttori specifici, e questo automatismo
sovrascrive (overrides) alcuni metodi del-
la classe base. ci impone di accettare
In più, contiene una proprietà Automobile alcune limitazioni rispetto
che permette di accedere all’oggetto Data-
Table tipizzato. al progetto originale
La classe AutomobileDataTable, a sua vol-
ta, mette a disposizione un insieme di pro-
prietà che permettono di accedere per nome
alle varie colonne contenute nella tabella, L’applicazione di esempio
nonché alcuni metodi, come AddAutomo- Il codice allegato contiene una piccola appli-
bileRow, NewAutomobileRow e RemoveAu- cazione di esempio, costituita da un program-
tomobileRow, che consentono di accedere ma Windows che sfrutta le classi applicative
alle righe della tabella considerandole come AutomobileSet e AutomobileRow, mostrando
istanze della classe AutomobileRow. come sia possibile accedere sia ai metodi spe-
Quest’ultima classe, infine, fornisce un in- cifici, sia a quelli generici.
sieme di proprietà tipizzate per accedere ai In particolare, i dati mantenuti all’interno del-
valori mantenuti nelle singole celle. l’oggetto AutomobileSet vengono normalmente

N. 63 - Maggio/Giugno 2005 VBJ 33


SOFTWARE ENGINEERING

visualizzati all’interno di un DataGrid, mentre il


codice associato ad un pulsante mostra come
sfruttare i metodi applicativi specifici:

Dim oAuto As AutomobileSet.AutomobileRow


oAuto = AutomobileSet1.Automobile.Item(DataGrid1
.CurrentRowIndex)
oAuto.Sposta(TextBox1.Text)
DataGrid1.Refresh()

L’accesso all’oggetto oAuto viene implemen-


tato tramite la proprietà Item della classe Auto-
mobileTable, che restituisce un riferimento ad
un oggetto AutomobileRow. Una volta ottenuto
il riferimento a questo oggetto, diviene possibile
richiamarne i metodi applicativi specifici.

La classe AutomobileRow
rappresenta l’elemento
che ha il compito
di mantenere la Figura 3 La vista Class View permette di accedere al
logica applicativa file AutomobileSet.vb generato dal wizard

scopi, che, anche se molto utili per evitare er-


Conclusioni rori a runtime, provocano la necessità di mo-
Grazie all’automatismo offerto da Visual Studio dificare il codice generato ogni qualvolta vie-
nella generazione del codice associato ai Data- ne effettuata una modifica alla struttura del da-
Set tipizzati, l’implementazione di classi che in- tabase. Queste limitazioni risultano però tutto
capsulino la logica applicativa del programma sommato non troppo pesanti, soprattutto se si
risulta semplice e veloce. considera il risparmio di tempo che l’automati-
La scelta di sfruttare questo automatismo però smo permette di ottenere. La soluzione che ab-
ci impone di accettare alcune limitazioni rispet- biamo ottenuto è molto .NET-centrica, e difficil-
to al progetto originale. mente portabile su diverse librerie, linguaggi di
programmazione o ambienti di sviluppo.
Questa è stata però una scelta di progetto,
che ha permesso di ottenere classi che, oltre
Un DataSet tipizzato non a implementare una specifica logica applicati-
va, ci consentono di continuare a sfruttare gli
è altro che una sottoclasse automatismi del framework, come ad esem-
di DataSet con dei membri pio la possibilità di mostrare i dati all’interno
di una griglia.
pubblici aggiuntivi
Bibliografia
[1] L.Vandoni, “Implementazione della logica ap-
Anzitutto, il Data Adapter non viene incapsulato plicativa in programmi VB.NET”, VBJ n. 62,
all’interno della classe, ma rimane al suo ester- Marzo 2005
no. Inoltre, le classi generate vengono riempite [2] L.Vandoni, “L’accesso ai dati nei linguaggi
di metodi non strettamente necessari ai nostri object-oriented”, VBJ n.60, Novembre 2004

34 VBJ N. 63 - Maggio/Giugno 2005


DATABASE

Yukon in scena:
si alza il sipario
Yukon, nome in codice della nuova release del motore di database di casa Microsoft, ovve-
ro SQL Server 2005, sta prendendo definitivamente forma.

di Andrea Benedetti

I
n attesa della Beta 3, versione che ci si aspet- Il primo, SQL Computer Mana-
ta “features complete” e che dovrebbe vedere la ger, è un unico strumento che
luce nel prossimo mese di maggio, cominciamo raccoglie al suo interno le varie
a fare una panoramica su ciò che si presenterà agli utilità di servizi e di protocolli pri-
occhi dei DBA. ma distribuiti in diversi software
L’avvento del Framework .NET ha rivoluzionato il (Figura 2).
modo di lavorare degli sviluppatori e molto proba- Dalla console è possibile defini-
bilmente lo rivoluzionerà anche ai Database Admi- re alias di client (il vecchio Client
nistrator, grazie alla prossima versione del motore Network Utility, ora chiamato SQL
di database di casa Microsoft, completamente inte- Native Client Configuration), pro-
grato con la prossima release del Common Langua- tocolli di comunicazione abilitati
ge Runtime (la 2.0). SQL Server 2005 introduce, fi- e gestire tutti i servizi che pos-
nalmente, molte funzionalità attese e richieste dalla siamo installare a seconda del-
comunità degli sviluppatori/utilizzatori, alcune delle la versione del software: natural-
quali già presenti su sistemi concorrenti. mente SQL Server e SQL Agent
La scelta di versione su cui lavorare per la stesura e poi Analysis Server, Full Text,
dell’articolo è caduta sulla CTP (Community Technolo- Report Server. Da questa console
gy Preview) di Dicembre 2004, la versione 9.00.0981, interagiamo direttamente con tut-
l’ultima uscita dai laboratori di sviluppo Microsoft (Fi- ti i servizi sopra elencati, modifi-
gura 1). Applicazione sicuramente meno stabile del- candone la modalità di esecuzio-
la Beta2 già uscita, ma versione che introduce nuove ne (manuale, automatica o disa-
funzionalità (una tra tutte quella di aprire e visualizzare bilitata), la password di accesso
le tabelle - Open Table, come nel vecchio Entreprise e le classiche operazioni di start
Manager - anche se ancora non consente la distin- – stop – restart.
zione tra “Return all rows” e “Return Top”). Per rispondere ad una doman-
da che ricorre spesso sui new-
I nuovi tool di amministrazione e gestione sgroup, è utile specificare che
Due sono le novità relative ai tool di gestione e di tale utilità è legata alla macchi-
amministrazione presenti in questa nuova versione: na, quindi al server locale, che sia
SQL Computer Manager, uno snap-in per la Micro- mono o multi istanza. Non è quin-
soft Management Console (MMC), e SQL Server Ma- di possibile effettuare registrazio-
nagement Studio. ni verso altri server. La seconda,
più importante e chiaramente più
evidente novità, è SQL Server Ma-
Andrea Benedetti si occupa di disegno e manutenzione
di basi di dati e di sviluppo di applicazioni web-based fina-
nagement Studio.
lizzate all’erogazione di servizi sanitari per conto di Studio- Un unico software costruito ad
farma Srl di Brescia Può essere contatto all’indirizzo e-mail: hoc per la gestione e l’ammini-
abenedetti@infomedia.it strazione dei server, che unisce

N. 63 - Maggio/Giugno 2005 VBJ 35


DATABASE

la nostra istan-
za, scegliamo la
voce “Attach”.
Si presenterà a
video una finestra
che, pur essen-
do diversa dalla
versione 2000, ci
consente di ca-
pire immediata-
mente che dob-
biamo premere
il pulsante “Add”
per selezionare il
file di dati del da-
tabase di cui vo-
gliamo esegui-
re l’attach e pre-
mere “Ok”. Sele-
zioniamo quindi il
file northwnd.mdf
e procediamo al
suo attach. Tre
sono le novi-
Figura 1 SQL Server Management Studio tà che spiccano
subito in questa
finestra:

le funzionalità che erano proprie sia dell’Enter- - la finestra di selezione file adesso non è
prise Manager sia del Query Analyzer che quin- più una form-modale;
di, in quanto software distinto e separato, non - consente di visualizzare sotto forma di
esiste più. Abbandonata la scelta di utilizzare script l’azione che stiamo effettuando;
uno snap-in da inserire nella Microsoft Manage- - consente la possibilità di schedulare (e
ment Console (com’era invece Enterprise Ma- quindi di salvare) l’azione per eseguirla
nager) il tool è stato completamente riscritto e in un secondo momento.
ridisegnato, con un’interfaccia utente che, chi
è già abituato all’uso di Visual Studio, troverà Si tratta di novità che non sono presenti
assai familiare. solo nella finestra di selezione file, ma che
È interessante sapere da subito che il motore possiamo ritrovare praticamente in tutte le
di SQL Server 2005 consente la gestione an- attività che siamo in grado di svolgere sul
che di server relativi alla precedente versione server. La possibilità di avere form non -
(la 2000) e non viceversa, così come consen- modali (con il loro pulsante sulla barra delle
te l’attach di file di database provenienti pro- applicazioni) ci consente, ad esempio visua-
prio da quella versione. lizzando le proprietà di una tabella, di effet-
E proprio per effettuare una panoramica del- tuare delle comparazioni a video tra oggetti
le funzionalità e cominciare così a prendere di database/server diversi (cosa impossibile
dimestichezza con il nuovo strumento, ese- con la finestra delle proprietà nella versione
guiamo un attach dei file del classico databa- precedente). La possibilità di salvare (poten-
se Northwind prelevato da un’istanza di SQL do scegliere tra file, memoria, o una nuova
Server 2000. finestra di query) lo script delle azioni che an-
Come avremmo fatto con la versione prece- dremo a compiere, consente in primis di capire
dente, e quindi in maniera assolutamente im- come si comporta il software dietro le quinte,
mediata ed intuitiva, cliccando con il tasto de- quindi di poter sapere quali saranno le istruzioni
stro del mouse sulla cartella Databases del- che verranno effettivamente eseguite.

36 VBJ N. 63 - Maggio/Giugno 2005


DATABASE

Anche nella versione precedente era possibile Analyzer). Un’altra funzione accessibile diretta-
fare questo, a patto di aprire una traccia con SQL mente dal menu contestuale all’oggetto databa-
Profiler ed analizzare i vari comandi eseguiti passo se (tasto destro sul db, Tasks, Copy Database) è
passo. Avendo parlato dell’attach di un database, la copia di database.
è utile aprire subito una parentesi sull’operazione La scelta di questa funzione scatena la partenza
inversa: il detach. Questa operazione, che simil- di un wizard, quindi di un percorso guidato, che
mente alla precedente può essere fatta con il ta- consente la copia di un intero database da una
sto destro sul database interessato, menu Tasks – istanza SQL 2000 o naturalmente SQL 2005, ad
Detach, consente di poter chiudere (drop) le con- una istanza SQL 2005.
nessioni presenti ed eventualmente di aggiornare La copia può essere fatta adesso scegliendo tra
le statistiche della base dati. Una volta installato il due differenti modalità:
nostro database, prima di espandere il nodo “Nor-
thwind” appena creato, clicchiamo su di esso per - utilizzando il metodo detach/attach
visualizzare un’altra novità: la vista Summary (ta- - utilizzando il metodo di trasferimento SQL
sto F7). Una visualizzazione che risulta familiare Management Object
a chi era già abituato al “TaskPad” della versio-
ne precedente. Vista, questa, che ci permette di Il secondo metodo, certamente più lento, è
avere sotto controllo informazioni circa lo spazio chiaramente da preferirsi in tutti quei casi in
allocato, utilizzato e rimanente, data dell’ultimo cui si è impossibilitati a mettere in stato di of-
backup, connessioni attive e data di creazione. fline il database di partenza.
Espandiamo adesso il nodo “Northwind” per ac- Il metodo si rivela perfetto anche per effet-
corgerci della nuova suddivisione, quindi dell’or- tuare copie di database sulla stessa istanza,
ganizzazione logica, che viene fatta dei vari og- semplicemente cambiando il nome del db e dei
getti. Nei vari nodi figlio, se restano subito visibili file (o il percorso) di destinazione. Utilissimo il
sia Tables che Views, possiamo notare una nuova nuovo Template Explorer (dal menu View, op-
cartella – Programmability – che contiene al suo pure: CTRL + Alt + T) dal quale è possibile re-
interno le stored procedure, le funzioni, i trigger cuperare modelli guidati di istruzioni da ese-
(finalmente si possono vedere tutti e subito, sen- guire: attach/detach di database, configurazio-
za dover cercare tramite tasto destro – all tasks ne procedure di invio mail, definizione trigger,
– manage triggers sulle tabelle), tipi e ruoli, valo- ecc. (Figura 3).
ri di default, as-
sembly. Da sot-
tolineare come
le varie cartelle
di oggetti con-
tengano già, per
ogni database,
le stored proce-
dure, le funzioni
e le viste di si-
stema, consen-
tendo, con un
semplice drag
& drop sulle fi-
nestre di query,
di inserirle nel-
le istruzioni che
costruiremo (ri-
corda, anche se
in maniera mol-
to meglio orga-
nizzata, l’Object Figura 2 SQL Computer Manager
Browser del
vecchio Query

N. 63 - Maggio/Giugno 2005 VBJ 37


DATABASE

Gli attori entrano in scena EXEC sp_configure ‘show advanced options’ , ‘1’
Certamente le novità introdotte non riguarda- go
no solo gli strumenti di amministrazione e gestio- reconfigur
ne. Facciamo allora una panoramica cercando di go
presentare alcune delle più interessanti. La pri- EXEC sp_configure ‘clr enabled’ , ‘1’
ma, sicuramente quella più attesa e pubblicizza-
ta, riguarda, come abbiamo già accennato all’ini- Quindi possiamo costruire oggetti che si
zio, il supporto e l’integrazione con il framework riferiscono a metodi di classe, come:
.NET (la prossima release di Visual Studio 2005
contiene un nuovo tipo di progetto “Yukon”), sup- CREATE Function / Procedure / Trigger AS
porto dato non certo per mandare in pensione il EXTERNAL NAME myAssembly.myClass.myMethod
linguaggio T-SQL, che resta il linguaggio princi-
pe per la scrittura, il recupero e la manipolazione Le utilità oSql e iSql vengono sostituite e po-
dei dati, quanto per poter ottenere benefici che tenziate da un unico nuovo tool sempre a riga
si potranno avere, ad esempio, con l’accesso di- di comando: SQLCMD
retto a funzioni di crittografia, interazione con og-
getti COM tramite wrapper, possibilità di scrive- C:\>SQLCMD -E -dNorthwind -q”select * from region”
re ed utilizzare funzioni che prima avremmo do-
vuto scrivere ed installare come stored procedu- Il supporto mail è stato molto migliorato e, seppur
re estese, accedere a risorse esterne (file, Web esistendo ancora SQL Mail, entra in scena SQLi-
Service…) e, comunque, possibilità di utilizzare Mail, una nuova gestione non più basata su MAPI
tutto ciò che il framework mette a disposizione. ma su protocollo e server SMTP (consentendo di
Attenzione: il CLR (Common Language Runtime) specificarne anche più di uno). Il modello ad oggetti
è disabilitato per default e quindi per poterlo uti- DMO, pur restando per mantenere la compatibilità
lizzare è necessario abilitarlo, ad esempio tramite verso il basso, viene rimpiazzato ed ampliato da
la procedura sp_configure, come: due nuovi modelli ad oggetti, completamente scritti
per .NET, SMO (SQL Server Management Objects)e
RMO (Replica-
tion Management
Objects), ovvero
il modello relativo
alla gestione delle
repliche che sa-
ranno, da adesso,
possibili anche su
protocollo HTTP
L’utility Index Tu-
ning Wizard vie-
ne rimpiazzata ed
ampliata dal DTA,
Database Tuning
Advisor, che ana-
lizzando stress ed
utilizzo del server,
fornisce racco-
mandazioni circa
l’aggiunta, la mo-
difica e la rimo-
zione di strutture
legate alle perfor-
mance (indici clu-
Figura 3 Il Template Explorer ster e non-cluster,
viste indicizzate,
ecc.). Compare la

38 VBJ N. 63 - Maggio/Giugno 2005


DATABASE

funzione ROW_NUMBER, in grado di restituire un Il tipo di dati varchar che nella versione 2000
numero sequenziale di righe, comodissima per ri- permetteva una memorizzazione massima di
solvere il classico problema della paginazione dei 8.000 caratteri consente, specificando la clau-
dati su applicazioni web-based: sola max, di ampliarne la dimensione memo-
rizzabile fino ad un massimo di 2 GB intro-
USE Northwind ducendo, di fatto, il concetto di tipi “Large
GO Value”, arrivando alla memorizzazione di (231
WITH myProducts AS – 1) byte.
(
SELECT ProductName, UnitPrice, CREATE TABLE tabTest
ROW_NUMBER() OVER (order by ProductID)as RowNumber ( id int primary key, nome varchar(35), note varchar(max) )
FROM products
) La stessa clausola max può essere applicata
SELECT * FROM myProducts anche ai tipi Varbinary.
WHERE RowNumber between 40 and 50 Questa novità fornisce un’alternativa all’uti-
lizzo dei tipi text, ntext ed image, uniforman-
Nasce il nuovo operatore PIVOT, che consen- do il modello di accesso ai dati con i tipi già
te di realizzare molto facilmente query incrocia- presenti (possiamo quindi evitare di ricorrere a
te (possibili anche con la versione precedente, a funzioni specifiche costruite per i tipi blob: wri-
patto di lavorare molto sulla scrittura di procedu- teText, readText, updateText). Vengono intro-
re altamente personalizzate). dotti trigger che possono essere scatenati su
Attenzione: per poter utilizzare questo operato- eventi legati al database (alter/create/drop da-
re su database provenienti dalla versione 2000 di tabase), in sostanza su istruzioni di Data Defi-
SQL Server, è necessario che la compatibilità del nition Language (DDL).
database sia impostata a 90 (ovvero sul model- Questa tipologia di trigger, pur venendo invo-
lo SQL Server 2005). Per vedere la compatibilità cata sempre dopo lo scatenarsi dell’istruzione
impostata è sufficiente eseguire la procedura sp_ (ovvero non esistono, per questa tipologia, trig-
dbcmptlevel, come: ger di tipo instead of), può comunque essere
utilizzata per prevenire modifiche o cancellazioni
EXEC sp_dbcmptlevel @dbName =’Northwind’ di tabelle, come nell’esempio seguente:

Quindi, se utilizziamo per la nostra prova il USE dbTest


database Northwind importato da una versio- go
ne precedente, dobbiamo portare il suo livel- -- Creazione trigger su drop table
lo di compatibilità a 90 (Figura 4): CREATE TRIGGER trDeleteTable
ON DATABASE
USE [master] FOR DROP_table
GO AS
EXEC dbo.sp_dbcmptlevel @dbname=N’Northwind’, PRINT ‘Impossibile cancellare la tabella!’
@new_cmptlevel=90 ROLLBACK
GO GO
-- Se proviamo la drop table:
e poi provare l’operatore: DROP TABLE tabTest

USE Northwind /*
Questo il messaggio che riceviamo:
SELECT EmployeeID, [1996] as Y1, [1997] as Y2
from Impossibile cancellare la tabella!
(select 1 as num, year(orderDate) as Anno, EmployeeID Msg 3609, Level 16, State 2, Line 1
from orders) o Transaction ended in trigger. Batch has been aborted.
PIVOT */
(count (num) for Anno IN ([1996],[1997])
) as pvt Gestione degli errori, come per i linguaggi del
order by EmployeeID Framework .Net, a blocchi try … catch

N. 63 - Maggio/Giugno 2005 VBJ 39


DATABASE

tabase con reco-


very model impo-
stato a full): con-
sente di mante-
nere aggiornato
un secondo ser-
ver. In caso di
caduta del ser-
ver di produzio-
ne, le applicazio-
ni sono in grado
di riconnettersi al
secondo server.

• Database snap-
shot (disponibi-
le solo nella ver-
sione enterprise):
consente di effet-
tuare un’istanta-
nea, in sola lettu-
ra, dei dati, idea-
le per essere uti-
lizzata in soluzio-
ni di reportistica.
Figura 4 Proprietà e opzioni del database
• Data partitio-
ning: consente
di effettuare split
BEGIN TRANSACTION; di tabelle di grosse dimensioni, aumentan-
GO do performance e semplificando le opera-
zioni di manutenzione.
BEGIN TRY
-- Generiamo un errore: Conclusioni
SELECT 4/0 Le novità e le migliorie non finiscono certa-
print ‘tutto ok’ mente con l’elenco e la panoramica esposta
END TRY nell’articolo. SQL Server 2005 aggiunge alla
BEGIN CATCH versione precedente molte funzionalità in gra-
print ‘errore’ do di rendere migliore la vita a sviluppatori ed
END CATCH amministratori di database: programmabilità,
GO reportistica, soluzioni di fault tolerance e disa-
ster recovery, supporto ai device mobili, XML,
ROLLBACK TRANSACTION; XML schema, XQuery, Web Service, Notifica-
GO tion Services …
Intanto abbiamo cominciato a presentare ed a
Nell’esempio appena riportato, all’interno del conoscere alcuni dei principali attori tra quelli che
blocco try, si genera un’eccezione che viene entreranno in scena. Ma lo spettacolo, signori,
correttamente gestita dal blocco catch. deve ancora cominciare. E se il trailer già vi ten-
Viene riscritto il modello di trasformazione dati ta, la pellicola sarà ancora più interessante.
(ex DTS) in SQL Server Integration Services.
Chiudiamo la presentazione con altre tre impor- Riferimenti
tanti novità legate ai database ed ai loro dati: [1] http://www.microsoft.com/sql/2005/
default.asp
• Database mirroring (disponibile solo con da- [2] newsgroup: microsoft.public.it.sql

40 VBJ N. 63 - Maggio/Giugno 2005


DATABASE

Log delle transazioni


mediante trigger
In particolari contesti, è utile che l’applicazione software garantisca una risposta a
domande del tipo: “Chi ha modificato il tale attributo della tale tabella, e quando ciò è
avvenuto?”. Un log delle transazioni garantisce una risposta adeguata a tali esigenze.

di Francesco Quaratino

U
n database OLTP (On-Line Transaction Proces- ricamente all’utente, che ha fatto
sing), per sua natura, registra le transazioni non scaturire una cancellazione piut-
conservando memoria alcuna dei cambiamen- tosto che un aggiornamento o un
ti avvenuti nel tempo. inserimento. Un tale sistema di log
può essere implementato sia a li-
vello di applicazione che a livello
di database.
In determinate situazioni, assu- Questo articolo propone una ri-
me un’importanza particolare sposta a questa esigenza, con
una soluzione a livello di databa-
la possibilità di risalire al mo- se implementata in SQL Server
mento esatto e all’utente che 2000 mediante l’uso di trigger.

ha fatto scaturire una cancella- Fattori di rischio


Progettare una soluzione di log
zione piuttosto che un aggior- che registri le transazioni in un da-
namento o un inserimento tabase piuttosto che in un formato
testo o XML, pone il progettista del
sistema di fronte ad alcuni fattori la
cui analisi preventiva può risultare
Non è possibile quindi tracciare la storia di un’entità fondamentale per la sua buona riu-
del database, da cui emergano informazioni circa i mu- scita. Registrare ogni cambiamento
tamenti dei suoi dati nel tempo e ad opera di chi essi avvenuto nell’arco di vita di una o
siano avvenuti. Intendo riferirmi, quindi, ad una vera più entità di un database operazio-
e propria operazione di logging attraverso cui risalire, nale, implica il far fronte a costi di
mediante semplici interrogazioni, allo stato di un’enti- manutenzione delle procedure sof-
tà di database, incluso l’utente di database che lo ha tware realizzate a tale scopo - sia a
determinato e le sue coordinate temporali. È possibi- livello di applicazione che a livello
le imbattersi in diverse situazioni in cui assume un’im- di database -, come anche a mag-
portanza particolare, e talvolta cruciale, la possibilità di giori costi di manutenzione dei da-
risalire al momento esatto e all’individuo, o più gene- tabase coinvolti e di ottimizzazione
delle performance - si pensi, per
esempio, alla memoria su disco ne-
Francesco Quaratino è consulente in ambito di progettazio-
ne e amministrazione di database OLTP e OLAP, oltre che di
cessaria ad ospitare i dati di log e
applicazioni software orientati ai dati. È certificato MCDBA e al fatto che ad ogni operazione di
sviluppa in VB6, ASP, VB.NET e ASP.NET. Può essere contatto inserimento/modifica/cancellazio-
all’indirizzo e-mail: q
f uaratino@infomedia.it ne nel database operazionale ne

N. 63 - Maggio/Giugno 2005 VBJ 41


DATABASE

corrisponde una nel database di log.


Sarà necessario valutare l’impatto della proce-
dura di log sulle performance del database ope-
razionale, ed eventualmente considerare una pro-
cedura di storicizzazione o di aggregazione dei
dati di log i quali potrebbero raggiungere dimen-
sioni su disco considerevoli. Una soluzione che
prevede un database come repository dei dati di
log - come quella proposta in questo articolo -, fa
nascere problematiche simili a quelle che scaturi-
scono nella progettazione dei più comuni databa-
se OLTP, perché sarà soggetto a frequenti scrittu-
re. Mi riferisco, per esempio, alla scelta dei campi
da indicizzare, che in un database OLTP privilegia
i dati il cui tipo occupa quanto meno spazio pos-
sibile, allo scopo di rendere più efficienti le ope-
razioni di scrittura; questo perché in un sistema Figura 1 Tabella del database di esempio

di registrazione delle transazioni saranno di gran

Listato 1 Script di creazione delle tabelle per lunga più numerose le operazioni di scrittura ri-
ospitare il log di [Products] spetto a quelle di lettura. Per lo stesso motivo, la
creazione di un qualsiasi indice sarà il risultato di
una scelta oculata e più che giustificata, e nella
USE NorthwindLog
GO manutenzione degli indici si imposterà un FILL-
FACTOR (fattore di riempimento) ragionevolmen-
CREATE TABLE [dbo].[Products_InsertedDeletedLog] ( te basso. A questo proposito, ricordo che tanto
[PKey] [int] IDENTITY (1, 1) PRIMARY KEY CLUSTERED,
[ProductID] [int] NOT NULL,
più il fillfactor di un indice - sia esso clustered o
[InsertUser] [nvarchar] (256) NOT NULL, meno - è prossimo al 100% tanto meno spazio
[InsertTime] [datetime] NOT NULL, libero viene riservato nelle pagine di dati dell’in-
[DeleteUser] [nvarchar] (256) NULL, dice per i futuri inserimenti. Un valore alto di fill-
[DeleteTime] [datetime] NULL,
[UniqueID] [uniqueidentifier] NOT NULL )
factor causa frequenti split dei dati dell’indice che
GO incidono negativamente sui tempi di esecuzione
di operazioni di scrittura. Per impostare il valore
CREATE TABLE [dbo].[Products_UpdatedLog] ( di riempimento basta eseguire il comando di rico-
[PKey] [int] IDENTITY (1, 1) PRIMARY KEY CLUSTERED,
[FKey] [int] NOT NULL, struzione degli indici (DBCC DBREINDEX) speci-
[ProductID] [int] NOT NULL, ficando il nome del database e opzionalmente il
[ProductName] [nvarchar] (40), nome dell’indice specifico, per esempio:
[SupplierID] [int],
[CategoryID] [int],
[QuantityPerUnit] [nvarchar] (20), DBCC DBREINDEX (‘MyDB’, my_index_name, 65)
[UnitPrice] [money],
[UnitsInStock] [smallint], È importante notare che il valore del fillfactor,
[UnitsOnOrder] [smallint],
così come lo stato di frammentazione di un indi-
[ReorderLevel] [smallint],
[Discontinued] [bit], ce, si altera col tempo e si ristabilisce unicamente
[UpdateUser] [nvarchar] (256) NOT NULL, con la ricostruzione dell’indice stesso.
[UpdateTime] [datetime] NOT NULL ) Per approfondire queste ad altre considerazioni
GO
circa la progettazione degli indici di SQL Server
CREATE INDEX [IX_ProductID] 2000, rimando all’ottimo eBook disponibile gra-
ON [dbo].[Products_InsertedDeletedLog]([ProductID]) tuitamente per il download dal sito [1].
GO

CREATE INDEX [FK_FKey]


Un’architettura possibile
ON [dbo].[Products_UpdatedLog]([FKey]) Supponiamo di voler tracciare il log della tabella
GO [Products] del database di esempio [Northwind]
(Figura 1) e di volerlo fare in un database diverso

42 VBJ N. 63 - Maggio/Giugno 2005


DATABASE

da quello operazionale - quest’ultima scelta po- te di database e la data e ora dell’inserimento del
trebbe avere diverse motivazioni che sono fuo- prodotto, e [DeletedUser] e [DeletedDate], rispet-
ri dallo scopo di questo articolo, in cui intendo, tivamente l’utente di database e la data e ora del-
comunque, dimostrare la sua fattibilità. Innan- la cancellazione del prodotto.
zitutto, creiamo un nuovo database [Northwin-
dLog] e disegniamo le tabelle che ospiteranno
il log della tabella [Products] (Listato 1): la [Pro-
ducts_InsertedDeletedLog] che registrerà la na-
I trigger sono utilizzati per
scita e morte del prodotto (eventi che coinci- mantenere integri i dati in
dono con l’inserimento e la cancellazione) e la
[Products_UpdatedLog] che registrerà invece i database normalizzati e non,
cambiamenti avvenuti durante la vita del prodot- o per implementare logiche
to (che coincidono con l’inserimento e gli aggior-
namenti) (Figura 2). Analizziamo in dettaglio la applicative molto complesse
struttura delle due tabelle e la relazione che le
lega. [Products_InsertedDeletedLog] presenta la
chiave primaria surrogata [PKey] - comodamente
autogestita attraverso l’autoincremento del tipo Vi è un ultimo campo [UniqueID] di tipo UNI-
di dato IDENTITY -, il [ProductID] che rappresen- QUEIDENTIFIER che sarà discusso opportuna-
ta la chiave primaria della tabella sorgente [Pro- mente nel seguito dell’articolo.
ducts], i campi [InsertedUser] e [InsertedDate], La chiave primaria surrogata [PKey] ha la funzio-
in cui saranno registrati rispettivamente l’uten- ne di identificare univocamente il prodotto, supe-
rando il limite rappresenta-
to dalla possibile modifica
Listato 2 Il trigger per l’inserimento del log in fase di creazione N prodotti del valore della chiave pri-
maria della tabella di cui si
intende tracciare il log.
Questo non è il caso del-
USE Northwind la tabella [Products] del no-
GO
stro esempio, la cui chiave
CREATE TRIGGER tr_insert_Products ON [dbo].[Products] primaria è di tipo IDENTI-
FOR INSERT TY, ma supponendo che
AS
[ProductName] fosse sta-
DECLARE @date datetime
BEGIN ta la chiave primaria e che il
suo valore fosse stato mo-
IF @@ROWCOUNT = 0 dificato per uno o più pro-
RETURN
dotti, il nostro log avreb-
SET @date = GETDATE() be dovuto tenerne trac-
cia considerandolo però
INSERT INTO NorthwindLog.dbo.Products_InsertedDeletedLog non come un nuovo pro-
(ProductID, InsertUser, InsertTime, UniqueID)
SELECT ProductID, USER, @date, UniqueID
dotto, bensì un prodotto
FROM Inserted già in precedenza creato
e a cui si fossero appor-
INSERT INTO NorthwindLog.dbo.[Products_UpdatedLog] tate modifiche. La tabel-
(FKey, ProductID, ProductName, SupplierID, CategoryID,
QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, la [Products_UpdatedLog]
ReorderLevel, Discontinued, UpdateUser, UpdateTime) presenta tutti i campi della
SELECT tabella [Products] con l’ag-
IDL.PKey, I.ProductID, I.ProductName, I.SupplierID, I.CategoryID, giunta di una chiave prima-
I.QuantityPerUnit, I.UnitPrice, I.UnitsInStock, I.UnitsOnOrder,
I.ReorderLevel, I.Discontinued, USER, @date ria [PKey] di tipo IDENTITY,
FROM Inserted AS I INNER JOIN NorthwindLog.dbo.Products_InsertedDeletedLog AS IDL una chiave esterna [FKey]
ON I.UniqueID = IDL.UniqueID alla chiave primaria [PKey]
di [Products_InsertedDele-
END
GO tedLog], i campi [UpdateU-
ser] e [UpdateTime] in cui

N. 63 - Maggio/Giugno 2005 VBJ 43


DATABASE

saranno registrati l’utente


di database e la data e l’ora Listato 3 Il trigger per l’inserimento del log in fase di aggiornamento di N
prodotti
dell’inserimento/aggiorna-
mento. Quindi, per la buo-
na riuscita dell’operazio- CREATE TRIGGER tr_update_Products ON [dbo].[Products]
ne di logging, ecco quan- FOR UPDATE
AS
to deve avvenire in sintesi:
DECLARE @date datetime
per ogni prodotto inserito BEGIN
in [Produtcs], si crea una
riga in [Products_Inserted- IF @@ROWCOUNT = 0
RETURN
DeletedLog] che ne registra
i dati di nascita (chiave pri- SET @date = GETDATE()
maria del prodotto, utente
e data inserimento), con INSERT INTO NorthwindLog.dbo.[Products_UpdatedLog]
(FKey, ProductID, ProductName, SupplierID, CategoryID,
una chiave primaria surro- QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
gata; in [Products_Update- ReorderLevel, Discontinued, UpdateUser, UpdateTime)
dLog] si inserisce una riga SELECT
che riporta lo stato di ogni IDL.PKey, I.ProductID, I.ProductName, I.SupplierID, I.CategoryID,
I.QuantityPerUnit, I.UnitPrice, I.UnitsInStock, I.UnitsOnOrder,
singolo campo nell’ope- I.ReorderLevel, I.Discontinued, USER, @date
razione di inserimento; le FROM Inserted AS I INNER JOIN NorthwindLog.dbo.Products_InsertedDeletedLog AS IDL
eventuali successive mo- ON I.UniqueID = IDL.UniqueID
difiche a uno qualsiasi dei
END
campi di [Products], produ- GO
cono l’inserimento di una
riga in [Products_Update-
dLog] che conserva la relazione con la [Products_ FROM [Products2004]
InsertedDeletedLog] attraverso la chiave esterna
[FKey]; infine, la cancellazione di un prodotto in In un trigger AFTER INSERT sulla tabella [Pro-
[Products] comporta l’aggiornamento dei campi ducts], la pseudo-tabella Inserted è costituita da
[DeletedUser] e [DeletedDate] della riga di [Pro- più righe risultanti dalla SELECT. In questo caso,
duct_InsertedDeletedLog. non è possibile risalire al valore del campo [PKey]
autogeneratosi con incremento automatico, poi-
ché la pseudo-tabella Inserted è un insieme non
La chiave primaria surrogata ordinato di righe (come ogni altra tabella di un
database relazionale). Per il nostro trigger, cono-
ha lo scopo di superare il scere il valore assegnato ad ogni [PKey] inserito,
è fondamentale al fine di stabilire una relazione
limite derivante dalla possi- tra [Products_InsertedDeletedLog] e [Products_
bile modifica del valore della UpdatedLog] attraverso i campi [PKey] e [FKey].
Il problema è stato risolto aggiungendo il campo
chiave primaria della tabella [UniqueID] di tipo UNIQUEIDENTIFIER nella tabel-
di cui tracciare il log la di origine, con un vincolo di DEFAULT che ne
imposta il valore attraverso la funzione NEWID(),
il quale genera un identificatore univoco globale
(GUID, Globally Unique Identifier):
Usare i trigger
Prima di analizzare i trigger creati per imple- ALTER TABLE [Northwind].[dbo].[Products]
mentare il sistema di log, è opportuno analizza- ADD UniqueID UNIQUEIDENTIFIER DEFAULT(NEWID())
re un problema, alla cui soluzione si è solo ac- GO
cennato, circa la possibilità di effettuare un in-
serimento di massa, per esempio: Più semplicemente si potrebbe usare un sempli-
ce tipo IDENTITY con autoincremento, ma la scel-
INSERT INTO [Products] (ProductName, QuantityPerUnit, UnitPrice) ta è caduta sulla prima soluzione per rendere più
SELECT ProductName, QuantityPerUnit, UnitPrice chiara la distinzione tra il campo [UniqueID] e

44 VBJ N. 63 - Maggio/Giugno 2005


DATABASE

[ProductID]. Il Listato 2
mostra il trigger AFTER
INSERT che alimenta il
database di log duran-
te la fase di creazione
di un nuovo prodotto.
In questo modo, per
ogni nuovo prodotto
si ha un identificatore
univoco rappresentato
dal campo [UniqueID]
che consente di stabi-
lire una relazione tra le
due pseudo-tabelle De-
leted e Inserted nel trig- Figura 2 Le nuove tabelle create
ger AFTER UPDATE (Li-
stato 3). In esso, si noti
come la JOIN tra Dele-
ted e [Products_Inser- AS
tedDeletedLog] sia costruita sui due campi SELECT TOP 100 PERCENT
[UniqueID] delle rispettive tabelle. Per finire, il P_IDL.ProductID AS FirstProductID, P_UL.*,
trigger AFTER DELETE (Listato 4) produce un InsertUser, InsertTime, DeleteUser, DeleteTime
aggiornamento dei campi [DeleteUser] e [De- FROM dbo.Products_InsertedDeletedLog P_IDL
leteTime] della riga di [Products_InsertedDe- INNER JOIN dbo.Products_UpdatedLog P_UL
letedLog]. Una vista sul database consente di ON P_IDL.PKey = P_UL.FKey
leggere i dati del log, ottenendo per ogni riga ORDER BY P_UL.FKey, P_UL.PKey
tutte le informazioni utili: data di inserimento,
aggiornamento e cancellazione, oltre che lo Conclusioni
stato di ogni singolo campo nell’ambito di una L’idea di partenza era quella di avere in tempo
operazione di trattamento dei dati. reale informazioni sullo stato di un’entità del da-
tabase. Per realizzarla si è pensato all’uso degli
CREATE VIEW dbo.[ProductsLog_VIEW] AFTER TRIGGER, i quali sono solitamente utiliz-
zati per mantenere integri i dati in database nor-
malizzati e non, o per implementare logiche appli-
Listato 4 Il trigger per l’inserimento del log in cative particolarmente complesse [2] [3]. Nel caso
fase di eliminazione di N prodotti
affrontato in questo articolo i trigger si sono dimo-
strati – ancora una volta - un approccio vincente
CREATE TRIGGER tr_delete_Products ON alla manutenzione dei dati. Personalmente ritengo
[dbo].[Products] che i trigger siano uno strumento molto versatile,
FOR DELETE ma da usare con parsimonia poiché inducono ad
AS
DECLARE @date datetime una naturale proliferazione di procedure di cui è
BEGIN facile perdere il controllo. Inoltre, la loro particola-
re natura di procedure scatenate in background,
IF @@ROWCOUNT = 0 talvolta rende il loro comportamento inaspettato
RETURN
agli occhi di un DBA un po’ distratto.
SET @date = GETDATE()
Bibliografia
UPDATE IDL
[1] D. Jones – “The definitive guide to:
SET DeleteUser = USER, DeleteTime = GETDATE()
FROM Deleted As D INNER JOIN NorthwindLog.dbo.Products_ SQL Server performance optimization”,
InsertedDeletedLog AS IDL Realtimepublishers.com, 2003
ON D.UniqueID = IDL.UniqueID [2] D. Esposito – “Dati integri e controllati con
END
i trigger”, VBJ N.59, 2004
GO [3] F. Quaratino – “Azioni referenziali con SQL
Server 2000”, VBJ N.61, 2005

N. 63 - Maggio/Giugno 2005 VBJ 45


DATABASE

MDAC 2.8 e Windows


98: problemi
di compatibilità MDAC

In particolari casi, utilizzando MDAC 2.8 sotto Windows 98, si ottengono blocchi del siste-
ma apparentemente inspiegabili. La soluzione è l’MDAC 2.7!

di Gionata Aladino Canova


R
ecentemente, abbiamo terminato lo sviluppo di Installare Windows 98 (su un
un prodotto con Access XP, utilizzando Office pc o su una Virtual Machine)
XP Developer per distribuirlo con il runtime. Lo • Installare Office XP con Ac-
abbiamo installato al secondo cliente dei nostri (poten- cess o soltanto Access XP
ziali) svariati clienti. Il cliente in questione ha comincia- (non abbiamo provato con
to a chiamare riferendoci di errori per noi atipici. Dopo Office 2000 o 2003)
diverse indagini infruttuose, ci siamo rivolti al suppor- • Installare l’MDAC 2.8
to tecnico di Microsoft, che ha cominciato a lavora- • Installare la stampante Xe-
re sul caso. Nel frattempo, abbiamo portato avanti le rox DocuPrint N17 PS3 o
nostre prove, che ci hanno condotto all’individuazione Brother HL 1450 o Samsung
precisa del problema. Windows 98, in combinazione ML-1520 (solo su un pc reale,
con alcune stampanti, se l’MDAC 2.8 è installato e se poiché è USB); i driver rela-
viene utilizzato il VBA, produce svariati errori, alcuni tivi sono reperibili sui siti dei
dei quali visibili nella Figura 1. Precisiamo che le in- produttori.
formazioni che troverete in questo articolo sono frut-
to di nostri studi, poiché di documentazione ne esiste Avviare Access e seguire i passi:
veramente poca, quindi potrebbero contenere inesat-
tezze. Ma vediamo i fatti in dettaglio. • Creare un nuovo database
• Creare un report ed aggiun-
I passi per riprodurre il problema gervi un’etichetta con scritto
Il problema è stato rilevato sia su macchine fisiche qualsiasi cosa; salvarlo con il
che su macchine virtuali, create sotto Microsoft Vir- nome “Report1”.
tual PC. Per riprodurlo, seguire i passi successivi: • Creare un modulo con il codice

Function StampaReport()
DoCmd.OpenReport “Report1”, acViewNormal
End Function
Gionata Aladino Canova programma dai bei tempi del
Sinclair Spectrum. Laureato in Informatica, è titolare della
Aladino Informatica e socio di TDE Informatica srl. Sviluppa • Creare un nuovo pannello
con Microsoft Access, VB.NET e realizza siti in ASP/ASP comandi da Strumenti \ Uti-
.NET. Può essere contattato tramite e-mail all’indirizzo lità Database \ Gestione pan-
info@aladinoinformatica.it nello comandi

46 VBJ N. 63 - Maggio/Giugno 2005


DATABASE

Figura 1 Errori causati dall’accoppiata Windows 98 e MDAC 2.8 con talune stampanti

• Creare un sottomenu con una voce che ri- 2147417848 (80010108): Metodo ‘Open’ del-
porti al menu principale l’oggetto ‘_Recordset’ non riuscito. Insistendo
• Creare nel menu principale, una voce che ese- con le prove, in alcuni casi si verificano errori
gua il codice StampaReport che chiudono brutalmente Access o, addirittu-
• Creare nel menu principale un richiamo per ra, schermate blu.
il sottomenu Se adesso installate un’altra stampante, con
driver forniti insieme a Windows 98, la impo-
Adesso, aprite il pannello dei comandi. Pre- state come predefinita e riprovate ad utilizza-
mendo in sequenza il pulsante di stampa e poi re il database, tutto dovrebbe funzionare rego-
quello per il cambio di menu, compariranno i larmente.
primi errori. In ordine di probabilità, il primo er- Sul sito FTP di Infomedia potete reperire un file
rore a verificarsi dovrebbe essere un Errore ese- già pronto per effettuare le stesse prove.
guendo il comando; inserendo nella switchboard
un gestore di errori, si vede che l’errore reale è Analisi del problema
un Error -2147417848: metodo ‘Value’ dell’og- Quando ci si trova in una situazione in cui
getto ‘_Textbox’ non riuscito. la documentazione scarseggia e non si hanno
Cercando sui newsgroup si trova molto poco. punti di riferimento per procedere, una tecnica
Chiudendo e riaprendo il pannello dei coman- utile è il divide et impera. Si comincia ad elimi-
di, potreste ottenere un Errore di run-time ‘- nare tutto ciò che si può; quando il problema

N. 63 - Maggio/Giugno 2005 VBJ 47


DATABASE

non si presenta più, forse si ha qualcosa su cui Sviluppare e distribuire


lavorare. Con questo approccio siamo arriva- con diverse versioni di MDAC
ti ad isolare i componenti minimi che scatena- Si pone però un problema. Se, per sviluppa-
no il problema. re, si utilizza l’ultima versione di MDAC, la 2.8,
Purtroppo non siamo riusciti a trovare nes- si ha il problema di doverla cambiare prima di
sun fattore comune tra i driver che causano distribuire il pacchetto.
problemi e nessun fattore comune tra quel- Infatti, copiando un file .mdb che ha riferimenti
li che invece funzionano. Infatti, alcuni driver all’MDAC 2.8 in un ambiente dove sia installata
scaricati da internet scatenano il problema, al- la versione 2.7, otterremo l’errore Il database o
tri no, mentre tutti quelli forniti con Windows il progetto di Microsoft Access include un rife-
98 che abbiamo provato, sembrano funziona- rimento mancante o errato al file ‘msado15.dll’
re regolarmente. versione 2.8. Vediamo le strade percorribili.
Avendo ristretto il problema all’MDAC 2.8, Se utilizzo solo l’ADO e non l’ADOX, posso,
abbiamo ricontattato il supporto tecnico. Pur- nel sistema di sviluppo, selezionare l’ADO 2.7
troppo, quando anche loro hanno riprodotto il al posto del 2.8.
problema, al momento di scalare al supporto Il database portato sotto Windows 98 sembra
di livello superiore, sono stati fermati poiché funzionare correttamente.
Windows 98 non è più supportato. Tra le va- Se, oltre all’ADO utilizzo anche l’ADOX, il pro-
rie prove, abbiamo condotto un test anche su blema è più complesso.
Windows ME e sembra che il problema non Infatti, quando inserisco un riferimento al-
si presenti. l’ADOX, non potendone selezionare la versio-
ne, il VBA prende la più recente.
Ossia: se ho installato l’MDAC 2.8, seleziono
l’ADO 2.7 e l’ADOX relativo, chiudendo e ria-
Il testing può solo prendo la dialog dei riferimenti, scoprirò che
mostrare la presenza la versione in uso è la 2.7 per l’ADO ma la 2.8
per l’ADOX.
di errori, non la Questo fatto può essere verificato anche tra-
mite un ciclo sulll’insieme References, con la
loro assenza routine

Sub StampaVersioniRiferimenti()
Dim i As Integer
Soluzione del problema For i = 1 To References.Count
Ovviamente la soluzione banale è quella di ag- Debug.Print References(i).Name & “=” &
giornare il sistema operativo. References(i).Major & “.” & References(i).Minor
La realtà è che molti clienti non digeriscono Next
questo fatto. End Sub
Quindi abbiamo provato con l’MDAC 2.7 e
questa strada sembra funzionare. Vediamo i Compilando il database e spostandolo sotto
passi da seguire: Windows 98, non otterremo errori per l’ADO
ma otterremo l’errore Il database o il proget-
1. Se su un PC è già installato l’MDAC 2.8, to di Microsoft Access include un riferimento
dobbiamo procedere alla sua disinstallazio- mancante o errato al file ‘msadox.dll’ versione
ne. Leggendo [1] scopriamo che il fatto che 2.8. In effetti, il riferimento è corretto, solo la
questa operazione vada a buon fine, è tut- versione è errata.
t’altro che scontato. Per disinstallare, dopo La soluzione migliore sembra essere di svi-
aver aperto un prompt, passiamo nella car- luppare con ADO 2.8 e poi copiare il file in
tella C:\Programmi\File comuni\Microsoft un pc con Windows 98 e MDAC 2.7, seguen-
Shared\dasetup e lanciamo il comando da- do i passi:
setup /q. Per eventuali problemi di disinstal-
lazione, consultare [1] • Copio il file sotto Windows 98
2. Scaricare ed eseguire l’installazione del- • Nell’apposita finestra tolgo i riferimenti al-
l’MDAC 2.7, reperibile su [2]. l’ADO e all’ADOX; la chiudo.

48 VBJ N. 63 - Maggio/Giugno 2005


DATABASE

• Riapro la finestra ed aggiungo i riferimenti e, tramite il comando Strumenti \ SourceSafe


all’ADO 2.7 e all’ADOX 2.7 \ Create Database From SourceSafe Project...
• Compilo il database si ricrea il file ex-novo.
• Riporto l’MDB sul pc di sviluppo per la di- A questo punto, senza compilarlo, lo si spo-
stribuzione. sta sotto Windows 98 e si procede come già
detto. Il file così creato sembra che abbia tut-
Problemi di riferimenti errati to il codice in stato di decompilato.
Purtroppo, agendo nel modo anzidetto, si Il problema non si pone, infine, se utilizzate
può verificare un ulteriore problema. Access, un file MDE. Infatti, in questo caso, nel nuovo
ogni volta che compila un oggetto, si memo- file che viene creato, il codice viene ricompila-
rizza il codice compilato. In alcuni casi è pos- to per intero.
sibile che quel codice abbia dei riferimenti non
validi. A quel punto si possono ottenere gli er- Collaudi finali
rori più disparati. Uno classico e visibile è ve- La nostra applicazione è formata da un file
dere una casella di testo di una maschera o di di dati, dall’applicazione e dalla libreria in for-
un report, alla quale è associata un’espressio- mato .mde.
ne tipo =Date(), che visualizza, invece del valo- Abbiamo ricompilato libreria ed applicazio-
re, la scritta #Nome?. Cercando sui gruppi con ne sotto Windows 98 e MDAC 2.7. Il risulta-
“decompile access problemi” o “decompile ac- to lo abbiamo riportato sotto Windows XP, nel
cess problems” troverete comunque molta do- pacchetto creato in precedenza. Il compilatore,
cumentazione. pur sfruttando ADO 2.7 e ADOX 2.8, pare tol-
Ovviamente, più il database è complesso, più lerare la situazione. (A tal proposito, se a qual-
è facile che si verifichi il problema. Ad esempio, cuno fosse sfuggito, esiste un aggiornamento
noi sviluppiamo utilizzando una libreria .mde non automatico per Office XP Dev che risolve
aggiuntiva e notiamo con una certa frequenza tra l’altro alcuni problemi di installazione sot-
problemi del genere. to Windows 98 – vedi [4] e l’SP1 per Office XP
Le soluzioni, sono ancora una volta, molteplici: – vedi [5]).
si può provare ad ovviare con il comando Abbiamo poi provato ad installare il pacchet-
to sotto una macchina virtuale con Windows
C:\...\MSACCESS.EXE <nomefile>.mdb /decompile 98 appena installato, avendo cura di installarvi
prima l’MDAC 2.7. Lo abbiamo anche provato
che decompila il file. Ossia, mette tutti i mo- sotto Windows ME e XP. I collaudi non hanno
duli in stato di non compilato. A questo pun- fatto rilevare alcun problema anche se, si sa,
to si ricompila il tutto. Purtroppo anche que- che il testing può solo mostrare la presenza di
sto approccio può causare problemi. In alcu- errori, non la loro assenza.
ni casi, ma non siamo mai riusciti a riprodurre
un procedimento, abbiamo perso alcune mo- Riferimenti
difiche fatte al codice. Per altri problemi cono- [1] 311720 PRB: Il rollback di MDAC potrebbe
sciuti, vedere [3]. non riuscire in Windows 95, Windows 98 e
Windows Millennium Edition
http://support.microsoft.com/kb/311720/
[2] Download MDAC 2.7 http://tinyurl.com/fyzg
una tecnica oppure http://msdn.microsoft.com/data/
downloads/ e cercare MDAC 2.7
utile è il [3] Subject: INFO: The real deal on the /
"divide et impera" Decompile switch http://trigeminal.com/
usenet/usenet004.asp
[4] OFFXPDEV: Microsoft Office XP Developer
Packaging Wizard Patch Available on MSDN
Un approccio che pare funzionare, se si uti- h t t p : / / s u p p o r t . m i c r o s o f t . c o m/
lizza Visual Source Safe, è quello di rigenerare default.aspx?scid=kb;en-us;Q305003
completamente il database. In pratica, una vol- [5] OFFXPDEV: Download e installazione di Of-
ta effettuate tutte le modifiche, si archivia il file fice XP Developer Service Pack 1 (SP-1)
in Visual Source Safe, si cancella il file in locale http://support.microsoft.com/kb/313166/it

N. 63 - Maggio/Giugno 2005 VBJ 49


PRODOTTI

VBdocman
Documentazione
automatizzata del codice
La documentazione del codice semplificata

di Fabio Perrone

L
a documentazione tecnica di un progetto ri- avanzato e facilmente leggibile:
veste un aspetto fondamentale; è sufficien- in questo caso risulta utile ricor-
te pensare a coloro che scrivono librerie di rere a strumenti come VBdoc-
codice distribuibili a terzi o a chi lavora in team: man della slovacca Helixoft.
è sempre la parte più aggiornata di un proget- VBdocman è un add-in per Vi-
to, a differenza magari dei requisiti o dell’anali- sual Studio .NET, e con l’instal-
si di dettaglio. lazione viene aggiunta un’ico-
na sulla toolbar per un acces-
so rapido, e una voce di menù
sotto Tools.
VBdocman presenta È importante notare che la
senza alcuna ombra documentazione può essere
creata in diversi formati: HTML
di dubbio caratteristiche Help 1.x (file con estensione
di completezza .chm), Help 2 (file con esten-
sione *.HxS, la più recente tec-
ed efficienza nologia Microsoft per la docu-
mentazione, ampiamente uti-
lizzata in Visual Studio .NET),
file HTML puri (contenenti solo
Chi utilizza C# può già servirsi dei commenti XML HTML e Java in modo da distri-
all’interno del proprio codice sorgente, caratteri- buire la documentazione imme-
stica che per i programmatori Visual Basic.NET diatamente su un sito Web), file
sarà presente solo dalla versione 2005 di Visual rtf e file XML.
Studio.NET. Tuttavia, la documentazione XML da Se si desidera risparmiare tem-
sola non fornisce un livello d’interfaccia utente po senza scrivere nessun com-
mento all’interno del codice, è
possibile far sì che VBdocman
crei in automatico la docu-
mentazione grazie all’attivazio-
Fabio Perrone si è laureato in matematica e MCP in Visual Ba-
sic, lavora presso TSF s.p.a. dove si occupa di progettazione e ne dell’opzione “Compile also
sviluppo di applicazioni Windows e Web. Può essere contattato non-commented members”,
tramite e-mail all’indirizzo fperrone@programmers.net. che permette di generare i file

50 VBJ N. 63 - Maggio/Giugno 2005


PRODOTTI

altri membri,
impostazioni
dei parametri o
altro, dal menu
contestuale
menzionato in
precedenza si
può scegliere
“Comment edi-
tor”: avremo a
disposizione un
vero e proprio
editor XML con
il quale creare
tag XML avan-
zati che sem-
plificheranno la
creazione dei
commenti.
VBdocman
prevede l’utiliz-
zo di commenti
Figura 1 Schermata introduttiva delle opzioni nativi “@-style”:
sono commenti
VB classici con
alcune caratte-
necessari alla documentazione recuperando ristiche aggiuntive, vale a dire si inizia la
le informazioni sui membri delle classi e pre- riga con il simbolo di commento di VB (‘) e
sentandoli in un formato MSDN-like, quindi poi si inseriscono istruzioni che permetto-
completo di link, elenco membri, ecc. no al compilatore della documentazione di
Come è ovvio, la documentazione così crea- identificare la porzione di codice che si sta
ta può non risultare sufficiente se si deside- commentando (@see, @param, ecc.). Per ot-
rano informazioni aggiuntive come la descri- tenere una documentazione veramente fles-
zione dei parametri passati ai metodi, link a sibile e completa, è possibile utilizzare due
eccezioni o esempi. caratteristiche avanzate del programma: i
In questo caso, è possibile utilizzare i com- template e le macro.
menti XML utilizzati già in C#, solo che le ri- I primi servono per definire l’output della
ghe che contraddistinguono i commenti stessi compilazione; sono forniti template per la
devono essere precedute da ‘ ‘ ‘ o da qualsia- generazione dei file .HxS, .chm, .rtf, .html e
si combinazione di caratteri scelta dall’uten- .xml, completamente ridefinibili in modo da
te, con la possibilità di utilizzare 5 tag XML poter personalizzare l’output; le macro sono
personalizzati oltre a quelli già presenti (tipo direttive che sono fornite al compilatore per
<summary>, <example>, <param>, ecc.). formattare l’output del testo già direttamen-
Poiché scrivere i tag XML per tutti i membri te al momento della scrittura dei commenti,
di un progetto ampio può essere un lavoro utilizzabili però solo nei commenti “@-style”.
particolarmente tedioso, VBdocman aiuta in Il notevole vantaggio offerto dalle macro è
questa operazione permettendo l’inserimen- la possibilità di utilizzare cicli o altre istru-
to automatico di commenti XML semplice- zioni proprie dei linguaggi ad alto livello per
mente selezionando la porzione di codice da la creazione di una documentazione tecnica
documentare, premendo il tasto destro del veramente professionale; lo svantaggio è che
mouse e scegliendo “Add VBdocman com- il loro apprendimento non è immediato e, al-
ment” dal menu contestuale. meno all’inizio, richiede uno studio approfon-
Per creare una documentazione più com- dito, magari esaminando i template già forniti
plessa, contenente magari riferimenti ad per comprenderne a fondo il funzionamento.

N. 63 - Maggio/Giugno 2005 VBJ 51


PRODOTTI

Per chi sviluppa


librerie distribui-
bili o controlli o
per chi lavora in
un team di la-
voro un aspet-
to fondamenta-
le riveste il co-
siddetto “Con-
text Sensitive
Help”, in altre
parole la possi-
bilità di fornire
all’utilizzatore
del codice do-
cumentato aiuto
sui singoli mem-
bri con la sem-
plice pressione
del tasto F1 po-
sizionandosi sul
membro stesso,
oppure il tooltip Figura 2 XML Comment Editor
che compare –
grazie all’Intelli-
Sense – nel mo-
mento della digitazione del codice. Ottenere menzionare un’ulteriore opzione di compila-
queste importanti funzionalità con VBdoc- zione: la possibilità di compilare una nuova
man è particolarmente semplice: è sufficien- documentazione per l’intera soluzione oppure
te attivare una check-box ed il programma far sì che ogni progetto facente parte di una
soluzione produca la propria documentazio-
ne. È ovvio che la prima possibilità è parti-
colarmente valida in soluzioni che condivido-
La documentazione XML no namespace tra di loro; la seconda è più
adatta se sono soluzioni contenenti progetti
da sola non fornisce di test per librerie distribuibili a terzi.
un livello d’interfaccia
Conclusioni
utente avanzato La presenza sul mercato di numerosi tool per
e facilmente leggibile la documentazione del codice, alcuni anche gra-
tuiti (VBCommenter), evidenziano quanto l’esi-
genza di produrre documentazione in modo
rapido, completo ed efficiente sia sempre più
sentita dalla comunità degli sviluppatori. VB-
provvederà per noi alla creazione dell’aiuto docman presenta senza alcuna ombra di dub-
contestuale. bio caratteristiche di completezza ed efficien-
Il programma si presenta in tutta la sua fles- za; per quanto riguarda la rapidità, la possibilità
sibilità nel momento dell’impostazione del- di inserire documentazione grazie ai template
le opzioni di compilazione per la creazione permette di ridurne i tempi di creazione, tutta-
della documentazione: è possibile scegliere via la compilazione di una soluzione comples-
l’accessibilità dei membri da includere nel- sa richiede una quantità di tempo abbastanza
la documentazione (membri pubblici, privati, elevata. I prezzi variano dai 143$ per chi acqui-
friend, ecc.) e quali membri includere (classi, sta da 11 a 20 licenze ai 229$ per la versione
moduli, proprietà, eventi, ecc.). Vale la pena monoutente.

52 VBJ N. 63 - Maggio/Giugno 2005


PRODOTTI

C-Sharpener
Un originale add-in per Visual Studio che consente di convertire il codice VB.NET in C#

di Lorenzo Vandoni

D
a molti anni, la scelta del linguaggio di pro- “transerror” e “transwarning”,
grammazione non è più considerata il pro- ed opportunamente evidenziati
blema principale da affrontare per lo svilup- con commenti all’interno del co-
po di un’applicazione software. dice generato.
Nell’ambito del .NET Framework, addirittura, il lin- Il risultato è costituito da un
guaggio è stato ridotto a una sorta di dialetto al nuovo progetto C#, che viene
servizio della piattaforma. automaticamente incluso all’in-
Ciononostante ci sono ancora molte situazioni in terno della soluzione, pronto per
cui la scelta del linguaggio può risultare importante. essere compilato.
Ad esempio, si potrebbe volere sfruttare del codi-
ce VB.NET in un progetto C#, oppure si vorrebbe Un piccolo test
includere un esperto programmatore VB.NET nel- La versione di valutazione usa-
lo sviluppo di un’applicazione C#, senza obbligar- ta per questa prova consente di
lo ad apprendere un nuovo linguaggio. tradurre fino a 500 linee di co-
dice, il che mi ha permesso di
Da VB.NET a C# fare alcune piccole prove di tra-
C-Sharpener permette di risolvere questi ed altri duzione con tre progetti di ri-
problemi. Si tratta di un add-in per Visual Studio, dotte dimensioni – un eseguibile
che permette di convertire automaticamente codi- Windows, una semplice DLL, e
ce VB.NET in C#. un’applicazione Internet. La tra-
Una volta installato, il programma può essere at- duzione della DLL non ha pro-
tivato dal menu Tools di Visual Studio. Il processo vocato nessun problema.
di traduzione è guidato da un wizard, e consente La traduzione dell’applicazio-
di selezionare per la traduzione uno dei progetti in- ne Internet ha dato luogo a 13
clusi nella soluzione attualmente aperta in Visual “transwarning”, relativi princi-
Studio. Possono essere impostate diverse opzio- palmente all’introduzione di ri-
ni, tra cui la possibilità di mantenere i commenti ghe di codice per l’assegna-
originali, e quella di introdurre operazioni di cast mento esplicito della gestione
esplicite ove necessarie. degli eventi, e all’introduzione
Al termine del processo di traduzione viene mo- di variabili temporanee nei ci-
strata una fi nestra di riepilogo in cui vengono cli foreach. In particolare, que-
evidenziati, tra l’altro, il numero di righe di codi- sto significa che un’istruzione
ce convertite e il numero di problemi rilevati du- VB.NET del tipo:
rante la traduzione. Questi ultimi vengono suddi-
visi in due categorie, denominate rispettivamente Private Sub Page_Init(...) Handles
MyBase.Init

viene tradotta in C# con un'as-


Lorenzo Vandoni si è laureato in Informatica a Milano nel 1990,
segnazione esplicita:
ed è uno specialista di progettazione e sviluppo con tecniche
e linguaggi object-oriented. Ha collaborato alla realizzazione di
diversi software commerciali in ambiente Windows. Può essere base.Init += new System.EventHandler
contattato tramite e-mail all’indirizzo lvandoni@infomedia.it. ( Page_Init );
private void Page_Init(...) {

N. 63 - Maggio/Giugno 2005 VBJ 53


PRODOTTI

ticolare – l’invocazione
di un costruttore della
classe base – mentre
in altri casi analoghi la
traduzione è stata effet-
tuata in modo corretto.

Limitazioni conosciute
Secondo il produttore,
C-Sharpener dovrebbe
essere in grado di tra-
durre il 99% del codi-
ce VB.NET in C#.
Probabilmente è vero,
anche se ci possono
essere molti modi con
cui questa percentua-
le potrebbe essere cal-
colata. Insieme con l’in-
stallazione viene fornito
un file PDF che riporta
Figura 1 Il wizard di C-Sharpener permette di convertire un progetto VB.NET in C#
l’elenco di tutte le limi-
tazioni conosciute, ov-
vero dei casi in cui il
e un ciclo del tipo: processo di traduzione potrebbe non funzio-
nare correttamente.
Dim oObj As MyObject Il documento è piuttosto ampio e dettaglia-
For Each oObj In MyObjects to, e costituisce una lettura interessante, an-
oObj.Function() che perché mette in evidenza molte differen-
Next ze non banali tra i due linguaggi. Sono subito
andato a cercare il caso che mi è capitato nel
viene tradotto, in modo un po’ ridondante, test, ma non vi ho trovato nessun riferimento,
con: segno che l’elenco non è del tutto esaustivo. Al
di là di questa considerazione, però, questo do-
MyObject oObj = null; cumento può risultare sicuramente utile, anche
foreach (MyObject transTemp0 in MyObjects) { perché per ogni possibile problema noto viene
oObj = transTemp0; suggerito un modo per aggirare l’ostacolo.
oObj.Update();
} Altre opzioni
Tra le opzioni che possono essere impostate
Al di là di queste piccole segnalazioni, però, durante il processo di traduzione vi è la possibi-
la traduzione è stata effettuata correttamente, e lità di mantenere i file intermedi generati duran-
ho potuto compilare ed eseguire l’applicazione te il processo di traduzione. Si tratta di file XML,
Internet senza nessun problema. che comprendono una completa analisi dei file
Qualche problema c’è stato, invece, con il pro- sorgenti, utilizzata evidentemente come passo
grammino Windows che, nonostante abbia dato intermedio per la traduzione. Anche per proget-
luogo ad un unico “transwarning”, relativo come ti semplici, come quelli utilizzati per il test, la di-
nel caso precedente all’introduzione della ge- mensione di questi file è sicuramente eccessiva
stione esplicita degli eventi, ha causato un er- per poter effettuare un’analisi superficiale, ma
rore di compilazione, dovuto al fatto che è stata trovo che aver lasciato la possibilità di accede-
“dimenticata” la parola chiave “ref” per passa- re a queste informazioni sia molto interessante,
re un parametro per riferimento, come richiesto anche perché rende potenzialmente implementa-
dalla funzione richiamata. Va detto che questa bili altri tipi di analisi e traduzioni basate su que-
“dimenticanza” è capitata in un solo caso par- sti file XML, sicuramente più semplici da tratta-

54 VBJ N. 63 - Maggio/Giugno 2005


PRODOTTI

re rispetto ai sorgenti originali. Altra funzionalità Ho trovato un po’ limitativa la possibilità di tra-
interessante è costituita dalla possibilità di lan- durre solo interi progetti, e non porzioni di co-
ciare il processo di traduzione dalla linea di co- dice, anche perché ho l’abitudine di compilare
mando. Questo permette di utilizzare il tool al- molte DLL a linea di comando, ma non credo
l’interno di elaborazioni batch, tutt’altro che in- che questa potrà essere vista da molti come
frequenti in molte aziende di sviluppo. una limitazione importante.
Anche l’errore occorso durante la traduzione
Conclusioni è piuttosto particolare, e il giudizio complessi-
Lo strumento è sicuramente interessante, vo non può che essere positivo.
e non privo di possibili applicazioni pratiche.
Tra le altre non va dimenticata la possibilità di Scheda prodotto:
portare i propri progetti VB.NET su un siste-
ma open source come Mono, che fornisce un Nome e Versione C-Sharpener
compilatore C#. Categoria Add-in
Produttore Elegance technologies
Per la valutazione: (o Distributore)
Sistema operativo Windows 2000 o superiore
Voto complessivo 4 Requisiti
Nessun particolare requisito
Funzionalità 3 hardware/software
Interfaccia e Usabilità 4 Sito Internet www.elegancetech.com
Prestazioni 4 csharpener_
e-mail
Tempestività sul mercato 4 support@elegancetech.com

N. 63 - Maggio/Giugno 2005 VBJ 55


PRODOTTI

Sharp Shooter 1.9


Non solo report: presentiamo uno dei migliori prodotti di reportistica e non solo, inte-
ramente pensato per essere integrato con .NET.

di Marco Caridi

"I
l generatore più flessibile di report per la piat- glese). Selezionato dalla libreria un
taforma .NET disponibile sul mercato!”. Que- modello tra quelli forniti con il sof-
sto è lo slogan di lancio del prodotto da par- tware o di propria personalizzazio-
te della casa americana 9Rays.NET. Si tratta di una ne, l’engine provvede a produrre i
applicazione software specializzata per la produzione report. Questo “core” applicativo
di report statistici di ogni genere. La reportistica non accede ai datastore per leggere
è argomento tra i più stuzzicanti, però questo settore e selezionare i dati e produce un
ha da sempre conservato la sua nicchia di mercato, metadato (in formato XML) pari al
traendo vitalità dalla necessità oggettiva di presenta- report desiderato. L’ultimo stadio
re, in modo facile e flessibile, risultati di operazioni sui software è costituito dal “presen-
dati. Il prodotto, già al primo impatto, sembra essere tation layer”. Grazie al concetto di
veramente di grande semplicità di uso e potenzialità. stile in connubio con XML stesso,
Completamente compatibile, o per meglio dire, “pen- il metadato è presentato all’uten-
sato” per il framework .NET, Sharp Shooter facilita te nello stile e nella forma prescel-
drasticamente la generazioni di report. ti. In particolare è possibile filtrare
È un sistema aperto, consente personalizzazioni gra- il metadato producendo un report
zie alla possibilità di estendere qualsiasi funzione già nei seguenti formati:
presente con procedure software proprietarie svilup-
pabili n VB.NET o altri linguaggi. Per esempio è possi- • (X)HTML – per una facile pub-
bile sviluppare filtri di esportazione sotto forma di Dy- blicazione web;
namic Link Libraries e definirli nell’ambiente di repor- • TESTO – per meglio trattarlo
tistica come plug-in esterni. Grazie alle sue funzioni di e trasferirlo in sistemi mono-
import ed export, per esempio, è possibile importa- tematici come Unix e similari;
re namespaces, variabili locali, procedure, controllan- • IMMAGINE – in un formato se-
do nel dettaglio l’intero processo di produzione del re- lezionabile tra moltissime op-
port, nonchè importare vecchi report generati dal tool zioni (jpg, bmp, gif, tiff…);
Crystal Reports. Uno degli effetti grafici più accattivanti • PDF – per renderlo adattato allo
è la possibilità di utilizzare formati ed orientamenti te- strumento Adobe Acrobat;
stuali e grafici differenziati nella stessa pagina del re- • RTF;
port. Il prodotto è “ovviamente” basato su una logica • altri ancora.
ad oggetti gerarchica per cui qualunque estensione ap-
plicativa può essere salvata in una libreria e riutilizzata Si è parlato di piena compati-
in applicazioni future. Entriamo nel merito dell’architet- bilità con il framework .NET, ma
tura applicativa per meglio chiarirne gli aspetti funzio- cosa implica questo per l’utente
nali. La definizione di un report è basata sul concetto esperto? È garanzia di estendi-
di modello (o template per gli estimatori della lingua in- bilità del software mediante pro-
cedure sviluppate con uno qual-
siasi dei linguaggi di scripting of-
ferti dalla piattaforma. Il modello
Marco Caridi è laureato in Ingegneria Elettronica presso la
dati gerarchico caratteristico di
Università` “La Sapienza” di Roma. Si occupa di Analisi e Svi-
luppo Software. Da diversi anni è consulente di progetto presso ADO.NET si sposa perfettamente
il centro servizi VAS di TIM in Roma. Può essere contattato con Sharp Shooter consentendo
tramite e-mail all’indirizzo mcaridi@infomedia.it. facilmente di inserire nei report i

56 VBJ N. 63 - Maggio/Giugno 2005


PRODOTTI

stesso rendendolo piacevole e facile da legge-


re. Una nota di merito riguarda la fornita raccolta
d’esempi (oltre 90) inclusa nel pacchetto softwa-
re. Esempi di personalizzazioni e sviluppo di filtri
ad hoc sia in VB.NET sia in DELPHI.NET. Ce n’è
insomma per tutti i gusti! Prima di chiudere que-
sta recensione veniamo agli aspetti commerciali.
Il prodotto può essere scelto tra quattro possibili
versioni che vanno dalla Professional alla Light.
Con la prima, la casa fornisce persino il codice
sorgente dell’applicazione! Il requisito minimo è
che il framework.NET sia installato sulla mac-
china dell’utilizzatore finale del software. Questa
breve recensione non vuole e non può sostituir-
Figura 1 Visione schematica dell'uso del prodotto si alla documentazione ufficiale alla quale si ri-
manda per approfondimenti del caso.

Scheda prodotto:
dati presi dall’oggetto. Anche ASP.NET si pre-
senta al tool con un biglietto da visita più che di Nome e Versione Report Sharp Shooter 1.9
riguardo. Infatti l’integrazione completa tra i due
Categoria Reporter
ambienti consente di creare e pubblicare facil-
Produttore
mente report su Internet Information Server. Il 9Rays.Net – www.9rays.net
(o Distributore)
tool non trascura nemmeno elementi di corredo Sistema operativo Windows
come le intestazioni di pagina, i numeri di pagi- Requisiti
na automaticamente generati, logo, e qualunque .NET
hardware/software
info desideriate visualizzare all’interno del report Prezzo A partire da 375 USD

N. 63 - Maggio/Giugno 2005 VBJ 57


ARCHITECT'S CORNER

Ottimizzare i lock
sui database
Quattro cose da ricordare con SQL Server

di Ingo Rammer

C
ome sviluppatori, talvolta tendiamo a vedere rowset (semplificando, ciò si-
i database come stupidi mezzi per memo- gnifica che il database mantie-
rizzare informazioni con un’unica responsa- ne una copia dei dati selezionati
bilità: memorizzare i dati dell’applicazione in modo per ciascun utente per tutta la
persistente e recuperarli il più rapidamente possi- durata della transazione).
bile. Una attenta attività di tuning e di profiling è Locking significa che vengono
un compito che gran parte di noi può lasciare agli creati e controllati differenti tipi
esperti di database e agli amministratori. di lock durante la durata della
Ma se ci si imbatte in problemi di timeout, dea- transazione.
dlock e prolungati lock di transazioni, un rapido Questi lock possono limitare
sguardo dietro le quinte può essere più che profi- l’accesso a un database, a una
cuo. Il principale problema dei database, e al con- tabella, a una pagina, a un in-
tempo quasi il motivo per cui esistono, è il fatto tervallo (di record o di criteri di
che più utenti possono accedere alla stessa risor- selezione) o a singoli record.
sa contemporaneamente, richiedendo operazioni La creazione e il controllo dei
sia di lettura sia di scrittura. lock dipende dal livello di isola-
Per mantenere i dati consistenti, due principali si- mento della transazione selezio-
stemi differenti si sono consolidati per i database nata, il che porta a una matri-
relazionali: l’utilizzo dei lock di database (locking) ce di compatibilità strettamen-
e il versioning dei resultset (rowset versioning). Ad te definita tra operazioni con-
esempio, SQL Server (fino alla versione 2000 com- correnti. I tipi principali di lock
presa) utilizza il primo metodo e introduce l’altro sono “S” e “X”, dove S signifi-
nella versione 2005. ca shared e X si riferisce a un
D’altro canto, i database Oracle evitano la creazio- lock esclusivo.
ne di lock di database per gli accessi a sola lettura Ad esempio, se la transazio-
(SELECT SQL) e utilizzano invece il versioning dei ne A vuole modificare gli stes-
si blocchi di informazione sotto-
posti a lock dalla transazione B,
dovrebbe attendere finché il lock
non viene rimosso. Ciò avviene
normalmente all’atto del COM-
Ingo Rammer è il fondatore di thinktecture, una compagnia MIT o del ROLLBACK.
che aiuta gli sviluppatori e gli architetti software a progettare e
implementare applicazioni e Web service .NET. Partecipa come Finora, tutto semplice...
speaker alle conferenze internazionali dedicate a tali argomenti
ed è autore del best-seller Advanced .NET Remoting (APress).
Per verificare la necessità e l’ef-
È Microsoft Regional Director per l’Austria e può essere con- fetto dei differenti tipi di lock, si
tattato tramite il sito http://www.thinktecture.com/staff/ingo. può selezionare uno dei livelli di
isolamento della transazione:

58 VBJ N. 63 - Maggio/Giugno 2005


ARCHITECT'S CORNER

• Read Committed: vengono letti i dati sotto- no una delle transazioni come vittima del dea-
posti a commit; dlock e forzano l’abort e il rollback di questa
• Read Uncommitted: vengono letti i dati delle transazione. Per la propria applicazione, ciò di
transazioni correntemente in esecuzione; solito provocherà la generazione di una ecce-
• Repeatable Read: i record interessati dalla zione che permette di riavviare la transazione. I
SELECT verranno sottoposti a lock. Per le blocchi normali (se una transazione deve sem-
altre transazioni: nessun UPDATE possibi- plicemente attendere un po’ perché un lock sia
le, solo INSERT; rimosso) sono più difficili da riconoscere poi-
• Serializable: i record e gli intervalli interessati ché incidono solo sul throughput dell’applica-
dalla SELECT verranno sottoposti a lock. Per zione – in transazioni al secondo.
le altre transazioni: nessun UPDATE possi- Consideriamo nuovamente l’esempio prece-
bile e nessun INSERT possibile nei criteri di dente: se T1 e T2 utilizzano gli oggetti A e B
selezione della clausola WHERE. nella stessa sequenza, ma T1 decide di porre
un lock su B per alcuni secondi (ad esempio,
Ma che significa? durante una transazione più grande), allora T2
In poche parole, ciò significa che i lock inutil- dovrà attendere finché T1 rilascia i lock.
mente estesi o duraturi distruggono le presta- Questa situazione è detta di blocco. Il pro-
zioni e la scalabilità delle applicazioni. blema con questi blocchi è che possono se-
Significa anche che i lock troppo piccoli di- riamente incidere sulla scalabilità dell’appli-
struggono i dati. Per garantire la stabilità del- cazione mentre si verificano talvolta su tabel-
l’applicazione, è estremamente importante che le apparentemente non importanti.
lo sviluppatore conosca il comportamento di Un problema di blocking molto comune, ad
locking del proprio database e delle proprie esempio, si ha quando una singola tabella
applicazioni. viene utilizzata come base per i valori identi-
ty o per le chiavi primarie (invece di utilizzare
Passo 1: Analizzare i deadlock e i blocchi le colonne IDENTITY di SQL Server).
In un modo o nell’altro, gran parte di noi In questi casi si può osservare una tabella,
avrà già visto (o causato) deadlock nelle ap- spesso denominata in modo simile a “COUN-
plicazioni database. TERS”, con campi come “COUNTER_NAME”
Questi deadlock vengono causati da due e “NEXT_VALUE”.
transazioni che cercano di accedere con- Questa tabella conterrà un record per cia-
temporaneamente alle stesse due risorse (o scuna tabella di dati, per cui verrà utilizzata
in effetti, agli stessi due lock) ma in ordine per fornire gli identificatori della chiave pri-
inverso. maria.
Ad esempio, se la transazione T1 pone un Prima di eseguire l’INSERT di un record in
lock sull’oggetto A e poi prova ad accedere una tabella dell’applicazione, si dovrà prima
all’oggetto B mentre, al contempo, la transa- selezionare il valore NEXT_VALUE corrente,
zione T2 pone un lock sull’oggetto B e ten- incrementarlo ed eseguire l’UPDATE della ta-
ta di accedere all’oggetto A. In questo caso, bella COUNTERS prima di eseguire l’INSERT
nessuna delle transazioni sarà in grado di effettivo.
terminare. Operazioni come queste possono avere un
Per evitare questi tipi di deadlock, di solito è effetto collaterale imprevisto: tutti gli INSERT
sufficiente far sì che tutte le applicazioni ac- verranno eseguiti serialmente in una transazio-
cedano ai dati nella stessa sequenza. Se en- ne. T2 può solo iniziare l’inserimento in qual-
trambe le transazioni T1 e T2 accedono prima siasi tabella dopo che T1 ha eseguito il com-
alla tabella A e poi alla tabella B, non provo- mit. In tal modo, si trasforma effettivamente
cheranno alcun deadlock (poiché il lock su A SQL Server in un database single-user, per-
verrà rimosso dopo che la prima transazione lomeno per quanto concerne le operazioni di
termina, in modo che la seconda transazione INSERT (per inciso: invece di seguire l’approc-
possa accedere allo stesso oggetto). Se l’ap- cio descritto, ad esempio, si possono utiliz-
plicazione deve gestire i deadlock, si è “for- zare le colonne IDENTITY in SQL Server e ef-
tunati” finché li si possono ignorare. fettuare una invocazione “SELECT SCOPE_
Tutti i sistemi di database attualmente più IDENTITY()” dopo l’operazione di INSERT se
diffusi riconoscono questi deadlock, designa- si deve accedere alla chiave primaria appena

N. 63 - Maggio/Giugno 2005 VBJ 59


ARCHITECT'S CORNER

generata. In alternativa, si possono utilizzare processo richiedesse contemporaneamente i


valori GUID generati dal client. dati (prima del COMMIT), ad esempio inviando
Se si deve realmente ricorrere a tabelle uno statement come “SELECT UnitPrice FROM
COUNTER come quella mostrata prima, può Products WHERE ProductID = 7”, ciò provo-
essere una buona idea recuperare un gruppo cherebbe il blocco del secondo processo.
di ID distinti – ad esempio 100 – in una tran- È interessante notare che ciò non sarebbe ne-
sazione separata e conservare questi ID sul cessario, poiché il campo UnitPrice non viene
client). Per identificare un comportamento di modificato dalle precedenti istruzioni UPDA-
blocco come quello descritto prima, consiglio TE. È qui che entra in gioco la caratteristica di
di familiarizzare con SQL Profiler. SQL Server di cui ho detto precedentemente.
In tal caso, si può avviare il profiler e definire Ad esempio, si può creare un indice non-uni-
un filtro come “Duration > 1000” per richiede- que, non-clustered che contiene i campi Pro-
re i dati di log di tutte le transazioni che han- ductID e UnitPrice.
no dovuto attendere più di un secondo per il In questo caso, la seconda richiesta non ver-
rilascio di un determinato lock. rebbe bloccata, poiché la query potrebbe es-
sere pienamente soddisfatta utilizzando l’indi-
ce senza dover ricercare i dati originali nella
riga sottostante. Siccome l’indice non è stato
modificato dall’aggiornamento, non verrà bloc-
Locking significa che ven- cato, pertanto la seconda richiesta può esse-
gono creati e controllati re servita immediatamente.

differenti tipi di lock durante Passo 3: Attenzione agli aggiornamenti


la durata della transazione Se seguite da un po’ di tempo la rubrica Ar-
chitect’s Corner, saprete già che non ritengo
necessariamente che i metodi di accesso a
database generati automaticamente siano una
Passo 2: Pensare come SQL Server grande idea nelle parti delle proprie applicazio-
Si può anche sfruttare una caratteristica pres- ni che devono supportare un notevole carico
soché sconosciuta del motore di SQL Server: di transazioni in un ambiente scalabile.
in gran parte dei casi SQL Server porrà un lock Un ulteriore motivo di questa convinzione è
solo su ciò che esattamente è stato modificato. il seguente: basta immaginare che il proces-
Anche se ciò sembra molto banale, in alcuni so di consegna illustrato prima non verrà ge-
casi questo unico fatto può far accrescere la stito con una semplice istruzione di UPDATE
scalabilità della propria applicazione. ma invece avverrà utilizzando un DataSet, o
Basta immaginare di avere una tabella “Pro- un O/R Mapper o un metodo simile.
ducts” che contiene, tra gli altri, i campi Pro- In questo caso, è facilmente possibile che,
ductID, UnitPrice e UnitsInStock (per inciso: dopo una prima istruzione SELECT, possa es-
combinare il livello attuale di giacenza di ma- sere generato un comando SQL come il se-
gazzino con i dati statici di un prodotto può guente: “UDPATE products SET UnitsInStock
non essere una best practice. Ma l’ho visto = 46, UnitPrice = 97 /* ... altre colonne ... */
fare abbastanza spesso, pertanto ritengo sia WHERE ProductID = 7”. In questo caso, il me-
un esempio molto valido in questo caso. Inol- todo comprende tutte le colonne nella istruzio-
tre, si tenga conto che sto utilizzando delle ne UPDATE (e non solo l’unica colonna modi-
istruzioni SQL solo per semplificare la visua- ficata che sarebbe stata sufficiente).
lizzazione. Nei sistemi reali, normalmente si L’ottimizzazione mostrata al passo 2 (che per-
vedrebbero delle query con parametri o delle metteva di utilizzare un indice separato per ac-
invocazioni a stored procedure). crescere il grado di parallelismo) non funziona
Se si utilizzasse questa tabella per registra- più in questo caso.
re una consegna effettuata da uno dei propri Statement come questo fanno sì che venga
fornitori, si eseguirebbe molto probabilmente automaticamente generato un lock per ciascun
una sequenza di statement simili a “UDPATE indice nelle righe interessate e perciò influisce
products SET UnitsInStock = UnitsInStock + in modo negativo sulla scalabilità dell’applica-
10 WHERE ProductID = 7”. Se un ulteriore zione anche quando non sarebbe necessario.

60 VBJ N. 63 - Maggio/Giugno 2005


ARCHITECT'S CORNER

Step 4: Suggerimenti di locking come ul- che conoscere il comportamento del locking, e
tima risorsa le relative conseguenze, negli scenari di utilizzo
Fino alla versione 6.5 di SQL Server, il lock concorrente. Ovviamente, nello spazio dedica-
più piccolo possibile era a livello di pagina di to a questa rubrica, ho potuto fornire solo alcu-
database che può contenere alcuni record (di ni spunti su questo argomento. Perciò suggeri-
solito, una pagina è di 4KB). sco di investire del tempo con SQL Profiler per
Dalla versione 7.0 di SQL Server, il motore del tracciare gli effetti dei differenti livelli di isola-
database decide se è meglio porre un lock a li- mento delle transazioni in differenti scenari, in
vello di pagina o a livello di record. modo da imparare a stimare il comportamento
In alcuni casi può essere perciò utile evitare di locking del proprio database.
la creazione di lock bloccanti a livello di pagi- Inoltre, vi raccomando due libri. Anche se di
na, suggerendo esplicitamente a SQL Server di solito sono considerati letteratura per ammini-
utilizzare lock a livello di record. stratori di sistema, credo realmente che ogni
Si può farlo utilizzando il suffisso “with sviluppatore di applicazioni database critiche
(ROWLOCK)” come in questo caso: “UDPATE debba leggere o utilizzare come riferimento i
products WITH (ROWLOCK) SET UnitsInStock testi [1] e [2]. Facendolo, la lotta contro dea-
= UnitsInStock + 10 WHERE ProductID = 7. dlock o timeout bloccanti diverrà un ricordo
del passato.
Conclusioni
Come si è visto, può essere necessario trat- Riferimenti
tare SQL Server come ben più di un sempli- [1] Ken England “Microsoft SQL Server 2000
ce deposito di dati per evitare i deadlock e i Performance Optimization and Tuning Han-
lock di lunga durata. dbook”, Elsevier Digital Press
Per aumentare, o in primo luogo abilitare, la [2] Kalen Delaney “Inside Microsoft SQL Server
scalabilità delle proprie applicazioni, si deve an- 2000”, Microsoft Press
ENTERPRISE

Dieci tecniche
per controllare lo spam
CipherTrust rivela la propria top ten dei suggerimenti per controllare e combattere il
frustrante afflusso di spam nelle caselle aziendali.

di David Stanley

I
n un’era in cui si tende sempre più verso una “e- una soluzione antispam aziendale
economy”, è di capitale importanza che l’industria comprenderà un gestore integrato
delle telecomunicazioni si adatti a questo scenario. di politiche, che impone la politica
Vista la rapida migrazione verso l’utilizzo di dispositivi aziendale all’intero sistema di email
mobili al posto delle linee cablate e la crescente quan- e permette insiemi differenti di rego-
tità di abitazioni con accesso a Internet, si potrebbe le per differenti utenti e gruppi.
immaginare che le aziende leader stiano orientandosi
verso questa situazione. Ma così non è. Un buon nu- 3. Expertise – Conoscere il nemico
mero delle aziende dell’indice FTSE 100 non possono Gli spammer stanno costante-
neanche essere raggiunte via email e ciò può essere mente migliorando i propri meto-
causato solo da una cosa: la minaccia dello spam. Lo di, particolarmente man mano che
spam in azienda si è indubbiamente trasformato da fa- le aziende hanno infine iniziato a
stidio a problema critico. Nessun approccio allo spam difendersi. I produttori devono es-
può funzionare da solo, e nessuna singola tecnologia sere in grado di sviluppare e di-
è in grado di contrastarne l’aggressione. Ritengo però stribuire policy, firme, parole chia-
che utilizzando le seguenti dieci tecniche si possano ve e valori alle aziende utilizzando
avere buone armi contro la minaccia dello spam. la propria soluzione. Solo attraver-
so un costante miglioramento, una
1. Diversità – L’approccio a cocktail soluzione può continuare ad essere
L’identificazione è il primo passo verso il blocco del- responsiva agli spammer anche in
lo spam; a differenza dei virus non vi è alcuna unica presenza di nuove minacce.
soluzione che blocchi tutto lo spam. Ciò che è ne-
cessario è un “approccio a cocktail” in cui le aziende 4. Autenticazione – Posso vede-
impiegano più tecniche, comprese le analisi euristiche re un documento?
e i tool di filtraggio collaborativo in tempo reale. Gli spammer investono una note-
vole quantità di tempo e di impegno
2. Flessibilità – Misure differenti per persone differenti nel celare la propria identità e il punto
Un problema comune nelle aziende è la diversa defini- di origine dei loro attacchi. Fortunata-
zione di cosa sia esattamente lo spam. Per una organiz- mente, ciò lascia segnali rivelatori alle
zazione l’invio massiccio di email può essere visto come spalle. Un buon tool deve essere in
un fastidio, mentre per altre è un’operazione essenziale. grado di autenticare l’indirizzo DNS
Le soluzioni antispam devono permettere agli ammini- del server che sta inviando il mes-
stratori di imporre regole differenti e anche permettere saggio. Se il DNS Lookup inverso
di applicare regole differenti a utenti differenti. In teoria, non riesce ad autenticare il dominio
di una connessione in ingresso, ciò
può indicare un server dirottato, e ciò
può rappresentare un dato prezioso
David Stanley è VP e MD, EMEA, di CipherTrust.
per identificare lo spam.

62 VBJ N. 63 - Maggio/Giugno 2005


ENTERPRISE

5. Collaborazione – Uniti resistiamo, divisi cadiamo nistratore. Una generazione automatica di regole,
Le aziende devono sfruttare gli sforzi collaborativi dove le regole vengono create senza l’interven-
della comunità Internet per poter definire nuove si- to dell’amministratore e l’inserimento in whitelist
gnature e politiche. Non facendolo, si rende incom- degli utenti sicuri, migliorerà “al volo” il tasso di
pleta ogni soluzione. I migliori produttori hanno una rilevazione e farà diminuire i falsi positivi.
stretta collaborazione con i principali ricercatori e con
le iniziative collaborative per assicurare risposte ag- 9. Sicurezza – Osservare il quadro complessivo
giornate e importanti alle minacce dello spam. È bene proteggere l’intero sistema email da-
gli attacchi basati su email. L’intero sistema di
6. Apprendimento – Se mi inganni una volta, è email è un obiettivo non solo per gli spammer,
colpa tua. Se mi inganni due volte, è colpa mia ma anche per hacker e intrusi. Anche gli spam-
Gli spammer sono implacabili. Con le raffiche di mer sono hacker, che principalmente raccolgono
email che costano quasi nulla, hanno ogni moti- indirizzi email su mailserver e gateway. Un buon
vo per lanciare ripetutamente lo stesso attacco. sistema aziendale di email deve tener conto di
Per quanto frustrante sia ricevere spam, lo è an- queste vulnerabilità ed essere in grado di pro-
cor più ricevere lo stesso spam all’infinito. Nuo- teggere almeno sé stesso e in teoria l’intero si-
ve regole devono essere create automaticamen- stema di email da questi attacchi.
te man mano che nuove minacce emergono per
impedire in futuro uno spam analogo e/o permet- 10. Profiling – L’immondizia fuori, la comuni-
tere agli utenti finali di essere assistiti nella inter- cazione entra
cettazione dello spam. La sfida in corso delle aziende per combattere
lo spam è il compromesso tra un alto tasso di
7. Verifica – Controlla da te rilevazione e un alto tasso di falsi positivi. Fino a
Le aziende devono autorizzare i dipendenti a poco tempo fa, questa relazione era fissa. Man
esaminare e inserire i messaggi nelle proprie mano che aumentava il tasso di rilevazione, au-
code di quarantena, pur rispettando la supervi- mentava anche il numero di falsi positivi. L’uni-
sione complessiva dell’amministratore. Una sfida co modo per rompere questo modello, conse-
importante per gli amministratori incaricati delle guendo un alto tasso di rilevazione e minimiz-
soluzioni aziendali anti-spam è la gestione delle zando i falsi positivi, è installare una soluzione
aspettative e delle preoccupazioni degli utenti che può prendere decisioni complesse e dalle
finali. Dopo l’introduzione della soluzione anti- molte sfaccettature. Utilizzando un sistema di
spam, gli utenti finali avranno timore che ven- profiling, gli amministratori possono adottare in
gano bloccate le mail legittime. Una vera solu- modo aggressivo il blocco dello spam senza il
zione aziendale deve comprendere tool che per- rischio di perdere mail legittime.
mettano agli amministratori di fornire l’accesso
a code di quarantena per alcuni utenti o per tut- Una esauriente soluzione anti-spam
ti gli utenti, permettendo loro di essere tranquilli Amministrare queste dieci tecniche per con-
sui messaggi che sono stati bloccati. trollare lo spam, può diventare rapidamente
un compito ingestibile. Oggigiorno, le azien-
8. Automazione – Il miglior amico dell’ammi- de stanno cercando di prevenire lo spam uti-
nistratore lizzando solo una o due di queste tecniche, il
Conseguire e mantenere alti tassi di blocco anti- che produce una scarsa rilevazione e un alto
spam con un basso numero di falsi positivi è un tasso di falsi positivi. Una soluzione completa
impegno costante. Per garantire che gli ammini- dovrebbe basarsi su tutti i principi di cui si è
stratori non siano costretti a investire troppo tem- discusso. Fornendo questa protezione sul ga-
po in questo compito, una soluzione anti-spam teway, in una piattaforma irrobustita, resisten-
deve essere in grado di mantenere una efficien- te agli attacchi, si migliorerà la sicurezza com-
za indipendentemente dall’intervento dell’ammi- plessiva dell’azienda.

CipherTrust espone a Infosecurity Europe 2005, l’evento principale in Europa per l’Information Security. Giunta al suo decimo
anniversario, Infosecurity Europe comprende seminari, presenta nuovi prodotti e servizi, conta oltre 250 espositori e 10.000
visitatori. Si tiene nel mese di Aprile al Grand Hall, Olympia, Londra. Informazioni a: www.infosec.co.uk

N. 63 - Maggio/Giugno 2005 VBJ 63


I N O F F E R TA V B J 6 3
Scrivi a
Distributed Systems: Effective XML-50 Specific
Principles and Paradigms book@infomedia.it Ways to Improve Your XML
(International Edition) specificando di Elliotte Harold
di A. Tanenbaum
e M. van Steen nell’oggetto della
Prentice Hall
e-mail: Addison Wesley
ISBN 0131217860
803 pp - 69,95 €
IN OFFERTA ISBN 0321150406
336 pp - 46,95 €
VBJ n. 63
OPPURE
inviaci il coupon
BGP Sistemi di basi di dati
di I. van Beijnum sottostante Fondamenti 4/E
al numero di fax R. Elmasri - S. Navathe

0587/732232
O’Reilly Potrai acquistare Pearson Italia
ISBN 0596002548 ISBN 8871922204
288 pp - 41,40 €
i libri qui riportati con 580 pp - 35,00 €
uno
SCONTO
Database Design Manual:
ECCEZIONALE Beginning PHP 5 and
using MySQL for Windows MySQL: From Novice
di Norman, M. del 10% anche se to Professional
acquisti solo un di Gilmore W. J.

libro
Springer Apress
ISBN 1852337168 OPPURE ISBN 1893115518
225 pp - 69,50 € 736 pp - 40,50 €
del 20% se acquisti
3 libri

VBJ 63
LIBRI
Photoshop CS Computer
a portata di mano a responsabilità limitata
Autore J. C. Teague, W. Dietrich Autore David Harel
Editore Mc Graw Hill Editore Einaudi
ISBN 8835643954 ISBN 8806160095
Lingua Italiano Lingua Italiano
Anno 2004 Anno 2002
Pagine 624 Pagine 196
Prezzo € 38,50 Prezzo € 13,00

uesto libro è rivolto a quella fascia di persone che vuole impa- Un piccolo classico, questo di David Harel, computer scientist di fama

Q rare Adobe Photoshop da zero o comunque da un’esperienza


non approfondita, e a chi vuole comprendere velocemente
le novità introdotte rispetto alla versione precedente. Si comincia
planetaria, che divulga con brio concetti applicativi di algoritmica e
complessità computazionale per mostrare matematicamente, non
empiricamente o filosoficamente, “dove le macchine non riescono ad
ovviamente con un’attenta analisi dell’interfaccia di Photoshop, che a arrivare”, come recita il sottotitolo. Punto di partenza: non tutti i problemi
primo impatto può sembrare scarna, mentre in realtà cela una mole sono alla portata dei calcolatori, non importa quanto questi siano potenti
di comandi impressionante, spesso ignorati anche da chi lo utilizza o programmati in linguaggi avanzati. Esistono problemi indecidibili (o
quotidianamente da anni. La seconda delle cinque parti, in cui è non computabili) per i quali non c’è algoritmo di risoluzione; e problemi
stato giustamente diviso il libro per identificare i vari “temi” trattati, decidibili (computabili), ma con algoritmi di risoluzione troppo onerosi.
riguarda l’uso degli strumenti disponibili e dei principali comandi. Sono indecidibili il problema “della fermata” (se l’esecuzione di un
Seguono le attività legate alla fotografia digitale ed al video, la stampa dato problema avrà termine partendo da un certo input) e quello del
con annessa la gestione del colore ed infine il Web. “controllo dei programmi” (sapere se un programma termina e fornisce
Ogni “parte” contiene diversi paragrafi, tutti abbastanza scorrevoli, la soluzione corretta per tutti gli input ammissibili). Fra i decidibili, poi,
grazie ad una descrizione sapiente e mai macchinosa dei comandi per molti “non siamo ancora riusciti a trovare l’algoritmo più veloce, o
da eseguire, appoggiata da un buon numero di immagini “pratiche”, a dimostrare che sotto un certo limite non si può andare”; abbiamo
che fanno riferimento a quanto spiegato dal testo. Tra un paragrafo e dunque problemi “buoni” (a complessità polinomiale) e problemi “cattivi”
l’altro si possono trovare riferimenti ai comandi da tastiera, utilizzabili (esponenziali o superpolinomiali) o intrattabili che richiedono quantità di
per richiamare velocemente lo strumento o la funzione di cui si sta tempo irragionevoli anche a partire da piccoli input. Una vasta classe di
parlando, con la giusta combinazione sia per Windows che per Mac. problemi decidibili, inoltre, non è noto se sia trattabile, è assai difficile
Oltre questo, si incontrano spesso box grigi e testi contrassegnati cioè “stabilire se un algoritmo risponde “sì” con un dato input, ma è
dalle scritte “note” e “suggerimento”, contenenti informazioni utili facile certificare che lo fa, quando lo fa”; l’ “orario” di una scuola, note
alla comprensione e l’applicazione del capitolo; in alcuni casi, i box le disponibilità degli insegnanti e le ore di lezione per materia e per
grigi parlano di persone famose nel loro campo, di come utilizzano classe, è di questo genere. Se non si può far nulla con gli indecidibili,
tal strumento o funzione, con relativi indirizzi Web per approfondire fra i decidibili la ricerca è volta a migliorare gli intrattabili (mediante
meglio. Nel complesso, il libro riesce a trattare tutti gli argomenti soluzioni approssimative ma vicine alle esatte) e ad esplorare la classe
possibili o gli manca poco per farlo, ovviamente questo penalizza dei forse trattabili (se esistono algoritmi buoni per uno, saranno buoni per
quelli più difficili, come la stampa tipografica e la gestione del co- tutti); a tali frontiere: calcolo parallelo, randomizzazione, computazione
lore, che per essere trattati a fondo richiederebbe un libro di pari quantistica, calcolo molecolare, Harel dedica uno smilzo capitolo e non
dimensione. Concludendo, un libro relativamente economico per la eccessive speranze. Più concreta è la parte dedicata alla crittografia,
sua corposità, facile da leggere e ben strutturato, se pensate che la quale “sfrutta con astuzia e senza vergogna le limitazioni alla com-
Photoshop farà parte del vostro futuro, è una lettura che mi sento putazione che abbiamo visto finora” ed è largamente adoperata nelle
di consigliare senza remore. relazioni umane e… tra computer (protocolli di interazione), compagni
ormai insostituibili ma non migliori di noi: “è il lato splendente dell’infor-
matica, a cui questo libro cerca di contrapporre il lato oscuro”.
Pro
Semplice da leggere, offre una buona panoramica di tutti gli Pro
strumenti ed i maggiori comandi. Lettura agile e alla portata dell’utente medio o del semplice
curioso.
Contro
Contro Non aggiunge quasi nulla ad un precedente lavoro teorico del
Non copre approfonditamente argomenti difficili come la stampa 1987.
tipografica e la gestione del colore.

Stefano Arcidiacono Giuseppe Cornacchia

N. 63 - Maggio/Giugno 2005 VBJ 65