8. Exercício de aplicação – [Cálculo de impostos] com uma arquitetura em camadas
![]() |
Aqui, retomamos o exercício descrito na Secção 4.1. Começamos com a versão em ficheiro de texto descrita na Secção 4.3. Para tratar este exemplo com objetos, utilizaremos uma arquitetura de três camadas:
![]() |
- a camada [DAO] (Data Access Object) trata do acesso aos dados. A seguir, estes dados serão inicialmente encontrados num ficheiro de texto e, posteriormente, numa base de dados MySQL;
- A camada [de negócios] lida com a lógica de negócios, neste caso, o cálculo de impostos. Não lida com dados. Estes dados podem provir de duas fontes:
- da camada [DAO] para dados persistentes;
- a camada [console] para dados fornecidos pelo utilizador.
- A camada [console] lida com as interações com o utilizador.
A seguir, as camadas [DAO] e [business] serão implementadas, cada uma, utilizando uma classe. A camada [console] será implementada pelo programa principal.
Partiremos do princípio de que todas as implementações da camada [dao] fornecem o método getData(), que devolve uma tupla de três elementos (limits, coeffR, coeffN) — as três matrizes de dados necessárias para calcular o imposto. Noutras linguagens, isto é designado por interface. Uma interface define métodos (neste caso, getData) que as classes que implementam essa interface devem possuir.
A camada [business] será implementada por uma classe cujo construtor recebe uma referência à camada [dao] como parâmetro, garantindo a comunicação entre as duas camadas.
8.1. A camada [DAO]
Vamos combinar as várias classes necessárias para a aplicação num único ficheiro, impots.py. Os objetos neste ficheiro serão então importados para os scripts que os necessitam.
Começamos com o caso em que os dados se encontram num ficheiro de texto, tal como no exemplo da Secção 4.3.
![]() |
O código da classe [ ImpotsFile] (impots.py) que implementa a camada [DAO] é o seguinte:
Notas:
- linhas 7-8: definimos uma classe ImpotsError derivada da classe Exception. Esta classe não acrescenta nada à classe Exception. Utilizamo-la exclusivamente para ter uma classe de exceção personalizada. Esta classe poderá ser expandida posteriormente;
- linhas 11–18: uma classe de métodos utilitários. Aqui, o método cutNewLineChar remove quaisquer caracteres de quebra de linha de uma string;
- linha 25: a abertura do ficheiro pode lançar a exceção IOError;
- linhas 32, 39, 46: a exceção personalizada ImpotsError é lançada;
- o código é semelhante ao estudado no exemplo da Secção 4.3.
8.2. A camada [de negócios]
![]() |
A classe [ ImpotsMetier] (impots.py) que implementa a camada [de negócios] é a seguinte:
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]))
Notas:
- linhas 5-6: o construtor da classe recebe uma referência à camada [dao] como parâmetro;
- linha 16: utilizamos o método getData da camada [dao] para recuperar os dados necessários para calcular o imposto;
- o resto do código é análogo ao estudado no exemplo da Secção 4.3.
8.3. A camada [console]
![]() |
O script que implementa a camada [console] (impots-03) é o seguinte:
Notas:
- Linha 4: Importamos todos os objetos do ficheiro impots.py, que contém as definições das classes. Depois de feito isto, podemos usar esses objetos como se estivessem no mesmo ficheiro que o script;
- Linhas 17–21: Instanciamos tanto a camada [dao] como a camada [business], com tratamento para potenciais exceções;
- Linha 18: instanciamos a camada [dao] e, em seguida, a camada [business]. Guardamos a referência à camada [business];
- linha 19: tratamos as duas exceções que podem ocorrer;
- o resto do código é semelhante ao estudado no exemplo da Secção 4.3.
8.4. Resultados
Os mesmos que já foram obtidos nas versões que utilizam matrizes e ficheiros.
O ficheiro de dados 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
O ficheiro de dados data.txt:
O ficheiro results.txt contendo os resultados:




