Base or not Base?

4 apr 2015 15:59

_Logo Una classica convenzione che ho utilizzato negli anni riguarda il prefisso Base per le classi astratte. In realtà non è una buona pratica ed infatti per i nuovi progetti non la utilizzo più, in linea col principio che un tipo rappresenta un qualcosa che ha già un nome significativo: il suo ruolo. Il prefisso I resiste, ma senza solidi motivi.

L’utilizzo di Base (o di Abstract) permette a chi deriva quella classe astratta di capire che si tratta appunto di un tipo non istanziabile, ma questo non ha nessun vantaggio: se il tipo è da derivare che sia astratto o no non ha alcuna importanza.

Base permette inoltre all’utilizzatore di capire che non può istanziare l’oggetto, ma per questo ci pensa già il compilatore. Tra l’altro l’utilizzatore, per creare il tipo più corretto, dovrebbe utilizzare una factory o un IoC, magari anche solo un metodo shared della classe stessa.

Se nel corso del tempo la classe dovesse diventare concreta, sarebbe necessario rinominarla in ogni dove. Certamente le funzionalità di refactoring di un qualsiasi IDE aiutano, ma non è detto che sia operazione senza dolore (magari esiste già un tipo con quel nome, magari stiamo parlando di una API, magari cambiare nome significa ricompilare un centinaio di progetti…).

Se il tipo astratto viene inoltre utilizzato per il valore di ritorno di un membro, identificarlo come astratto non ha senso e può confondere l’utilizzatore.

In una vecchia discussione presente su stackoverflow, viene evidenziato come nel .NET vi sia una doppia convezione: ProviderBase e SessionStateStoreProviderBase utilizzano un suffisso, mentre DbParameter e DbCommand no. E nelle guide del .NET Framework la convenzione è ancora citata. Ma quelle guide sono state scritte molto tempo fa quando l’eredità del C++ era ancora forte, infatti è nata in casa Microsoft un’altra convenzione grazie al progetto StyleCop.

Archiviato Base possiamo passare al prefisso per eccellenza: I. Sebbene sia utilizzato ovunque, soffre delle stesse considerazioni fatte per Base: teoricamente non ha validi motivi di esistere. Se proprio, considerando che il concetto di astrazione è generico, e identifica con interfaccia di un tipo l’insieme dei sui membri pubblici, allora I dovrebbe essere usato sia per le interfacce sia per le classi astratte. Ma in entrambi i casi ritorniamo allo stesso discorso.

Sull’argomento cito questi due articoli: Dont Distinguish Between Classes And Interfaces e Naming Classes and Interfaces.

Infine, una precisazione/avvertimento: non ha alcun senso modificare centinai di classi dei propri legacy project per adottare una nuova convenzione. Sarebbe tempo sprecato. Continuare ad usare la convezione del progetto è la strada migliore oppure, in accordo col team, introdurre la nuova convenzione gradualmente.

Ricordo infine con terrore quando usavo come prefisso cls seguito da un acronimo del dominio seguito dal nome vero e proprio. Poi sono rinsavito e ho iniziato ad utilizzare i namespace abbandonando l’inutile prefisso. In quel caso modificare tutti i sorgenti è stato obbligatorio: non volevo lasciare tracce.