@@ -103,9 +103,26 @@ Ces éléments et leurs intéractions peuvent être modéliser sur un diagramme
...
@@ -103,9 +103,26 @@ Ces éléments et leurs intéractions peuvent être modéliser sur un diagramme
### Héritage
### Héritage
Tous les controllers héritent directement ou indirectement de VitisAbstractController.
Ce qui vous permet de facilement accéder aux services principaux de l'application :
- Accés au disque
- Accés à la base de donnée
- Utilisation des properties
- Configuration de la route
- Gestion des logs
- ...
### Implémentation
### Implémentation
### Traits
L'implémentation est utilisé à plusieurs endroit dans l'application.
Prenons l'exemple du service d'accés à la base de donnée, ils implémentent tous l'interface DataAccessor.
Vous avez donc la possibilité d'appeler les mêmes méthode sur toutes ces classes, avec les même paramètre et avec le même type de retour.
Biensûr en cas d'un typage large du retour le comportement ne pourra pas être stable, il faut donc utiliser un typage fort sur ce genre de méthode de développement.
L'avantage de ce genre de pratique, si dans le futur Vitis doit par exemple se connecter à un nouveau SGBD (mysql par exemple), il suffira de développer un MsqlAccessor qui implémentera DataAccessor, pour que toute l'application fonctionne sans modification. A condition de ne pas avoir utiliser des requêtes SQL directement dans le code via la connexion de DBAL.
### Utilisation de l'interface de manipulation des fichiers
### Utilisation de l'interface de manipulation des fichiers
...
@@ -115,13 +132,462 @@ A partir du moment ou votre controlleur hérite de `VitisAbstractController`, il
...
@@ -115,13 +132,462 @@ A partir du moment ou votre controlleur hérite de `VitisAbstractController`, il
Le FileManager a une relation de composition avec l'une des deux classes ou les deux classes implémentant L'interface `FileAccessorInterface`, à savoir `LocalAccessor` et `S3Accessor`. La nuance d'une ou deux étant compliqué je rentre pas dans le détail.
Le FileManager a une relation de composition avec l'une des deux classes ou les deux classes implémentant L'interface `FileAccessorInterface`, à savoir `LocalAccessor` et `S3Accessor`. La nuance d'une ou deux étant compliqué je rentre pas dans le détail.
Le Filemanager se comporte alors comme une **Factory Method**(on en parlera plus tard), qui va fournir l'objet que l'on veut en fonction de la configuration de Vitis. Cette classe va agir comme une couche d'abstraction pour le développeur, c'est à dire qu'il passera le chemin d'écriture et le code lui retournera l'objet adapté pour interagir avec le systéme de fichier utilisé par Vitis.
Le Filemanager se comporte alors comme une **Factory Method**mais en version simplifiée, qui va fournir l'objet que l'on veut en fonction de la configuration de Vitis. Cette classe va agir comme une couche d'abstraction pour le développeur, c'est à dire qu'il passera le chemin d'écriture et le code lui retournera l'objet adapté pour interagir avec le systéme de fichier utilisé par Vitis.
## Autres mot clés
## Autres mot clés
final
-**final** : Signifie que les enfant héritant de cette classe ne pourront pas surcharger cette fonction.
-**self** : Permet d'accéder au constante ou méthode statique d'un objet sans l'instancier.
-**static** : Permet de définir qu'une méthode peut être utiliser sans instanciation de sa classe, c'est à dire qu'elle ne doit pas utiliser **this** pour fonctionner. C'est un usage qui tombe de plus en plus dans l'oubli, cependant il reste utile. Autre utilisation de ce mot clé en PHP, il permet d'utiliser la valeur d'une constante surcharger dans l'enfant depuis un parent.
## Design Pattern
Un design pattern, également connu sous le nom de patron de conception, est une solution éprouvée et réutilisable à un problème courant dans la conception de logiciels. Il s'agit d'un modèle de conception générique qui peut être appliqué à différentes situations pour résoudre des problèmes similaires.
Les design patterns fournissent des approches structurées et éprouvées pour résoudre des problèmes de conception logicielle tels que la création d'objets, la gestion des relations entre les objets, la réutilisation de code, l'organisation du flux d'exécution, etc. Ils permettent de capturer l'expertise et l'expérience des développeurs dans un format réutilisable, favorisant ainsi la clarté, la maintenabilité et l'évolutivité du code.
Les design patterns ne sont pas des morceaux de code prêts à l'emploi, mais plutôt des modèles conceptuels qui décrivent comment résoudre un problème de conception spécifique. Ils fournissent des directives générales, des structures et des interactions entre les composants logiciels, permettant aux développeurs de créer des solutions flexibles, évolutives et robustes.
Il existe de nombreux types de design patterns, tels que les patterns de création, les patterns structurels et les patterns comportementaux, chacun se concentrant sur des aspects spécifiques de la conception logicielle.
On peut aussi s'en inspiré sans forcément les utilisés de manière brut.
### Patterns de création
Il se concentre sur les mécanismes de création d'objets en encapsulant le processus de création et en fournissant une interface générique pour créer différents types d'objets.
Les patterns de création visent à fournir des approches flexibles et modulaires pour créer des objets, en évitant les dépendances directes entre les classes et en améliorant la maintenabilité, la réutilisabilité et la souplesse du code.
Les patterns de création résolvent généralement des problèmes tels que :
- Comment créer des objets sans couplage étroit avec les classes concrètes.
- Comment configurer et initialiser des objets complexes.
- Comment éviter la duplication de code lors de la création d'objets similaires.
- Comment cacher les détails de création d'objets aux clients.
Il existe plusieurs patterns de création couramment utilisés, tels que :
- Singleton : garantit qu'une classe n'a qu'une seule instance et fournit un point d'accès global à cette instance.
```php
classSingleton{
privatestatic$instance;
privatefunction__construct(){
// Constructeur privé pour empêcher l'instanciation directe depuis l'extérieur de la classe
}
publicstaticfunctiongetInstance(){
if(self::$instance===null){
self::$instance=newSingleton();
}
returnself::$instance;
}
}
```
- Factory Method : définit une interface pour créer des objets, mais permet aux sous-classes de décider quelle classe concrète instancier.
```php
interfaceAnimal{
publicfunctionmakeSound();
}
classDogimplementsAnimal{
publicfunctionmakeSound(){
echo"Woof!";
}
}
classCatimplementsAnimal{
publicfunctionmakeSound(){
echo"Meow!";
}
}
interfaceAnimalFactory{
publicfunctioncreateAnimal();
}
classDogFactoryimplementsAnimalFactory{
publicfunctioncreateAnimal(){
returnnewDog();
}
}
classCatFactoryimplementsAnimalFactory{
publicfunctioncreateAnimal(){
returnnewCat();
}
}
```
- Abstract Factory : fournit une interface pour créer des familles d'objets liés ou dépendants sans spécifier leurs classes concrètes.
- Builder : permet de construire un objet complexe étape par étape, en séparant le processus de construction de la représentation finale de l'objet.
- Prototype : permet de créer de nouvelles instances en clonant des objets existants, évitant ainsi les coûts de création d'objets à partir de zéro.
### Patterns structurels
Les patterns structurels sont axés sur l'organisation des objets en utilisant l'héritage, la composition et l'agrégation pour atteindre un certain objectif. Ils permettent de créer des structures plus grandes à partir de petites classes et d'établir des relations entre les objets de manière à simplifier le système global.
Les patterns structurels sont souvent utilisés pour résoudre des problèmes liés à la composition d'objets, à la réutilisation du code et à l'optimisation des performances. Ils aident à simplifier les interactions entre les objets, à rendre le code plus flexible et maintenable, et à favoriser une meilleure séparation des responsabilités.
Ces patterns structurels offrent des solutions génériques aux problèmes de structure et d'organisation des objets dans un système. Ils favorisent une meilleure conception logicielle en favorisant la modularité, la flexibilité et la réutilisabilité du code.
Certains exemples de patterns structurels couramment utilisés sont :
- Adapter : permet d'adapter une interface existante à une autre interface attendue par le client.
- Proxy : fournit un substitut ou une représentation de substitution pour un objet afin de contrôler son accès.
- Decorator : permet d'ajouter des fonctionnalités supplémentaires à un objet de manière dynamique.
```php
interfaceShape{
publicfunctiondraw();
}
classRectangleimplementsShape{
publicfunctiondraw(){
echo"Drawing a rectangle.<br>";
}
}
classCircleimplementsShape{
publicfunctiondraw(){
echo"Drawing a circle.<br>";
}
}
abstractclassShapeDecoratorimplementsShape{
protected$decoratedShape;
publicfunction__construct(Shape$decoratedShape){
$this->decoratedShape=$decoratedShape;
}
publicfunctiondraw(){
$this->decoratedShape->draw();
}
}
classRedShapeDecoratorextendsShapeDecorator{
publicfunctiondraw(){
parent::draw();
$this->setRedBorder();
}
privatefunctionsetRedBorder(){
echo"Setting red border.<br>";
}
}
```
- Bridge : sépare une abstraction de son implémentation, permettant à chacune d'évoluer indépendamment.
```php
interfaceColor{
publicfunctionapplyColor();
}
classRedimplementsColor{
publicfunctionapplyColor(){
echo"Applying red color.<br>";
}
}
classBlueimplementsColor{
publicfunctionapplyColor(){
echo"Applying blue color.<br>";
}
}
abstractclassShape{
protected$color;
publicfunction__construct(Color$color){
$this->color=$color;
}
publicabstractfunctiondraw();
}
classCircleextendsShape{
publicfunctiondraw(){
echo"Drawing a circle. ";
$this->color->applyColor();
}
}
classRectangleextendsShape{
publicfunctiondraw(){
echo"Drawing a rectangle. ";
$this->color->applyColor();
}
}
```
### Patterns comportementaux
Les patterns comportementaux permettent de modéliser les comportements des objets et d'organiser les interactions entre eux de manière efficace. Ils visent à encapsuler les comportements spécifiques dans des objets distincts et à promouvoir une meilleure séparation des responsabilités.
Voici quelques exemples de patterns comportementaux couramment utilisés :
- Observer : Ce pattern définit une dépendance un-à-plusieurs entre objets, de sorte que lorsqu'un objet change d'état, tous ses dépendants en sont notifiés et mis à jour automatiquement.
```php
interfaceObserver{
publicfunctionupdate($data);
}
interfaceSubject{
publicfunctionattach(Observer$observer);
publicfunctiondetach(Observer$observer);
publicfunctionnotify($data);
}
classConcreteSubjectimplementsSubject{
private$observers=[];
publicfunctionattach(Observer$observer){
$this->observers[]=$observer;
}
publicfunctiondetach(Observer$observer){
$index=array_search($observer,$this->observers);
if($index!==false){
unset($this->observers[$index]);
}
}
publicfunctionnotify($data){
foreach($this->observersas$observer){
$observer->update($data);
}
}
publicfunctiondoSomething(){
// Faire quelque chose...
// Notifier les observateurs
$this->notify("Données mises à jour");
}
}
classConcreteObserverimplementsObserver{
publicfunctionupdate($data){
echo"Observateur notifié avec les données : ".$data."<br>";
}
}
```
- Strategy : Ce pattern permet de définir une famille d'algorithmes interchangeables. Les algorithmes sont encapsulés dans des classes distinctes, ce qui permet de les sélectionner et de les utiliser dynamiquement selon les besoins.
- Template Method : Ce pattern définit le squelette d'un algorithme dans une classe de base, en déléguant l'implémentation de certaines étapes aux sous-classes. Il permet ainsi de personnaliser le comportement de l'algorithme sans en modifier la structure globale.
```php
abstractclassGame{
abstractprotectedfunctioninitialize();
abstractprotectedfunctionstartPlay();
abstractprotectedfunctionendPlay();
publicfinalfunctionplay(){
$this->initialize();
$this->startPlay();
$this->endPlay();
}
}
classFootballGameextendsGame{
protectedfunctioninitialize(){
echo"Football game initialized.<br>";
}
protectedfunctionstartPlay(){
echo"Football game started.<br>";
}
protectedfunctionendPlay(){
echo"Football game ended.<br>";
}
}
classBasketballGameextendsGame{
protectedfunctioninitialize(){
echo"Basketball game initialized.<br>";
}
protectedfunctionstartPlay(){
echo"Basketball game started.<br>";
}
protectedfunctionendPlay(){
echo"Basketball game ended.<br>";
}
}
```
- Command : Ce pattern encapsule une demande en tant qu'objet, ce qui permet de paramétrer les clients avec différentes demandes, de les mettre en file d'attente, de les enregistrer et de les annuler.
- Iterator : Ce pattern fournit un moyen d'accéder séquentiellement aux éléments d'une collection sans exposer la structure interne de la collection. Il permet d'itérer de manière transparente sur les éléments d'une collection.
- State : Ce pattern permet à un objet de modifier son comportement interne lorsqu'il change d'état. Il encapsule chaque état possible dans une classe distincte et permet au contexte d'alterner entre les états de manière transparente.
Ces patterns comportementaux offrent des solutions génériques pour gérer les interactions et les comportements des objets dans un système. Ils améliorent la flexibilité, la réutilisabilité et la maintenabilité du code en promouvant une meilleure séparation des responsabilités et une modularité accrue.