Vous êtes sur la page 1sur 14

Support de cours

Architecture des SI I

Chapitre 4 : Principes &


Patrons de conception

SOMMAIRE

Les principes de conception SOLID 2


Principe de responsabilité unique (SRP) 2
Principe ouvert-fermé (OCP) 5
Le principe de substitution de Liskov (LSP) 6
Le principe de ségrégation d’interface (ISP) 8
Le principe d'inversion de dépendance 9
Références 11
Les patrons de conception 11
Disposoble 11
Factory Pattern 12
Repository 13
Unit Of Work 13
Références 14
Les principes
incipes de conception SOLID
Les principes de conception SOLID sont essentiellement utilisés pour gérer la plupart des problèmes
de conception de logiciels auxquels nous sommes généralement confrontés en tant que développeur
dans notre programmation quotidienne.

Les principes SOLID représentent


eprésentent cinq principes de conception orientée objet, promus par Robert C.
Martin, connu par l'oncle Bob. Ces principes servent essentiellement à rendre les conceptions
logicielles plus compréhensibles, flexibles et maintenables.

Principe de responsabilité
responsabil unique (SRP)
Qu'est-ce
ce que le principe de responsabilité unique ?
Le principe de responsabilité unique stipule que les objets ne devraient avoir qu'une seule
responsabilité et qu'ils ne devraient avoir qu'une
qu' seule raison de changer.
En d'autres termes,
es, vous devez concevoir le logiciel de manière à ce que chaque classe soit liée à une
seule responsabilité. Cela ne signifie pas que votre classe ne doit contenir qu'une seule méthode ou
propriété, vous pouvez avoir plusieurs membres (méthodes ou propriétés)
propriétés) tant qu'ils sont liés à une
seule responsabilité ou fonctionnalité. Ainsi, avec l'aide de SRP, les classes deviennent plus petites et
plus propres et donc plus faciles à maintenir.
Exemple qui viole le principe de responsabilité unique ?
Comme vous pouvez vez le voir dans le code ci-dessous,
ci dessous, nous avons créé la classe ServiceFilm avec
quatre fonctionnalités telles que l'ajout et la suppression d’un film, la journalisation des erreurs ainsi
que l'envoi d'e-mails.
mails. Nous avons donc ajouté trop de responsabilités à la classe ServiceFilm et nous
avons violé le principe de responsabilité unique.
En effet, l'envoi d'e-mails
mails et la journalisation des erreurs ne font pas partie de la classe ServiceFilm. Il
devient alors très difficile de changer une responsabilité sans briser les autres responsabilités. Ainsi,
vous pouvez avoir plusieurs raisons de modifier la classe, non seulement pour changer la façon dont
les films sont gérés, mais en plus, vous pouvez également avoir des raisons supplémentaires de
changer la classe lorsque la logique de la journalisation des erreurs change ou bien la logique d’envoi
des e-mails change.
public class ServiceFilm
{
private readonly List<string
string> films = new List<string>();
private static int count;
public void AddFilm(string
string text)
{
try
{
films.Add($"{++count}
{++count}: {text}");
MailMessage mailMessage = new MailMessage("EMailFrom", "EMailTo",, "EMailSubject",
"EMailBody");
this.SendFilmEmail(mailMessage);
.SendFilmEmail(mailMessage);
}
catch (Exception ex)
{
System.IO.File.WriteAllText(
System.IO.File.WriteAllText(@"c:\ErrorLog.txt", ex.ToString());
}
}
public void DeleteFilm(int
int index)
{
try
{ films.RemoveAt(index); }
catch (Exception ex)
{
System.IO.File.WriteAllText(
System.IO.File.WriteAllText(@"c:\ErrorLog.txt", ex.ToString());
}
}
public void SendFilmEmail(MailMessage mailMessage)
{
try
{
// Here we need to write the Code for Email setting and sending the Film mail
}
catch (Exception ex)
{
System.IO.File.WriteAllText(
System.IO.File.WriteAllText(@"c:\ErrorLog.txt", ex.ToString());
}
}
}

En mélangeant plusieurs responsabilités dans une seule classe, nous obtenons les inconvénients
suivants,
● Code difficile à comprendre,
● Code difficile à tester,
● Risque de dupliquer la logique d'autres parties de l'application.

Voyons maintenant comment mettre en œuvre les fonctionnalités ci-dessus


ci dessus de manière à respecter
le principe de responsabilité unique.
mple qui respecte le principe de responsabilité unique ?
Exemple

Pour respecter le principe SRP, vous devez isoler les responsabilités. Pour le faire, vous auriez besoin
de définir une classe ou une interface pour chaque responsabilité. Lorsque vous concevez vos classes,
c
le nom de la classe doit désigner sa responsabilité.
Dans notre exemple, nous allons isoler les quatre responsabilités en créant pour chaque
responsabilité une classe. Dans la classe de ServiceFilm,, seules les fonctionnalités liées au Film seront
implémentées. La classe Logger ne sera utilisée qu'à des fins de journalisation. De même, la classe
Email va gérer les activités de messagerie.
public class ServiceFilmSPR
{
private readonly List<string
string> films = new List<string>();
private readonly Logger logger=new
logger= Logger();
private readonly MailSender emailSender = new MailSender();
private static int count = 0;

public int AddFilm(string


string text)
{
try
{
{++count}: {text}");
films.Add($"{++count}
emailSender.SendEmail(
emailSender.SendEmail("EMailFrom", "EMailTo", "EMailSubject", "EMailBody");
"EMailBody"
return count;
}
catch (Exception ex)
{
"Error Occurred while Adding Film", ex); return 0;
logger.Error("Error
}
}
public void DeleteFilm(int
int index)
{
Try { films.RemoveAt(index); }
catch (Exception ex)
{
"Error Occurred while Removing Film ",
logger.Error("Error , ex);
}
}
}
public class MailSender
{
private readonly Logger logger = new Logger();
public void SendEmail(string
string EMailFrom, string EMailTo, string EMailSubject, string EMailBody)
{
// Here we need to write the Code for Email setting and
and sending the email
}
}

public class Logger


{
public Logger()
{
// here we need to write the Code for initialization
// that is Creating the Log file with necesssary details
}
public void Info(string info)
{
// write the Code for info information into the ErrorLog text file
}
public void Debug(string info)
{
// write the Code for Debug information into the ErrorLog text file
}
public void Error(string message, Exception ex)
{
System.IO.File.WriteAllText(
System.IO.File.WriteAllText(@"c:\ErrorLog.txt", ex.ToString());
}
}

Avantages du principe de responsabilité unique

Les avantages de la SRP comprennent :


● Réduction de la complexité du code
● Augmentation de la lisibilité, l'extensibilité et facilite la maintenance
● Réduction des erreurs et amélioration de la réutilisation du code
● Meilleure testabilité
● Réduction du couplage

Principe ouvert-fermé
fermé (OCP)
ce que le principe ouvert fermé ?
Qu’est-ce

Le principe ouvert-fermé
fermé stipule que les entités logicielles telles que les modules, les classes, les
fonctions, etc. doivent être ouverte à l’extension mais fermée à la modification..
Ce principe suggère que nous devons concevoir une entité logicielle de telle sorte qu'elle permet
d'étendre son comportement sans modifier son code courant, lorsque de nouvelles exigences
surviennent et doit être misent en œuvre. La conformité à ce principe facilite la création
d’applications réutilisables et peuvent être maintenues facilement.
Pour réaliser ce principe, vous avez besoin d’utiliser des abstractions, qui est la clé, et de permettre
aux consommateurs d’accéder aux classes à travers ces abstractions définies. Les dérivés qui sont
créés à partir de ces abstractions sont clos pour modification depuis l'abstraction est fixé. Cependant,
vous pouvez étendre le comportement en créant de nouveaux dérivés de l'abstraction qui qu a déjà été
défini.
Exemple qui viole le principe ouvert fermé

Comme vous pouvez le voir dans le code ci-dessous,


ci dans la classe ServiceFilm,
ServiceFilm nous avons créé la
méthode GetFilmDiscount().
(). Cette dernière permet de calculer le montant final du film en fonction
fon
du son genre.

Jusqu’à maintenant, nous avons deux genres de film : Horreur et science-fiction.


science fiction. Nous avons donc
implémenté la logique en utilisant if-else.. Demain, si un autre genre de film entre en jeu, nous
devons modifier la logique de la méthode GetFilmDiscount() () en ajoutant un autre bloc else if au
code source. En modifiant le code source pour ajouter cette nouvelle exigence, nous violons le
principe ouvert fermé.

public enum FilmGenre


{
Horror, Fiction
};
public class ServiceFilm
{
public double GetFilmDiscount(Film film)
{
double finalAmount = 0;
if (film.Genre == FilmGenre.Horror)
{
finalAmount = film.Amount - 100;
}
else if (film.Genre == FilmGenre.Fiction)
{
Amount - 50;
finalAmount = film.Amount
}
return finalAmount;
}
}
Exemple qui respecte le principe ouvert fermé

Nous
us pouvons appliquer OCP en utilisant une interface, une classe abstraite, une classe générique,
des méthodes abstraites, des méthodes virtuelles et des méthodes d’extension lorsque vous
souhaitez étendre les fonctionnalités, selon le besoin.
Dans l'exemple ci-dessus,
dessus, nous créons une interface IServiceFilm contenant la méthode
GetFilmDiscount.. Pour chaque genre de film, nous lui créons une classe qui hérite de l’interface
IServiceFilm.
Lorsqu’un nouveau genre de film doit être ajouté, nous devons ajouter une autre classe qui hérite de
l’interface IServiceFilm.. En conséquence, l’entité parent servira de classe de base abstraite qui peut
être réutilisée avec des spécialisations supplémentaires
supplémentaires par héritage. Cependant, l'entité d'origine
est verrouillée pour permettre au programme d'être à la fois ouvert et fermé.
public interface IServiceFilm
{
public double GetFilmDiscount(Film film);
}
public class ServiceFilmHorror : IServiceFilm
{
public double GetFilmDiscount(Film
iscount(Film film)
{
return film.Amount - 100;
}
}
public class ServiceFilmFiction : IServiceFilm
{
public double GetFilmDiscount(Film film)
{
return film.Amount - 50;
}
}

Le principe de substitution de Liskov (LSP)


Qu’est-ce
ce que le principe de substitution de Liskov ?

Le principe de substitution de Liskov stipule qu’une classe de base doit être substituable par ses
classes dérivées sans que cela nécessite des modifications.
En termes simples, lorsque nous avons une classe de base et des relations de classe dérivée, c'est-à-
c'est
dire des relations d'héritage,, et nous pouvons remplacer l'objet d'une classe de base par un objet de
la classe dérivée, sans affecter le comportement de l'instance
l'instance de la classe de base, alors on dit qu'il
est dans le principe de substitution de Liskov.
Le but de ce principe est de vous aider à éviter certains problèmes lors de la modélisation de vos
objets en vous faisant prendre conscience des problèmes potentiels
potentiels qui ne sont pas si évident
lorsque vous utilisez l’héritage au moment du développement.
Exemple qui viole le principe de substitution de Liskov
Dans l'exemple suivant, nous avons créé une classe Duck avec deux méthodes Walk() et Eat(). Nous
avons créé aussi la classe ElectricDuck qui hérite de la classe Duck ainsi que ses deux méthodes Eat()
et Walk().

public class Duck


{
public string Color { get; set;
set }
public virtual void Walk()
{
Console.WriteLine("Duck
"Duck walks");
walks"
}
public virtual void Eat()
{
Console.WriteLine("Duck
"Duck eats");
eats"
}
}
public class ElectricDuck : Duck
{
public override void Walk()
{
"Electric Duck walks");
Console.WriteLine("Electric walks"
}
public override void Eat()
{
throw new Exception("I
"I don't eat");
eat"
}
}

static void Main(string[] args)


{
Duck duck = new ElectricDuck();
duck.Eat();
}

Comme vous pouvez le voir dans l'exemple ci-dessus,


ci dessus, nous avons stocker un objet de la classe
ElectricDuck dans une variable de référence Duck ( Duck duck = new ElectricDuck(); ).

Lorsque nous appelons la méthode Eat(), c'est-à-dire « duck.Eat() », nous obtenons une exception.
Cela signifie qu'une fois l'objet dérivé ElectricDuck est stocké dans objet parent Duck, le
comportement de ce dernier est également modifié. Ceci est contradictoire au principe LSP. Cette
dernière stipule que même si l'objet dérivé est remplacé par le parent, le comportement ne doit pas
être modifié.

L'idée de LSP est de s’assurer que les classes dérivées étendent les classes de base sans changer leurs
comportements.

Exemple qui respecte le principe de substitution de Liskov

Pour que notre exemple respecte le principe de Liskov, nous proposons la correction
suivante.
interface IDuck public virtual void Eat()
{ {
string Color { get; set; } "Duck eats");
Console.WriteLine("Duck eats"
void Walk(); }
} }
interface Iherbivorous public class ElectricDuck : IDuck
{ {
void Eat(); public string Color { get;
get set; }
}
public class Duck : IDuck, Iherbivorous public virtual void Walk()
{ {
public string Color { get; set;
set } "Electric Duck
Console.WriteLine("Electric
public virtual void Walk() walks");
{ }
Console.WriteLine("Duck walks"
"Duck walks"); }
}

Le principe de ségrégation d’interface (ISP)


Qu’est-ce
ce que le principe de ségrégation d’interface ?

Le principe de ségrégation d'interface


'interface stipule que les clients ne devraient pas être obligés
d'implémenter des méthodes qu'ils n'utilisent pas. Au lieu de construire des interfaces trop grandes,
grandes
vous devriez créer des interfaces plus petites (atomiques).
Décomposons la définition ci-dessus
dessus en deux parties.
● Premièrement, aucune classe ne devrait être forcée d'implémenter une ou plusieurs
méthodes d'une interface qu'elle n'utilise pas.
● Deuxièmement, au lieu de créer de grandes interfaces, créez plusieurs interfaces plus petites
dans le but que les clients ne pensent qu'aux méthodes qui les intéressent.

Conformément au principe de responsabilité unique de SOLID, comme les classes, les interfaces
int
devraient également avoir une responsabilité unique. Cela signifie que nous ne devrions forcer
aucune classe à implémenter une ou plusieurs méthodes dont elles n'ont pas besoin.
Exemple qui viole le principe de ségrégation d’interface

Supposons que vous voulez construire une sorte d'imprimante ou de scanner. Il existe aussi
l’imprimante multifonction qui effectue à la fois l'impression, la numérisation et la photocopie.
Donc, vous décidez de créer une interface pour tout type d’imprimante, nommée IMachine, comme
suit.
public interface IMachine
{
public void Scan(Document d);
public void Print(Document d);
public void Fax(Document d);
}

Tant que vous travaillez avec une imprimante multifonction, tout va bien car vous implémentez
toutes les méthodes de cette interface IMachine, comme suit.
public class MultiFunctionPrinter : IMachine
{
public void Print(Document d)
{
// do any think
}
public void Fax(Document d)
{
// do any think
}
public void Scan(Document d)
{
// do any think
}
}

Et si vous décidez, par exemple, de créer juste une imprimante à l'ancienne. Elle ne pourrait ni
numériser ni télécopier des documents. Elle pourrait juste imprimer.

Le problème est que vous n'avez qu'une seule grande interface avec beaucoup de responsabilités.
responsabi La
question qui se pose est « que feriez-vous
feriez vous à propos de la numérisation et de la télécopie, jetez-vous
jetez
une exception ». Et c'est là qu'intervient le principe de ségrégation des interfaces.
L'idée est de s'assurer que les classes dérivées ne doivent
doivent pas dépendre des méthodes dont elles
n'ont pas besoin. Au lieu d'avoir une grande interface, vous devriez avoir beaucoup d'interfaces plus
petites qui sont plus atomiques, dirons-nous
dirons nous en ce sens qu'elles sont en quelques sortes autonomes
et qu'elles couvrent
vrent une préoccupation particulière.
Exemple qui respecte le principe de ségrégation d’interface

Donc, ce que vous devez faire dans notre cas est de créer trois interfaces plus petites, une pour
l'impression, une pour la numérisation, et une pour la télécopie, comme suit.

public interface IPrinter public class Photocopier : IPrinter, IScanner


{ {
void Print(Document d); public void Print(Document d)
} {
public interface IScanner //
{ }
void Scan(Document d);
} public void Scan(Document d)
public class Printer : IPrinter {
{ //
public void Print(Document d) }
{ }
///
}
}

Le principe d'inversion de dépendance


Qu’est-cee que le principe d'inversion de dépendance ?

Le principe d'inversion de dépendances stipule que les modules de haut niveau du système ne
doivent pas dépendre directement des modules de bas niveau du système, mais plutôt d'une sorte
d'abstraction. Il stipule
le aussi que les abstractions ne doivent pas dépendre des détails. Les détails
devraient dépendre des abstractions

Ce principe vise principalement à réduire les dépendances entre les modules de code. Ceci est réalisé
par la définition des contrats pour les
les objets de bas niveau que les objets de haut niveau peuvent les
utiliser, sans qu’ils aient besoin de se soucier de l’implémentation spécifique fournie par les objets de
bas niveau.

Le DIP précise que dépendre des interfaces est moins risqué que de dépendre
dépendre d’implémentations
concrètes. Le fait d'avoir également des interfaces stables améliore la réutilisation du code. En
conséquence, ces interfaces bien conçues sont moins sujettes aux changements que les classes
concrètes qui les implémentent.

En offrant également une mise en œuvre qui dépend de l’interface, vous obtenez la possibilité de
choisir au moment de l’exécution, quelle implémentation est mieux adaptée à votre environnement
particulier.

Violation du principe d'inversion de dépendance :

Regardons ce bout de code.

public class Program public class PrinterWritter


{ {
static void Main(string[]
[] args) public void Write(string output)
{ { Console.WriteLine(output); }
Copy badCopy = new Copy(); }
badCopy.DoWork(); public class Copy
Console.ReadLine(); {
} private KeyboardReader reader;
} private PrinterWritter writter;
public class KeyboardReader public void DoWork()
{ {
public string Read() this.reader = new KeyboardReader();
{ return Console.ReadLine();
(); } this.writter = new PrinterWritter();
} this.writter.Write(this
this.reader.Read());
}
}

Notez que la classe Copy est une classe de haut niveau. Elle dépend à la fois de la classe
KeyBoardReader et de la classe PrinterWriter, qui sont des classes de bas niveau. En d'autres termes,
la classe copie dépend de l’implémentation concrète des deux classes KeyBoardReader et
PrinterWriter, et non de l’abstraction. Étant donné que DIP veut que les classes de haut niveau et de
bas niveau dépendent d'abstractions, ce code viole actuellement le principe principe d'inversion de
dépendance.
Solution pour le principe d'inversion de dépendance :

Nous avons implémenté le principe d'inversion de dépendance dans notre exemple où les classes de
haut niveau (classe Copy) ne doivent pas dépendre directement des classesclasses de bas niveau (classes
KeyBoardReader et PrinterWritter), mais plutôt d'une sorte d'abstraction (IReader et IPrinter). De
plus, l'abstraction (IReader et IPrinter) ne dépend pas des détails (KeyBoardReader et PrinterWritter)
mais les détails dépendent dee l'abstraction.
public class Program public class PrinterWriter : IWriter
{ {
public static void Main() public void Write(string output)
{ {
// Send output to Printer Console.WriteLine(string.Format(
.Format("Writing to
IReader r = new KeyboardReader(); printer {0}", output));
IWriter pw = new PrinterWriter(); }
Copy cp = new Copy(r, pw); }
cp.DoWork(); public class FileWriter : IWriter
// Send output to FileStream now {
IWriter fw = new FileWriter(); public void Write(string output)
Copy cpf = new Copy(r, fw); {
cpf.DoWork(); Console.WriteLine(string.Format(
.Format("Writing to
Console.ReadLine(); file {0}", output));
} }
} }
public interface IReader public class Copy
{ string Read(); } {
public class KeyboardReader : IReader private IReader reader;
{ private IWriter writer;
public string Read() public Copy(IReader
(IReader reader, IWriter writer)
{ return Console.ReadLine(); } { this.reader = reader; this.writer
.writer = writer; }
} public void DoWork()
public interface IWriter { this.writer.Write(this.reader.Read());
.reader.Read()); }
{ void Write(string output); } }

L’objectif principal de l'inversion de dépendance est de supprimer les dépendances de votre code.
Elle vous permet d'intégrer une certaine tolérance au changement dans votre code, de confronter le
changementt et de l'accompagner, permettant à notre système de s'adapter aux nouvelles exigences
importantes et aux règles changeantes.

Références
[1] https://docs.microsoft.com/en-us/dotnet/architecture/modern
us/dotnet/architecture/modern-web-apps-azure/architectural
azure/architectural-principles
[2] https://www.dotnetcurry.com/software-gardening/1176/solid-open-closed-principle
https://www.dotnetcurry.com/software
[3] https://docs.microsoft.com/en
https://docs.microsoft.com/en-us/archive/msdn-magazine/2014/may/csharp-bestbest-practices-dangers-of-
violating-solid-principles-in-csharp
[4] http://blogs.developpeur.org/fathi/archive/2011/11/26/pr-sentation-des-principes-solid.aspx
http://blogs.developpeur.org/fathi/archive/2011/11/26/pr solid.aspx

Les patrons de conception


Un patron de conception est un arrangement caractéristique de modules, reconnu comme bonne
pratique en réponse nse à un problème de conception d'un logiciel. Il décrit une solution standard,
utilisable dans la conception de différents logiciels.
Un patron de conception est issu de l'expérience des concepteurs de logiciels. Il décrit un
arrangement récurrent de rôless et d'actions joués par des modules d'un logiciel, et le nom du patron
sert de vocabulaire commun entre le concepteur et le programmeur. D'une manière analogue à un
motif de conception en architecture, le patron de conception décrit les grandes lignes d'une
d'u solution,
qui peuvent ensuite être modifiées et adaptées en fonction des besoins.
Disposable
Dans le Framework .Net Core, il existe deux types de ressources :
● Les ressources gérées sont des ressources que le garbage collector peut supprimer quand il
trouve
uve des objets non référencés.
● Les ressources non managées sont tout ce que le garbage collector ne peut pas gérer, par
exemple : les fichiers ouverts, les connexions de base de données ...

La question qui se pose, Comment pouvons-nous


pouvons nous libérer la mémoire si nous avons des ressources
non managées ? La réponse est l’utilisation de pattern Disposable.
Le pattern Disposable est un patron de conception qui est utilisé pour nettoyer des ressources non
managées. Il fournit un contrôle explicite, mettre en œuvre la méthode Dispose fournie par
l'interface IDisposable.. Le consommateur de l'objet devrait appeler cette méthode quand il a fini
d'utiliser l'objet.
Notez que vous devez fournir un nettoyage implicite
i en utilisant la méthode Finalize(), même lorsque
vous fournissez un contrôle explicite avec la méthode Dispose().
() fournit une sauvegarde pour éviter la fuite de ressource définitive si le programmeur
Finalize()
n’appelle pas Dispose.

Factory Pattern
Qu’est-ce
ce qu’un Factory Pattern ?
Le Factory Pattern est le modèle de conception le plus utilisé dans les langages de programmation
modernes comme Java et C#.
Le concept clé de ce pattern est d'abstraire la façon dont un objet est créé et instancié. Le but de
cette abstraction est d'éviter de coupler une implémentation avec des classes particulières ou la
manière dont chaque instance d'objet doit être créée et configurée. Le résultat est une
implémentation qui fonctionne comme un moyen abstrait pour la la création et l'initialisation d'objets,
qui à son tour suit le concept de séparation des préoccupations.
La séparation des préoccupations concerne les différents aspects de la fonctionnalité du logiciel. Par
exemple, la « logique métier" du logiciel est une
une préoccupation, et l'interface par laquelle une
personne utilise cette logique est une autre.
La séparation des préoccupations consiste à garder le code pour chacune de ces préoccupations
distinctes. La Modification de l'interface ne devrait pas exiger la
la modification du code de logique
métier, et vice versa.
Quels sont les avantages d’un Factory Pattern ?
Le Factory pattern est utilisé généralement pour séparer les responsabilités de création des objets.
Cette séparation permet :
● Aux gens de travailler sur des morceaux individuels du système dans l’isolement ;
● De faciliter la réutilisation ;
● D’assurer la maintenance d'un système ;
● D’ajouter des nouvelles fonctionnalités facilement ;
● De mieux comprendre le système ;

Repository
Qu’est-ce
ce qu’un Repository Pattern ?
Le repository pattern est un intermédiaire entre la couche métier et la couche d’accès aux données,
qui agit comme une collection d’objets en mémoire.
Le repository pattern est une couche d'abstraction qui fournit une approche bien organisée pour
maintenir une séparation entre l'accès aux données d'une application et les couches logiques métier.
Pour implémenter le repository pattern, vous pouvez créer une classe qui utilise la classe de contexte
et contient des méthodesdes telles que GetAll(), GetByID(), Insert(), Update() et Delete() qui vont
effectuer les opérations CRUD typiques sur une base de données.

Quels sont les avantages d’un Repository Pattern ?


Parmi les avantages d’utilisation du repository pattern, nous trouvons
tr :
● Réduit les requêtes en double
● Découple l'application de la couche d'accès aux données
● Rendre le code plus facile à maintenir et à lire
● Améliorer la testabilité de notre code.

Unit Of Work
Qu’est-ce qu’un Unit Of Work?
Une unité de travail est un modèle de conception décrit par Martin Fowler comme « maintenir une
liste d'objets affectés par une transaction commerciale et coordonne l'écriture des modifications et la
résolution des problèmes de concurrence. ».
En d'autres termes, l’Unit Of Work regroupe un ensemble d'opérations (d'insertion, de mise à jour,
de suppression, etc.) que nous souhaitons effectuer en une seule transaction, plutôt que de faire
plusieurs transactions sur une base de données. Il suit les changements qui nous intéressent jusqu'à
ce que nous soyons prêts à les enregistrer dans la base de données.
Quels sont les avantages d’un Unit Of Work ?
Unit Of Work est un design pattern qui répond à beaucoup de problèmes de développement et
apporte les avantages suivants :
● Il permet de garder en mémoire les modifications logiques de base de données dans un
ensemble cohérent.
● Il permet d’orchestrer les opérations de base sous forme de transactions pour pouvoir
annuler les modifications en cas de problèmes.
● Il permet d’isoler votre application des modifications de la couche de données et ainsi
faciliter les tests.
● Il coordonne le travail des différents Repositories en ne créant qu’un seul contexte partagé.

Références
[1]https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice
us/dotnet/architecture/microservices/microservice-ddd
ddd-cqrs-
patterns/infrastructure-persistence--layer-design
[2] https://docs.microsoft.com/en
https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started
started-with-ef-5-using-
mvc-4/implementing-the-repository
repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
application
[3]https://blog.dcube.fr/index.php/2019/09/05/generic
://blog.dcube.fr/index.php/2019/09/05/generic-repository-unit-of-work-et-entity
entity-framework/
[4]https://www.oodesign.com/factory
https://www.oodesign.com/factory-pattern.html
[5]https://www.codingame.com/playgrounds/36103/design
https://www.codingame.com/playgrounds/36103/design-pattern-factory-abstract-factory/design
factory/design-pattern-
factory

Vous aimerez peut-être aussi