USARE LE COSTANTI

I PROGRAMMATORI ODIANO I NUMERI

Nella pratica della programmazione è molto comune la tendenza ad usare variabili anche in espressioni dove si conosce a priori il loro valore: possiamo dire che i programmatori odiano i numeri e tendono a sostituirli sempre con variabili. In questo approfondimento vediamo il perchè esaminando qualche caso tipico.

NOMI AL POSTO DI NUMERI

Abbiamo visto nella Lezione 6 che l'oggetto Event, che rappresenta un evento di sistema passato a pygame dal sistema operativo, ha un attributo type che permette di identificarne il tipo. Che tipo di dato contiene questo attributo? Proviamo ad aprire IDLE e digitiamo:


>>> import pygame
>>> pygame.QUIT
256

>>> pygame.MOUSEBUTTONDOWN      
1025

>>> pygame.KEYDOWN    
768

Quindi i vari tipi di evento sono contraddistinti da un numero intero. Di solito questi numeri sono assegnati dal sistema operativo: se ora volessimo verificare se un certo Event ev è un clic del mouse dovremmo scrivere:


if ev.type == 1025:

E' facile capire che se il nostro programma dovesse monitorare parecchi tipi di evento diventerebbe difficile ricordare a quale numero corrisponde ogni evento. Inoltre una persona che dovesse leggere il nostro programma farebbe parecchia fatica a capire il suo funzionamento. Per questo gli sviluppatori di pygame hanno associato a ciascun tipo di evento una variabile diversa (QUIT, MOUSEBUTTONDOWN, ...) con un nome facile da ricordare ed un valore corrispondente al numero dell'attributo type. In questo modo possiamo scrivere


if ev.type == MOUSEBUTTONDOWN:
al posto dell'istruzione precedente.

Sorge però un pronlema: cosa succederebbe se io usassi nel mio programma la variabile MOUSEBUTTONDOWN, assegnandole un altro valore? Evidentemente pygame non riconoscerebbe più i clic del mouse, e si provocherebbe una serie di errori strani e difficilmente comprensibili.

VARIABILI COSTANTI

Quello che abbiamo visto è un esempio dell'uso di costanti nei linguaggi di programmazione. Una costante è una variabile di cui si conosce a priori il valore, e che non deve essere più modificata dopo la sua prima assegnazione. E' per questo che alcuni linguaggi, come il C, hanno un'apposita parola chiave per rendere immodificabile una variabile: in C potremmo scrivere const davanti al nome della variabile quando le assegniamo un valore la prima volta e questo provocherebbe un errore se tentassimo di modificarla.

In Python non c'è nulla del genere, tuttavia i programmatori hanno deciso di usare delle convenzioni, già derivate dall'uso nei linguaggi precedenti, che consentono di riconoscere facilmente le costanti e di evitare errori:

Tipicamente le costanti in pygame si usano per le dimensioni di oggetti fissi, per i colori (al posto delle tuple RGB) o per i parametri di qualche funzione.

Quindi nella nostra pratica della programmazione dovremo ricordarci di non modificare mai una variabile scritta tutta in maiuscolo: come abbiamo detto Python permette di farlo, ma questa è una pratica pericolosissima perchè nelle intenzioni del programmatore quella variabile deve avere un valore fisso. Allo stesso modo, se nel nostro programma usiamo una costante, dovremo darle un nome scritto tutto in maiuscolo per far capire la situazione a chi legge il programma.

UN ALTRO ESEMPIO

Rivediamo ora questo frammento, simile a quello che avevamo scritto nella Lezione 8 per far rimbalzare una Surface sui bordi della finestra:


import pygame
from pygame.locals import *

pygame.init()
screen = pygame.display.set_mode((800, 600))

square = pygame.Surface((40, 40))
square.fill((240, 200, 20))
square_rect = square.get_rect()
square_vel = [1, 1]

.   .   . 
	
    if square_rect.left < 0 or square_rect.right > 800:
        square_vel[0] *= -1
    if square_rect.top < 0 or square_rect.bottom > 600:
        square_vel[1] *= -1	
.   .   .

Uno stile di programmazione simile, con tutti questi numeri, è considerato una bad practice dai programmatori: i numeri vengono chiamati ironicamente magic numbers e sono vivamente sconsigliati. Ricordiamo che nella realtà un programma complesso viene creato in genere da più persone che lavorano su file diversi, e che nel ciclo di vita di un programma capita di dover correggere errori, aggiungere funzionalità, rivedere il codice spesso scritto da un'altra persona, per cui è fondamentale che tale codice sia facilmente leggibile ed interpretabile. I problemi dei magic numbers sono i seguenti:

Anche qui possiamo risolvere questi problemi con l'uso delle costanti al posto dei numeri:


import pygame
from pygame.locals import *

SCREENSIZE = (800, 600)
SQUARESIZE = (40, 40)
SQUARECOLOR = (255, 240, 20)

pygame.init()
screen = pygame.display.set_mode(SCREENSIZE)

square = pygame.Surface(SQUARESIZE)
square.fill(SQUARECOLOR)
square_rect = square.get_rect()
square_vel = [1, 1]
.   .   .

    if square_rect.left < 0 or square_rect.right > SCREENSIZE[0]:
        square_vel[0] *= -1
    if square_rect.top < 0 or square_rect.bottom > SCREENSIZE[1]:
        square_vel[1] *= -1	
.   .   .

Ho aggiunto le righe #4 #5 #6 nelle quali ho creato tre costanti. In questo modo ho ottenuto molteplci vantaggi:

Potreste obiettare che ho dovuto aggiungere tre righe, allungando il programma: è vero che queste tecniche sono pensate soprattutto per programmi molto grandi, nei quali spesso le costanti sono definite in un file apposito, che viene poi importato nel file principale. E' proprio il caso di pygame, che definisce centinaia di costanti per gli eventi, i parametri delle funzioni, ecc.; l'istruzione from pygame.locals import * importa contemporaneamente tutti i loro nomi in modo da poterli usare senza anteporre il nome del modulo.

Vi faccio notare che nel corso del tutorial non ho seguito questa strada per indicare le dimensioni dello schermo, preferendo ottenerle ogni volta con i metodi .get_width() e .get_height(). Questo è preferibile perchè non presume che le dimensioni della finestra rimangano immutate per tutto il programma (potreste avere ad esempio una finestra ridimensionabile).