1. Contexte Financier
De nombreuses applications financières gèrent des comptes de clients nécessitant des consultations de soldes des différents produits financiers ou sous-comptes. Par exemple, le compte financier fait partie de la balance des paiements d'un pays. Il mesure les variations de la propriété internationale d'actifs appartenant à des particuliers, des entreprises, au gouvernement ou à sa banque centrale. Les actifs incluent les investissements directs, les titres comme les actions et obligations, et les matières premières telles que l'or, et les devises. Le compte financier rapporte la variation totale des avoirs internationaux détenus. Il indique si le nombre d'actifs détenus a augmenté ou diminué, sans préciser le montant total des actifs. Une augmentation signifie que des capitaux étrangers entrent dans le pays, tandis qu'une diminution indique que des capitaux nationaux sortent vers des marchés étrangers. Le compte financier comprend deux sous-comptes principaux. Le premier présente la propriété nationale des actifs étrangers, mesurant les sorties d'argent pour acheter des actifs étrangers, et le second démontre la propriété étrangère des actifs nationaux, mesurant les entrées d'argent pour acheter des actifs domestiques. La seule différence entre ces sous-comptes réside dans l'origine de la propriété des actifs.
Le sous-compte de la propriété nationale des actifs étrangers se divise en trois types de comptes : réserves privées, gouvernementales et de la banque centrale. Quelle que soit l'entité propriétaire, une augmentation soustrait du compte financier. Les sous-comptes des propriétaires privés incluent les particuliers et les entreprises, et peuvent être classifiés par les comptes de dépôt dans des banques étrangères, des prêts aux étrangers, des titres de sociétés étrangères, des investissements directs réalisés à l'étranger, et des matières premières détenues dans d'autres pays. Les comptes des propriétaires gouvernementaux, principalement fédéraux, incluent principalement de l'or et des devises étrangères détenues en réserve, ainsi que la position de réserve au Fonds Monétaire International (FMI). La banque centrale peut posséder ces mêmes actifs, à l'exception de la position de réserve au FMI, et détient également des swaps de devises avec d'autres banques centrales.
Le sous-compte de la propriété étrangère d'actifs nationaux se divise en actifs privés et officiels étrangers. Lorsque les étrangers augmentent leur propriété des actifs d'un pays, le montant s'ajoute au compte financier. Les comptes domestiques incluent les dépôts détenus par des étrangers dans les banques nationales, les prêts accordés par des banques étrangères, les achats privés étrangers de titres d'État, les titres de sociétés détenus par des étrangers, les investissements directs étrangers, et d'autres dettes envers les étrangers. Les comptes officiels étrangers incluent les actifs détenus par des gouvernements ou banques centrales étrangères, ainsi que les expéditions nettes de la monnaie nationale aux gouvernements étrangers.
Le compte financier est une composante cruciale de la balance des paiements. Il s'ajoute à la balance des paiements lorsqu'il est positif et que des capitaux étrangers entrent pour acheter des actifs, et il soustrait de la balance des paiements lorsque des capitaux nationaux sortent pour acheter des actifs étrangers. Si le compte financier enregistre un excédent significatif, il peut compenser un déficit commercial. En cas de déficit commercial compensé par un excédent du compte financier, cela indique que le pays vend ses actifs pour payer des biens et services étrangers.
Ainsi, l'accumulation des soldes de tous les sous-comptes dans cette structure hiérarchique devient cruciale, car l'ajout ou le retrait d'un compte pourrait radicalement changer l'application si elle se basait uniquement sur une simple somme des sous-comptes élémentaires.
En informatique, l'algorithme « diviser pour régner » [1] est adapté à la sommation arborescente, calculant récursivement ou directement tous les sous-comptes du niveau le plus bas au plus haut. Les modèles de patron de conception structurelle [2] offrent des méthodes pour assembler des objets et classes dans des structures complexes, tout en maintenant flexibilité et efficacité.
Le patron de conception structurel composite permet d'organiser les objets en arborescence pour les traiter intégralement comme des objets individuels, évitant ainsi de redéfinir le traitement pour chaque individu. Le principe est d'identifier les classes feuille (scalaires ou primitives) et les classes composite (vecteur ou conteneur) comme illustré dans la figure 1, avec un composant de base nécessaire pour rendre toutes les classes concrètes interchangeables. Le parcours récursif des classes composite jusqu'aux classes feuille appelle de manière homogène l'opération de sommation pour obtenir le résultat final. Ainsi, bien que le nombre de comptes ne soit pas connu à l'avance et puisse évoluer dynamiquement, la définition du calcul cumulatif des soldes reste identique pour chaque compte dans l'arborescence.
Dans cet article, nous mettrons en œuvre le patron de conception composite en Python 3, pour résoudre le problème de l'accumulation dans une structure arborescente d'entités complexes, tout en respectant le principe SOLID [3].
2. Conception de composite
Le diagramme UML de la figure 2 illustre le développement du patron de conception composite. Le modèle de notre application peut être représenté sous forme d'arborescence, avec deux classes : la feuille et le composite. Les composites doivent contenir à la fois des feuilles simples et d'autres composites, et tous les comptes partagent une interface commune : le composant de base. Grâce à cette interface, le client n'a pas besoin de connaître la classe concrète des objets manipulés.
Toutes les classes concrètes ont une relation « est un » avec le composant de base, et les composites se couplent à l'interface par composition récursive. Les composites comprennent des instances en hiérarchie, héritant du composant de base. Les composites délèguent la plupart de leurs opérations à leurs classes fille via le polymorphisme en Python 3. Les méthodes d'ajout et de suppression d'éléments sont définies dans les composites.
La structure de composite suit correctement le principe ouvert/fermé de SOLID [3]. De nouveaux types d'éléments peuvent être introduits sans casser le code existant.
Il faut noter que placer les opérations concrètes dans l'interface du composant de base violerait le principe de ségrégation d'interface de SOLID [3], car les méthodes seraient vides dans la classe feuille, même si le client pourrait traiter tous les éléments de la même manière.
Dans notre contexte, l'opération du composant de base est d'obtenir le solde total de compte. Deux implémentations suffisent pour le modèle. Les comptes des classes feuilles fournissent directement les valeurs, tandis que les comptes des classes composites calculent récursivement les sommes des soldes de leurs sous-comptes.
Le client instancie les classes du niveau bas vers le haut, insérant progressivement les objets dans l'arborescence. Une fois la structure de composite créée pour tous les comptes, on peut appeler la méthode de solde d'une instance pour obtenir le résultat correspondant.
3. Développement de composite
Dans notre exemple, nous analysons l'économie en suivant l'évolution des soldes des comptes financiers en euros d'un pays entre 2001 et 2010. Pour simplifier, nous initialisons chaque compte feuille avec un montant fictif de 1 milliard d'euros en 2001, augmentant de 1 million d'euros chaque année. Nous instancions ces objets avant de les insérer dans les composites. Si les devises diffèrent, nous utilisons la librairie currency_converter pour convertir les montants. Enfin, le client obtient les soldes sur dix ans dans une boucle for, dessinant leur évolution avec matplotlib.
Pour démontrer l'avantage de notre structure face aux changements dynamiques, supposons que le pays suspende sa collaboration avec le FMI en supprimant son compte de réserve entre 2003 et 2008, avant de le rétablir en 2009.
Nous nous appuyons sur l'interface IAccount proposant des méthodes abstraites [4] aux comptes simples et complexes. La classe SimpleAccount connaît directement le solde par conversion de devise, tandis que la classe ComplexAccount somme récursivement les soldes de ses sous-comptes. Le calcul n'atteint chaque nœud qu'une seule fois, rendant le cache [5] inutile.
Les méthodes d'ajout et de suppression de comptes dans la classe ComplexAccount permettent de gérer les changements dynamiques. Dans notre cas, le compte « imf reserve government account » disparaît entre 2003 et 2008.
Les tests unitaires confirment les résultats attendus. Les comptes ne peuvent être ajoutés en double, ni supprimés s'ils sont inexistants.
Voici les résultats affichés dans la console, avec les rapports sauvegardés en image au format PNG.