Se passate da Torino il 21 febbraio

Si parlerà di un pattern da me molto amato, Decorator. E’ un peccato che Decorator porti a dei problemi di identità. Davvero!

Intanto questo è link con i dettagli sul meeting :
http://www.jugtorino.it/vqwiki/jsp/Wiki?MeetingFebbraio2007

Se non conoscete Decorator è meglio aspettare di leggere quanto segue fino a chè non avrete seguito il meeting di cui sopra.

Ora… perchè Decorator porta a problemi di personalità?

Supponiamo di avere una lista di oggetti di tipo User :

List registeredUsers = new ArrayList();

Abbiamo poi un metodo :

public void register(User user) {
if(!registeredUsers.contains(user)) registeredUsers.add(user);
}

Nulla di particolare no? Se non per il fatto che si potrebbe evitare di usare una ArrayList e passare all’uso dei Set, ad esempio di TreeSet, per assicurarsi automaticamente dell’unicità dello user. Ma questo renderebbe meno chiaro il problema, visto che nasconderebbe parte della logica.

Passiamo al nostro Decorator ora :
User è un’interfaccia, che viene implementata da SystemUser e da tre Decorators : AdminUser, TemporaryUser e RemoteUser. Ognuno di questi Decorators, una volta wrappato attorno a uno User…

classico : user = new AdminUser(user);

…aggiunge alcune funzionalità al SystemUser in modo del tutto trasparente e dinamico. Bello il decorator eh?

Ma il decorator è davvero così trasparente? Lo è e non lo è. Per le operazioni di uguaglianza non lo è per niente : il metodo di cui sopra, che controlla se un utente è già registrato prima di registrarlo, verrà sviato dal fal fatto che lo user che gli stiamo passando, per quanto sia solo un guscio attorno a un altro user, avrà un identità, nello heap degli oggetti, del tutto diversa dall’oggetto che contiene.

Per quello che deve fare il nostro manager di registrazione degli utenti, a noi piacerebbe tanto che :

registrator.register(user);
registrator.register(new AdminUser(user));
assertEquals(1,registrator.size());

E in vece no… ci ritroveremo due utenti registrati, quando di fatto si tratta dello stesso utente registrato due volte, sotto forma di due oggetti diversi, per quanto intimamente legati.

In breve, Decorator non è per niente trasparente all’operatore di identità. Allo stesso modo un oggetto che ne decori un altro dovrebbe assicurarsi di fare l’override sia di hashCode() che di equals() in modo da invocare il decorato anche in quel caso, come per i metodi dichiarati in User.

Peccato che “==” non sia a sua volta un metodo di cui poter fare l’override.

Risolvere questi problemi di identità pur continuando a usare Decorator spesso necessita di discriminare tra una classe e l’altra. Per evitare degli instanceof (brrr!!) viene in soccorso Visitor… ma non è la stessa cosa, parte dell’eleganza e compattezza data Decorator viene annullata dall’uso di Visitor che, per quanto sia un gran pattern, è tanto furbo quanto è poco elegante/chiaro.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s