8. Esercizio di applicazione – [Calcolo delle imposte] con un'architettura a livelli
![]() |
Qui riprendiamo l'esercizio descritto nella Sezione 4.1. Partiamo dalla versione con file di testo descritta nella Sezione 4.3. Per gestire questo esempio con gli oggetti, useremo un'architettura a tre livelli:
![]() |
- il livello [DAO] (Data Access Object) gestisce l'accesso ai dati. Di seguito, questi dati saranno inizialmente presenti in un file di testo, poi in un database MySQL;
- Il livello [business] gestisce la logica di business, in questo caso il calcolo delle imposte. Non gestisce i dati. Questi dati possono provenire da due fonti:
- il livello [DAO] per i dati persistenti;
- il livello [console] per i dati forniti dall'utente.
- Il livello [console] gestisce le interazioni con l'utente.
Di seguito, i livelli [DAO] e [business] saranno implementati ciascuno utilizzando una classe. Il livello [console] sarà implementato dal programma principale.
Supporremo che tutte le implementazioni del livello [dao] forniscano il metodo getData(), che restituisce una tupla di tre elementi (limits, coeffR, coeffN)—i tre array di dati necessari per calcolare l’imposta. In altri linguaggi, questa è chiamata interfaccia. Un’interfaccia definisce i metodi (in questo caso, getData) che le classi che implementano tale interfaccia devono avere.
Il livello [business] sarà implementato da una classe il cui costruttore accetta come parametro un riferimento al livello [dao], garantendo la comunicazione tra i due livelli.
8.1. Il livello [DAO]
Combineremo le varie classi necessarie per l'applicazione in un unico file, impots.py. Gli oggetti in questo file verranno poi importati negli script che ne hanno bisogno.
Iniziamo con il caso in cui i dati si trovano in un file di testo, come nell'esempio della Sezione 4.3.
![]() |
Il codice della classe [ ImpotsFile] (impots.py) che implementa il livello [DAO] è il seguente:
Note:
- righe 7-8: definiamo una classe ImpotsError derivata dalla classe Exception. Questa classe non aggiunge nulla alla classe Exception. La usiamo esclusivamente per avere una classe di eccezione personalizzata. Questa classe potrebbe essere ampliata in seguito;
- righe 11–18: una classe di metodi di utilità. Qui, il metodo cutNewLineChar rimuove eventuali caratteri di interruzione di riga da una stringa;
- riga 25: l'apertura del file potrebbe generare l'eccezione IOError;
- righe 32, 39, 46: viene generata l'eccezione personalizzata ImpotsError;
- il codice è simile a quello studiato nell'esempio della Sezione 4.3.
8.2. Il livello [business]
![]() |
La classe [ ImpotsMetier] (impots.py) che implementa il livello [business] è la seguente:
class ImpotsMetier:
# constructeur
# on récupère un pointeur sur la couche [dao]
def __init__(self, dao):
self.dao=dao
# calcul de l'impôt
# --------------------------------------------------------------------------
def calculer(self,marie,enfants,salaire):
# marié : oui, non
# enfants : nombre d'enfants
# salaire : salaire annuel
# on demande à la couche [dao] les données nécessaires au calcul
(limites, coeffR, coeffN)=self.dao.getData()
# nombre de parts
marie=marie.lower()
if(marie=="oui"):
nbParts=float(enfants)/2+2
else:
nbParts=float(enfants)/2+1
# une 1/2 part de plus si au moins 3 enfants
if enfants>=3:
nbParts+=0.5
# revenu imposable
revenuImposable=0.72*salaire
# quotient familial
quotient=revenuImposable/nbParts
# est mis à la fin du tableau limites pour arrêter la boucle qui suit
limites[len(limites)-1]=quotient
# calcul de l'impôt
i=0
while quotient>limites[i] :
i=i+1
# du fait qu'on a placé quotient à la fin du tableau limites, la boucle précédente
# ne peut déborder du tableau limites
# maintenant on peut calculer l'impôt
return math.floor(revenuImposable*(float)(coeffR[i])-nbParts*(float)(coeffN[i]))
Note:
- righe 5-6: il costruttore della classe riceve come parametro un riferimento al livello [dao];
- riga 16: utilizziamo il metodo getData del livello [dao] per recuperare i dati necessari al calcolo dell'imposta;
- il resto del codice è analogo a quello studiato nell'esempio della Sezione 4.3.
8.3. Il livello [console]
![]() |
Lo script che implementa il livello [console] (impots-03) è il seguente:
Note:
- Riga 4: importiamo tutti gli oggetti dal file impots.py, che contiene le definizioni delle classi. Una volta fatto ciò, possiamo utilizzare questi oggetti come se fossero nello stesso file dello script;
- Righe 17–21: Istanziamo sia il livello [dao] che il livello [business] con la gestione delle potenziali eccezioni;
- riga 18: istanziamo il livello [dao] e poi il livello [business]. Memorizziamo il riferimento al livello [business];
- riga 19: gestiamo le due eccezioni che potrebbero verificarsi;
- il resto del codice è simile a quello studiato nell'esempio della Sezione 4.3.
8.4. Risultati
Gli stessi già ottenuti nelle versioni che utilizzano array e file.
Il file di dati impots.txt:
12620:13190:15640:24740:31810:39970:48360:55790:92970:127860:151250:172040:195000:0
0:0.05:0.1:0.15:0.2:0.25:0.3:0.35:0.4:0.45:0.5:0.55:0.6:0.65
0:631:1290.5:2072.5:3309.5:4900:6898.5:9316.5:12106:16754.5:23147.5:30710:39312:49062
Il file di dati data.txt:
Il file results.txt contenente i risultati:




