La buona programmazione è merce rara. Frotte di programmatori al grido di “basta che funziona” popolano la rete. Hanno codice non commentato, arrabattato, non modulare in cui una classe svolge funzioni di altre classi e non ci si capisce nulla. Evitiamolo.
Le motivazioni sono molteplici: miglior debug, risoluzione dei bug, facilità nella portabilità, estendibilità, maggior comprensione del codice per chi volesse aiutarvi e molto altro.
Un elemento fondamentale di questa programmazione elegante è l’information hiding. Parlerò in dettaglio dell’information hiding nel mio progetto GaPG, vi basti sapere, se non ne siete a conoscenza, che per information hiding si intende la pratica di “nascondere” gli attributi di una classe e renderli accessibili solo tramite funzioni pubbliche chiamate setter, getter e in alcuni linguaggi anche deller.
Ovviamente non devono esistere tutte queste funzioni ogni volta. Sicuramente vogliamo che il nostro attributo sia accessibile all’esterno, quindi sicuramente metteremo sempre un getter. Ma potremmo volere che un certo attributo sia immutabile o, comunque, non possa essere modificato a piacere dall’esterno, e quindi non forniremo tramite attributo di un setter, rendendo così impossibile la modifica esterna.
Questo atteggiamento è spesso incompreso dai programmatori novelli. Essi infatti pensano che sia soltanto una forma di pornografia informatica, un feticismo da nerd. Grave. L’information hiding è la migliore contromisura per ogni sorta di bug. Impedire l’accesso solo a dati “puliti” è essenziale. Tramite un setter ad esempio possiamo controllare che il valore inserito rientri nel range di validità del valore, ad esempio, impedendo che il campo età di Persona possa essere impostato con un età negativa.
Python pecca parecchio da questo punto di vista. E questo è probabilmente il punto debole più vistoso di python. Così nelle versioni si è cercato di “pezzarlo” come si poteva. Python infatti non distingue fra attributi pubblici e attributi privati. Assume che siano sempre pubblici.
Una convenzione molto usata consiste nel anteporre all’attributo un doppio underscore ( _ _ ) in modo da segnalare che quell’attributo è privato. Ad esempio:
class CartaDaGioco(): def __init__(self,seme,valore): self.__seme = seme self.__valore = valore
Ma il concetto di privato inserito in questo modo è del tutto relativo. L’unica cosa che fa l’interprete per rendere più scomodo l’accesso a tali attributi è di rinominarli in _CartaDaGioco__seme e in _CartaDaGioco__valore. Questi metodi però restano accessibili per chi ne conosce il nome e sono ancora una forte tentezione.
Python offre però un metodo interessante per disincentivare ulteriormente l’uso scorretto dell’information hiding, offre la possibilità di gestire come se fosse un attributo setter e getter tramite delle variabili “virtuali”. Ma un esempio chiarirà di molto questo concetto in apparenza complesso.
class CartaDaGioco() def __init__(self,seme,valore): self.__seme = seme self.__valore = valore@property
def valore(self):
return self.__valore@valore.set
def valore(self,newseme):
if 1<=newseme<11 : self.__valore = newseme
In questo modo, tramite l’uso del decoratore property abbiamo creato un attributo virtuale valore associato all’attributo reale __valore. In questo modo possiamo accedere alla variabile come fosse un normale attributo:
>>> a = CartaDaGioco('bastoni',7) >>> print(a.valore) '7' >>> a.valore = 9 >>> print(a.valore) # il valore è stato modificato perché è un valore valido. '9' >>> a.valore = -20 >>> print(a.valore) # il valore non è cambiato perché -20 non è un valore valido. '9'
Come potete vedere, sebbene l’utilizzo di valore sia completamente uguale all’uso di un attributo abbiamo inserito un “vincolo” ai valori di valore ridefinendo il suo setter. Non specificando nessun setter, inoltre, quando proviamo a scrivere sull’attributo virtuale, ci viene restituito errore. Proprio come volevamo per creare un attributo immutabile.
Il decoratore property permette inoltre di creare attributi fittizi il cui valore è dato dalla combinazioni di attributi reali. Ad esempio se la classe Dipendente ha come unico attributo il campo stipendio possiamo definire con @property un attributo stipendioannuale che restituirà il valore di stipendio moltiplicato per 12.
Insomma. L’uso di property non è obbligatorio ma fornisce quel tocco di eleganza alla vostra programmazione.
Per maggiori informazioni vi rimando alla documentazione ufficiale. 🙂
Alla prossima.