In questi giorni sto lavorano per ideare una architettura di un
nuovo progetto per una web application. Si tratta di un progetto abbastanza
semplice, ma ormai non sono più in grado di scrivere del codice senza prima aver
definito un minimo di dettaglio architetturale, anche perchè ad ogni nuovo
progetto tento sempre di migliorare quello che può essere la base
dell'applicazione con l'esperienza maturata nei progetti precedenti.
Così mi sono imbattuto in un comportamento che a dire la verità
avrei dovuto immaginare, ma che di primo acchito mi ha sconcertato. In effetti
più che in una categoria "lo sapevate che" questo post dovrebbe andare in "avete
mai considerato che". Quello che è successo è che ho provato ad esporre lo
strato di logica applicativa, quello intermedio tra data layer e interface per
intenderci, per mezzo di un Singleton. Che Singleton e Web non andassero molto
daccordo ne ero già convinto, ma gli eventi mi hanno rafforzato ancor di più
questa convinzione.
Scritto il codice di base e fatti i dovuti test, mi sono posto
di problema di che "scope" avesse il Singleton. Sbadatamente avevo considerato
che una classe fosse Singleton nel thread che elabora la pagina, perciò questo
non avrebbe avuto nessuna conseguenza sulle altre pagine. Tuttavia una verifica
andava fatta, ed ho così deciso di creare un campo statico e di
valorizzarlo con il SessionId del chiamante. Ovviamente quello che è successo è
stato che l'id valorizzato da un thread era poi visibile da un'altra istanza di
browser.
Quello che ne evinco è quindi che l'uso di una classe Singleton
provoca "l'allocazione" (scusatemi il termine improprio) di una porzione di
codice eseguibile nel processo host, e quindi anche del relativo spazio di
allocazione per variabili & co. Morale sia quindi che i Singleton, almeno
usati per lo scopo iniziale che avevo individuato, non si possono usare,
soprattutto se essi devono mantenere uno stato al loro interno. Infatti in
questo caso sarebbe necessario utilizzare dei lock esclusivi (un po' come si fa
con le Application) per evitare delle situazioni di concorrenza e quindi ci si
esporrebbe al decadimento delle performances.
La mia soluzione finale, è stata quella di creare una classe
base per le pagine dell'applicativo, che inizializza un'istanza del controller
della logica sull'OnInit e lo distrugge se necessario sull'OnUnload. Un po' più
laborioso di un Singleton, ma certamente migliore.