Vous souhaitez créer un petit programme permettant de convertir automatiquement des montants dans une devise souhaitée.
Le projet gère les cas d'utilisation suivants :
-
Cas standard
- L'utilisateur utilise le programme avec un fichier d'entrée cohérent.
De plus la conversion demandée est possible (existence d'au moins un chemin possible de proche en proche entre la devise source et la devise cible).
- L'utilisateur utilise le programme avec un fichier d'entrée cohérent.
-
Cas anormaux
- L'utilisateur utilise le programme sans argument.
- L'utilisateur utilise un fichier d'entrée non cohérent (cohérence du format ou cohérence logique).
- L'utilisateur utilise un fichier d'entrée cohérent, cependant, la conversion ne peut pas être effectuée car il n'y a pas de chemin possible entre la devise source et la devise cible.
Une partie de la consigne est :
Si plusieurs chemins de conversion vous permettent d'atteindre la devise cible, vous devez utiliser le chemin le plus court.
La résolution de cette problématique est assimilable à une recherche du plus court chemin pour aller d'une devise source à une devise cible dans un graphe (liste de taux de change).
Les propriétés du graphe représentant ce problème sont :
- Graphe simple (pas de self-loop, pas de multi-edge)
- non orienté (undirected)
- sans notion de poids (unweighted)
Un graphe peut être représenté de différentes façons.
La manière de représenter un graphe aura une influence sur 2 choses :
- Complexité spatiale
Il s'agit de la quantité de mémoire utilisée pour représenter les données du graphe. - Complexité temporelle
Il s'agit de la performance des algorithmes qui vont pouvoir s'appliquer sur le graphe.
Par exemple :- trouver si deux sommets sont connectés
- trouver tous les sommets adjacents à un sommet donné
Dans ce projet, j'ai choisi de représenter les données en Edge list.
Plusieurs algorithmes existent pour trouver le plus court chemin entre 2 sommets dans un graphe :
- Dijkstra
- Bellman-Ford
- Floyd-Warshall
Dans ce projet j'ai choisi d'implémenter l'algorithme de Dijkstra.
- Video : mise en application pas à pas de l'algorithme de Dijkstra
- Finding The Shortest Path, With A Little Help From Dijkstra
- https://softwarecampament.wordpress.com/portsadapters/
- https://blog.xebia.fr/2016/03/16/perennisez-votre-metier-avec-larchitecture-hexagonale/
- https://www.freecodecamp.org/news/implementing-a-hexagonal-architecture/
- https://blog.octo.com/architecture-hexagonale-trois-principes-et-un-exemple-dimplementation/
Trois grandes zones :
- Application (Driver side)
- Domain
- Infrastructure (Driven side)
Le code et les concepts métier sont isolés dans la zone Domain. La zone Domain ne dépend de rien.
Il ne doit exister aucun concept technique dans dans la zone Domain.
La zone Domain contient des ports :
- ports primaires : ports à brancher sur la zone Application
- ports secondaires : ports à brancher sur la zone Infrastructure Le branchement aux ports se fait via des Adapter.
L'avantage est d'isoler dans le Domain toute la valeur métier du programme.
Pour moi, la responsabilité de validation du fichier d'entrée est à faire par la zone Domain.
C'est similaire par exemple au travail qui est fait par les validateurs dans un site web MVC.
Une partie du problème posé dans la consigne est assimilable à une recherche du plus court chemin pour aller d'un point A (devise source)
à un point B (devise cible) dans un graphe (liste de taux de change).
Pour moi, toute la logique de recherche est purement technique et ne doit donc pas se trouver dans la zone Domain.
C'est juste une fonctionnalite technique dont le Domain a besoin. Cela semble logique de le placer dans la zone Infrastructure.
On peut imaginer implémenter des algorithmes alternatifs pour trouver le plus court chemin :
- Algorithme de Bellman-Ford
- Algorithme de Floyd-Warshall
Les projets de tests utilisent le framework de tests unitaires MSTest.
Le framework de simulacre est Moq.
Dans ce projet, j'ai utilise l'IoC. J'utilise notamment ce principe pour rendre indépendante la zone Domain de l'architecture hexagonale.
L'IoC est l'un des 5 principes SOLID.
Pour faire l'injection de dépendance, j'ai utilisé le container IoC Unity.
J'ai choisi d'injecter les dépendances par constructeur.