diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f023ee932b1e8167bc682990286bf45c572ec907..51b9c86fb4bc40cb979edd2f0601450534a41d41 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,6 +13,7 @@ deploy-gtf-fr-documentation-dev : # - pip install sphinx-markdown-parser # - pip install myst-parser # - pip install pymdown-extensions + - pip install sphinxcontrib-phpdomain - sphinx-build -b html source build - aws s3 cp build/ s3://$S3_BUCKET_NAME_DEV_fr/ --recursive tags: diff --git a/README.md b/README.md index 29fa1f511ca076e1362527349a837e35d9f97539..b7a66763fe29b31961ba49f6d42362d5efce514d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ pip install sphinx_rtd_theme==0.5.2 pip install sphinx-markdown-parser pip install myst-parser pip install pymdown-extensions +pip install sphinxcontrib-phpdomain sphinx-build -b html source build ``` diff --git a/source/_static/ressources/uml/UMLNotationSummary.pdf b/source/_static/ressources/uml/UMLNotationSummary.pdf new file mode 100644 index 0000000000000000000000000000000000000000..04715b61845da46dfbffbdfa645f3ea5c10b1e7a Binary files /dev/null and b/source/_static/ressources/uml/UMLNotationSummary.pdf differ diff --git a/source/concept/index.rst b/source/concept/index.rst index ded59d64fea4678a70a5fa5d91605c9c2f2df229..6c9d06147b29c5a5822bff867a70b7a4b51b1d25 100644 --- a/source/concept/index.rst +++ b/source/concept/index.rst @@ -1,4 +1,4 @@ -Documentation Veremes sur les notions théoriques +Notions théoriques ================================================ .. image:: /images/Veremes_Black.svg @@ -14,4 +14,5 @@ Documentation Veremes sur les notions théoriques :glob: system/index.rst - bdd/index.rst \ No newline at end of file + bdd/index.rst + poo/index.rst \ No newline at end of file diff --git a/source/concept/poo/general.md b/source/concept/poo/general.md new file mode 100644 index 0000000000000000000000000000000000000000..ab1d7f349443605db091655295d9281dc6510b6d --- /dev/null +++ b/source/concept/poo/general.md @@ -0,0 +1,968 @@ +# Introduction + +La programmation orientée objet (POO) est un paradigme de programmation qui permet de modéliser des concepts du monde réel sous forme d'objets. +Veremes utilise principalement le PHP et le TypeScript pour développer qui sont deux langages prenant en charge ce paradigme. + +Les objets sont des instances de classes, qui sont des modèles pour la création d'objets. Les classes contiennent des propriétés, qui sont des variables qui stockent l'état de l'objet, et des méthodes, qui sont des fonctions qui définissent le comportement de l'objet. + +L'encapsulation est un concept clé de la POO qui consiste à masquer l'état interne d'un objet et à fournir une interface publique pour interagir avec cet objet. + +L'héritage est un autre concept important de la POO qui permet à une classe d'hériter des propriétés et des méthodes d'une autre classe parente. Cela permet de créer des classes dérivées qui héritent des fonctionnalités de la classe parente et peuvent également ajouter leurs propres fonctionnalités. + +Le polymorphisme est un autre concept clé de la POO qui permet à un objet d'être traité comme un objet d'un type différent. Cela permet de créer des classes qui partagent une interface commune mais ont des comportements différents. + +En utilisant ces concepts de base, la POO permet de créer des programmes plus modulaires, maintenables et évolutifs, car les objets peuvent être réutilisés et étendus de manière flexible. + +## Concepts clés de la POO + +### Classes, Interface, objets + +Une classe est un modèle pour la création d'objets qui définit les propriétés et les méthodes que posséderont les objets créés à partir de cette classe. Les propriétés sont des variables qui stockent l'état de l'objet, tandis que les méthodes sont des fonctions qui définissent le comportement de l'objet. C'est une sorte de plan pour créer des objets. + + + +Un objet est une instance d'une classe, c'est-à-dire qu'il est créé à partir d'un modèle de classe. Les objets ont des propriétés et des méthodes qui sont définies dans leur classe correspondante. + +L'encapsulation est un concept clé de la POO qui consiste à masquer l'état interne d'un objet et à fournir une interface publique pour interagir avec cet objet. Les niveaux de visibilité des propriétés (**public**, **private** et **protected**) sont utilisés pour définir l'accès à ces propriétés. + +Les objets ont une portée limitée à leur cycle de vie, c'est-à-dire qu'ils existent uniquement tant qu'ils sont référencés par une variable. Lorsqu'une variable qui fait référence à un objet est détruite ou affectée à une autre valeur, l'objet est libéré de la mémoire. + + + +ci-dessous un exemple concret de classe et de son utilisation: +```php +// Définition de la classe +class XWing { + // propriétés + public owner; + private hasWeapons = true; + + // méthodes + public function fly() : void { + error_log($this->owner ' décolle de Yavin IV'); + } + + public function shoot() : int { + if ($this->hasWeapons) { + error_log($this->owner ' tire sur l\'ennemi'); + } else { + error_log($this->owner ' ne peux pas tirer'); + } + } +} + + +// Utilisation de la classe + +$YL = new XWing(); +$YL->owner = 'Yellow leader' + +$YL->fly(); // print : Yellow leader décolle de Yavin IV + +``` + +L'interface va définir le comportement d'une classe. + +Il faut voir l'interface comme un contrat qui va imposer à la classe l'utilisant des attributs et des méthodes sans les définir. + +Exemple : Je signe un contrat de travail, je m'engage à réaliser les tâches qui m'incombent en tant que salarié. + +### Interactions et abstraction + +Les objets peuvent intéragir les un avec les autres de différentes manières. + +Un objet peut utiliser un autre objet, l'objet composant fait alors parti intégrante d' l'objet conteneur, les deux objets sont alors lié et la destruction de l'objet conteneur entraine la destruction de l'autre objet. On parle alors de **composition**, exemple : Une voiture est composé d'un moteur, d'une carroserie, ... La destruction de la voiture entraine la destruction des autres sous-objets. + +Un objet peut être composé d'un ensemble d'objets, on parle alors d'**aggrégation**. Dans ce cas l'objet conteneur contient plusieurs sous-objet d'un même type. Le lien est moins fort que la composition, dans le sens ou la desturction du conteneur n'entrainera pas forcément la destruction des autres objets car il ne les référence pas directement. On parle d'aggrégation, exemple : une bibliothèque contient des livres. + +Une classe peut **hériter** d'une autre classe, on parle alors de **spécialisation ou d'héritage**. La classe enfant va alors hériter des propriétés et des méthodes de la classe parente, la classe enfant peut comporter d'autre propriétés et d'autre méthode et peut surcharger également les éléments du parents. Ce mécanisme permet d'éviter la duplication de code. + +Une classe peut **implémenter** une interface, la classe en question devra alors avoir défini les méthode et contenir les attributs spécifié par l'interface. + +Ces deux dernier concepts permettent à l'objet de prendre différentes formes ou à modifier son comportement en fonction du contexte d'utilisation. On parle alors de **polymorphisme**. + +Une classe peut ne pas être prévue pour créer des objet mais pour servir de parent à plusieurs classes enfants dans le but de mutualiser du code, on parle alors de **classe abstraite**. On peut aussi parler de **méthodes abstraites** qui imposent les mêmes contraintes qu'une interface aux classe enfant (elle devront être surchargées obligatoirement). + +Dans la majorité des langages (c'est le cas dans ceux utilisés par Veremes), **une classe ne hérité que d'une seule autre classe en revanche elle peut implémenter autant d'interface qu'elle veut**. + +Dans le cas de PHP, ll existe un autre élément permettant la mutualisation de code redondant, il s'agit du **trait**. Le trait à la différence de l'interface autorise l'implémentation d'un code par défaut, il s'agit d'une collection de méthodes, c'est trés pratique en revanche c'est à utiliser avec précaution, le code implémenté dans le trait impliquant un contexte d'utilisation qui n'est pas forcément implémenter par votre classe ou vos objets. + +Les visibilités auront un impact sur l'usage du code mutualisé. + +Le code **privé** ne sera accessible que par la **classe elle-même**. +Le code **protégé** sera accessible par **la classe et ses enfants**. +Le code **public** sera accessible par **tout le monde** y compris de l'extérieur de l'objet final. + +Sur des exemples concrets : Vous pouvez interagir avec votre voitures via le volant, les pédales, des boutons ce serait des méthodes publics de l'objet voiture. Un Camion à le même comportement qu'une voiture lorsqu'on interagit avec le volant on pourrait parler de comportement protégé d'un véhicule. L'électronique de la voiture fait transiter les informations depuis les boutons aux composants électronique finaux par un flux spcifique et qui m'est totalement opaque, on est sur un comportement privé. + +### Modélisation + +Ces éléments et leurs intéractions peuvent être modéliser sur un diagramme de classe grâce à l'[UML](http://documentation-dev.veremes.net/dev/fr/_static/ressources/uml/UMLNotationSummary.pdf) + +## Exemple d'utilisation dans Vitis + +### 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 + +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 + + + +A partir du moment ou votre controlleur hérite de `VitisAbstractController`, il pourra accéder au `FileManager` car il y a une relation de composition protégé entre les deux classes. + +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** 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 + +- **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 +class Singleton { + private static $instance; + + private function __construct() { + // Constructeur privé pour empêcher l'instanciation directe depuis l'extérieur de la classe + } + + public static function getInstance() { + if (self::$instance === null) { + self::$instance = new Singleton(); + } + return self::$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 +interface Animal { + public function makeSound(); +} + +class Dog implements Animal { + public function makeSound() { + echo "Woof!"; + } +} + +class Cat implements Animal { + public function makeSound() { + echo "Meow!"; + } +} + +interface AnimalFactory { + public function createAnimal(); +} + +class DogFactory implements AnimalFactory { + public function createAnimal() { + return new Dog(); + } +} + +class CatFactory implements AnimalFactory { + public function createAnimal() { + return new Cat(); + } +} +``` +- Abstract Factory : fournit une interface pour créer des familles d'objets liés ou dépendants sans spécifier leurs classes concrètes. +```php +// Produit abstrait A +interface AbstractProductA { + public function operationA(); +} + +// Produit abstrait B +interface AbstractProductB { + public function operationB(); +} + +// Implémentation concrète du produit A +class ConcreteProductA1 implements AbstractProductA { + public function operationA() { + echo "Opération A pour le produit A1\n"; + } +} + +// Implémentation concrète du produit B +class ConcreteProductB1 implements AbstractProductB { + public function operationB() { + echo "Opération B pour le produit B1\n"; + } +} + +// Fabrique abstraite +interface AbstractFactory { + public function createProductA(): AbstractProductA; + public function createProductB(): AbstractProductB; +} + +// Implémentation concrète de la fabrique abstraite +class ConcreteFactory1 implements AbstractFactory { + public function createProductA(): AbstractProductA { + return new ConcreteProductA1(); + } + + public function createProductB(): AbstractProductB { + return new ConcreteProductB1(); + } +} + +// Client utilisant la fabrique abstraite +class Client { + private $productA; + private $productB; + + public function __construct(AbstractFactory $factory) { + $this->productA = $factory->createProductA(); + $this->productB = $factory->createProductB(); + } + + public function execute() { + $this->productA->operationA(); + $this->productB->operationB(); + } +} + +// Utilisation de l'Abstract Factory +$factory = new ConcreteFactory1(); +$client = new Client($factory); +$client->execute(); +``` +- 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. +```php +// Produit final +class Product { + private $partA; + private $partB; + private $partC; + + public function setPartA($partA) { + $this->partA = $partA; + } + + public function setPartB($partB) { + $this->partB = $partB; + } + + public function setPartC($partC) { + $this->partC = $partC; + } + + public function getInfo() { + return "Part A: " . $this->partA . ", Part B: " . $this->partB . ", Part C: " . $this->partC; + } +} + +// Builder abstrait +abstract class Builder { + protected $product; + + public function createProduct() { + $this->product = new Product(); + } + + public abstract function buildPartA(); + public abstract function buildPartB(); + public abstract function buildPartC(); + + public function getProduct() { + return $this->product; + } +} + +// Implémentation concrète du builder +class ConcreteBuilder extends Builder { + public function buildPartA() { + $this->product->setPartA("Part A built"); + } + + public function buildPartB() { + $this->product->setPartB("Part B built"); + } + + public function buildPartC() { + $this->product->setPartC("Part C built"); + } +} + +// Directeur +class Director { + private $builder; + + public function setBuilder(Builder $builder) { + $this->builder = $builder; + } + + public function buildProduct() { + $this->builder->createProduct(); + $this->builder->buildPartA(); + $this->builder->buildPartB(); + $this->builder->buildPartC(); + + return $this->builder->getProduct(); + } +} + +// Utilisation du pattern Builder +$builder = new ConcreteBuilder(); +$director = new Director(); +$director->setBuilder($builder); +$product = $director->buildProduct(); +echo $product->getInfo(); +``` +- 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. +```php +// Prototype abstrait +abstract class Prototype { + protected $name; + + public abstract function clone(): Prototype; + + public function getName() { + return $this->name; + } + + public function setName($name) { + $this->name = $name; + } +} + +// Implémentation concrète du prototype +class ConcretePrototype extends Prototype { + public function __construct() { + $this->name = "ConcretePrototype"; + } + + public function clone(): Prototype { + return clone $this; + } +} + +// Utilisation du pattern Prototype +$prototype = new ConcretePrototype(); +$clone = $prototype->clone(); +$clone->setName("Clone"); + +echo "Prototype: " . $prototype->getName() . "\n"; +echo "Clone: " . $clone->getName(); +``` + + +### 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. +```php +interface MediaPlayer { + public function play($fileName); +} + +interface AdvancedMediaPlayer { + public function playMp4($fileName); + public function playAvi($fileName); +} + +class Mp4Player implements AdvancedMediaPlayer { + public function playMp4($fileName) { + echo "Playing MP4 file: " . $fileName . "<br>"; + } + + public function playAvi($fileName) { + // Ne fait rien + } +} + +class AviPlayer implements AdvancedMediaPlayer { + public function playMp4($fileName) { + // Ne fait rien + } + + public function playAvi($fileName) { + echo "Playing AVI file: " . $fileName . "<br>"; + } +} + +class MediaAdapter implements MediaPlayer { + private $advancedMediaPlayer; + + public function __construct($audioType) { + if ($audioType === "mp4") { + $this->advancedMediaPlayer = new Mp4Player(); + } else if ($audioType === "avi") { + $this->advancedMediaPlayer = new AviPlayer(); + } + } + + public function play($fileName) { + $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION); + if ($fileExtension === "mp4") { + $this->advancedMediaPlayer->playMp4($fileName); + } else if ($fileExtension === "avi") { + $this->advancedMediaPlayer->playAvi($fileName); + } + } +} + +class AudioPlayer implements MediaPlayer { + public function play($fileName) { + $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION); + if ($fileExtension === "mp3") { + echo "Playing MP3 file: " . $fileName . "<br>"; + } else if ($fileExtension === "mp4" || $fileExtension === "avi") { + $mediaAdapter = new MediaAdapter($fileExtension); + $mediaAdapter->play($fileName); + } else { + echo "Invalid media format: " . $fileName . "<br>"; + } + } +} +``` +- Composite : permet de traiter un groupe d'objets de la même manière qu'un objet individuel. +```php +interface Employee { + public function getName(); + public function getSalary(); +} + +class Developer implements Employee { + private $name; + private $salary; + + public function __construct($name, $salary) { + $this->name = $name; + $this->salary = $salary; + } + + public function getName() { + return $this->name; + } + + public function getSalary() { + return $this->salary; + } +} + +class Manager implements Employee { + private $name; + private $salary; + private $subordinates; + + public function __construct($name, $salary) { + $this->name = $name; + $this->salary = $salary; + $this->subordinates = []; + } + + public function getName() { + return $this->name; + } + + public function getSalary() { + return $this->salary; + } + + public function addSubordinate(Employee $employee) { + $this->subordinates[] = $employee; + } + + public function removeSubordinate(Employee $employee) { + $index = array_search($employee, $this->subordinates); + if ($index !== false) { + unset($this->subordinates[$index]); + } + } + + public function getSubordinates() { + return $this->subordinates; + } +} +``` +- Proxy : fournit un substitut ou une représentation de substitution pour un objet afin de contrôler son accès. +```php +// Sujet abstrait +interface Subject { + public function request(); +} + +// Sujet concret +class RealSubject implements Subject { + public function request() { + echo "RealSubject: Traitement de la requête.\n"; + } +} + +// Proxy +class Proxy implements Subject { + private $realSubject; + + public function request() { + if ($this->realSubject === null) { + $this->realSubject = new RealSubject(); + } + + $this->beforeRequest(); + $this->realSubject->request(); + $this->afterRequest(); + } + + private function beforeRequest() { + echo "Proxy: Avant la requête.\n"; + } + + private function afterRequest() { + echo "Proxy: Après la requête.\n"; + } +} + +// Utilisation du pattern Proxy +$proxy = new Proxy(); +$proxy->request(); +``` +- Decorator : permet d'ajouter des fonctionnalités supplémentaires à un objet de manière dynamique. +```php +interface Shape { + public function draw(); +} + +class Rectangle implements Shape { + public function draw() { + echo "Drawing a rectangle.<br>"; + } +} + +class Circle implements Shape { + public function draw() { + echo "Drawing a circle.<br>"; + } +} + +abstract class ShapeDecorator implements Shape { + protected $decoratedShape; + + public function __construct(Shape $decoratedShape) { + $this->decoratedShape = $decoratedShape; + } + + public function draw() { + $this->decoratedShape->draw(); + } +} + +class RedShapeDecorator extends ShapeDecorator { + public function draw() { + parent::draw(); + $this->setRedBorder(); + } + + private function setRedBorder() { + echo "Setting red border.<br>"; + } +} +``` +- Bridge : sépare une abstraction de son implémentation, permettant à chacune d'évoluer indépendamment. +```php +interface Color { + public function applyColor(); +} + +class Red implements Color { + public function applyColor() { + echo "Applying red color.<br>"; + } +} + +class Blue implements Color { + public function applyColor() { + echo "Applying blue color.<br>"; + } +} + +abstract class Shape { + protected $color; + + public function __construct(Color $color) { + $this->color = $color; + } + + public abstract function draw(); +} + +class Circle extends Shape { + public function draw() { + echo "Drawing a circle. "; + $this->color->applyColor(); + } +} + +class Rectangle extends Shape { + public function draw() { + 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 +interface Observer { + public function update($data); +} + +interface Subject { + public function attach(Observer $observer); + public function detach(Observer $observer); + public function notify($data); +} + +class ConcreteSubject implements Subject { + private $observers = []; + + public function attach(Observer $observer) { + $this->observers[] = $observer; + } + + public function detach(Observer $observer) { + $index = array_search($observer, $this->observers); + if ($index !== false) { + unset($this->observers[$index]); + } + } + + public function notify($data) { + foreach ($this->observers as $observer) { + $observer->update($data); + } + } + + public function doSomething() { + // Faire quelque chose... + + // Notifier les observateurs + $this->notify("Données mises à jour"); + } +} + +class ConcreteObserver implements Observer { + public function update($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. +```php +interface PaymentStrategy { + public function pay($amount); +} + +class CreditCardStrategy implements PaymentStrategy { + private $cardNumber; + private $expirationDate; + private $cvv; + + public function __construct($cardNumber, $expirationDate, $cvv) { + $this->cardNumber = $cardNumber; + $this->expirationDate = $expirationDate; + $this->cvv = $cvv; + } + + public function pay($amount) { + echo "Paying $" . $amount . " with credit card.<br>"; + // Logique de paiement par carte de crédit + } +} + +class PayPalStrategy implements PaymentStrategy { + private $email; + private $password; + + public function __construct($email, $password) { + $this->email = $email; + $this->password = $password; + } + + public function pay($amount) { + echo "Paying $" . $amount . " with PayPal.<br>"; + // Logique de paiement par PayPal + } +} + +class ShoppingCart { + private $paymentStrategy; + + public function setPaymentStrategy(PaymentStrategy $paymentStrategy) { + $this->paymentStrategy = $paymentStrategy; + } + + public function checkout($amount) { + $this->paymentStrategy->pay($amount); + } +} +``` +- 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 +abstract class Game { + abstract protected function initialize(); + abstract protected function startPlay(); + abstract protected function endPlay(); + + public final function play() { + $this->initialize(); + $this->startPlay(); + $this->endPlay(); + } +} + +class FootballGame extends Game { + protected function initialize() { + echo "Football game initialized.<br>"; + } + + protected function startPlay() { + echo "Football game started.<br>"; + } + + protected function endPlay() { + echo "Football game ended.<br>"; + } +} + +class BasketballGame extends Game { + protected function initialize() { + echo "Basketball game initialized.<br>"; + } + + protected function startPlay() { + echo "Basketball game started.<br>"; + } + + protected function endPlay() { + 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. +```php +// Commande abstraite +interface Command { + public function execute(); +} + +// Commande concrète +class ConcreteCommand implements Command { + private $receiver; + + public function __construct(Receiver $receiver) { + $this->receiver = $receiver; + } + + public function execute() { + $this->receiver->action(); + } +} + +// Récepteur +class Receiver { + private $name; + + public function __construct($name) { + $this->name = $name; + } + + public function action() { + echo "Action effectuée par le récepteur " . $this->name . "\n"; + } +} + +// Invocateur +class Invoker { + private $command; + + public function setCommand(Command $command) { + $this->command = $command; + } + + public function executeCommand() { + $this->command->execute(); + } +} + +// Utilisation du pattern Command +$receiver = new Receiver("Récepteur"); +$command = new ConcreteCommand($receiver); +$invoker = new Invoker(); +$invoker->setCommand($command); +$invoker->executeCommand(); + +``` +- 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. +```php +// Agrégat +interface Aggregator { + public function getIterator(): Iterator; +} + +// Itérateur +interface Iterator { + public function hasNext(): bool; + public function next(); +} + +// Implémentation concrète de l'agrégat +class ConcreteAggregator implements Aggregator { + private $items = []; + + public function addItem($item) { + $this->items[] = $item; + } + + public function getIterator(): Iterator { + return new ConcreteIterator($this->items); + } +} + +// Implémentation concrète de l'itérateur +class ConcreteIterator implements Iterator { + private $items; + private $position = 0; + + public function __construct($items) { + $this->items = $items; + } + + public function hasNext(): bool { + return $this->position < count($this->items); + } + + public function next() { + if ($this->hasNext()) { + $item = $this->items[$this->position]; + $this->position++; + return $item; + } + } +} + +// Utilisation du pattern Iterator +$aggregator = new ConcreteAggregator(); +$aggregator->addItem("Item 1"); +$aggregator->addItem("Item 2"); +$aggregator->addItem("Item 3"); + +$iterator = $aggregator->getIterator(); +while ($iterator->hasNext()) { + echo $iterator->next() . "\n"; +} +``` +- 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. +```php +// Contexte +class Context { + private $state; + + public function __construct(State $state) { + $this->state = $state; + } + + public function setState(State $state) { + $this->state = $state; + } + + public function request() { + $this->state->handle($this); + } +} + +// État abstrait +interface State { + public function handle(Context $context); +} + +// Implémentation concrète de l'état +class ConcreteStateA implements State { + public function handle(Context $context) { + echo "Traitement spécifique de l'État A.\n"; + $context->setState(new ConcreteStateB()); + } +} + +// Implémentation concrète de l'état +class ConcreteStateB implements State { + public function handle(Context $context) { + echo "Traitement spécifique de l'État B.\n"; + $context->setState(new ConcreteStateA()); + } +} + +// Utilisation du pattern State +$context = new Context(new ConcreteStateA()); +$context->request(); // Appelle le traitement spécifique de l'État A +$context->request(); // Appelle le traitement spécifique de l'État B +$context->request(); // Appelle le traitement spécifique de l'État A +``` + +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. \ No newline at end of file diff --git a/source/concept/poo/images/blueprint.jpg b/source/concept/poo/images/blueprint.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c9ac1cc4cdd472459c136fc3f8197dd92eedc57b Binary files /dev/null and b/source/concept/poo/images/blueprint.jpg differ diff --git a/source/concept/poo/images/fileAccessor.png b/source/concept/poo/images/fileAccessor.png new file mode 100644 index 0000000000000000000000000000000000000000..6dbb9bbd832448880e0fcc60fbd740af001403b6 Binary files /dev/null and b/source/concept/poo/images/fileAccessor.png differ diff --git a/source/concept/poo/images/x-wing.jpg b/source/concept/poo/images/x-wing.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ea99c7d5aba46bcc2d3b10bdb93b36a8422a27a5 Binary files /dev/null and b/source/concept/poo/images/x-wing.jpg differ diff --git a/source/concept/poo/index.rst b/source/concept/poo/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..920f2f09d39e8a9a510421a2bf5ef9c467e5f752 --- /dev/null +++ b/source/concept/poo/index.rst @@ -0,0 +1,14 @@ +Programmation orienté objets +============================================ + + +Nous allons parler ici de conceptes de programmation. + +A quoi ça sert, pourquoi l'utiliser, comment ça fonctionne ? + +============================================ + +.. toctree:: + :maxdepth: 2 + + general.md \ No newline at end of file diff --git a/source/concept/rest/general.md b/source/concept/rest/general.md new file mode 100644 index 0000000000000000000000000000000000000000..38d7653b65014354fbb037f1ea08f778843c1742 --- /dev/null +++ b/source/concept/rest/general.md @@ -0,0 +1,120 @@ +# Introduction + +## Qu'est ce qu'une API ? + +En réalité, l’API ou Application Program Interface est, comme son nom l’indique, une interface servant à communiquer entre deux ou plusieurs applications (appareils, services, etc.) distinctes. Elle permet d’effectuer une requête spécifique et de recevoir une réponse, formulée sous un format établi. + +Elle se base donc sur une architecture client-serveur, sur laquelle le client est celui qui effectue la demande et le serveur, celui qui traite et renvoie la réponse. Le client n’a pas à se soucier de la manière dont ce traitement est fait, mais récupère juste ce qu’il a demandé. Le programme du côté du serveur peut donc être élaboré et écrit en n’importe quel langage. Cela n’affectera pas la réponse obtenue par le client, et ce, quelles que soient les technologies utilisées par celui-ci. Il suffit que ces technologies puissent interpréter le résultat communiqué et le tour est joué. + +Grâce à cette interface, les développeurs diminuent le volume de code à produire en n’effectuant que les liens entre les différentes APIs nécessaires pour leurs programmes et adaptés à leurs besoins et à ceux de l’entreprise. + +Les API permettent également de réutiliser à mainte reprise la même ressource, ce qui offre une flexibilité importante à chaque ressource. + +## Qu'est ce qu'une API REST ? + +Le mot REST est l’abréviation de Representational State Transfer. Une API est dite RESTful lorsqu’elle répond à certaines contraintes architecturales. En gros, c’est un ensemble de règles à respecter afin de rendre l’interaction entre le client et le serveur le plus flexible, le plus simple et le plus rapide possible. C’est pour cela que les entreprises la préfèrent aux autres manières de faire appel à des APIs. + +Elle se base essentiellement sur le protocole HTTP pour l’envoi de requêtes relatives au CRUD (création, récupération, modification ou suppression). L’interaction avec les ressources basées sur un serveur s’effectue à partir d’un URI. + +Il existe plusieurs formats dans lesquels ces dernières peuvent être retournées, à savoir : JSON, XML, XLT, YAML ou HTML. + +Le rôle premier d’une API REST est de servir d’intermédiaire entre le client et le serveur. C’est-à-dire que c’est elle qui réceptionne les requêtes émises par le client, le transmet à l’entité demandée au serveur, prend les réponses données par ce dernier puis les retransmettent au client. + + + +## Principes clés + +### L'URI comme identifiant de la ressource + +L'URI (ou le endpoint) permet d'identifier clairement un ressources. + +Exemple : **/rest/vx/clients** Permet d'agir sur la ressource gérant les clients. + +L'URI permet également de percevoir les relation entre les objets. + +Exemple : **/rest/vx/clients/{id}/commandes** Permet d'agir sur la ressource gérant les commandes d'un client spécifique. + +### Les verbes HTTP Pour identifier les opérations + +La seconde règle d’une architecture REST est d’utiliser les verbes HTTP existants plutôt que d’inclure l’opération dans l’URI de la ressource. Ainsi, généralement pour une ressource, il y a 4 opérations possibles (CRUD) : + +- Créer (create) +- Afficher (read) +- Mettre à jour (update) +- Supprimer (delete) + +HTTP propose les verbes correspondant : + +- Créer (create) => POST +- Afficher (read) => GET +- Mettre à jour (update) => PUT +- Supprimer (delete) => DELETE + +### Les réponses HTTP comme représentation de la ressource + +Il est important d’avoir à l’esprit que la réponse envoyée n’est pas une ressource, c’est la représentation d’une ressource. Ainsi, une ressource peut avoir plusieurs représentations dans des formats divers : HTML, XML, CSV, JSON, etc. + +C’est au client de définir quel format de réponse il souhaite reçevoir via l’entêteAccept. Il est possible de définir plusieurs formats. + +### L'utilisation du header authorization pour le jeton de connexion + + il est primordial de sécuriser une API REST. En effet, nous ne sommes jamais à l’abri d’une personne malveillante souhaitant dérober des données que nous exposons, surtout à travers le web. Plusieurs manières sont envisageables et à mettre en place pour qu’une API soit le moins vulnérable possible : + +- Utiliser le protocole HTTPS permet de chiffrer les échanges entre les deux parties, à savoir le client et le serveur ; +- Mettre en place un système d’authentification limite les personnes pouvant échanger avec l’API. Vous pouvez pour cela utiliser, par exemple, Json Web Token (JWT). JWT sert à identifier un utilisateur et à lui donner l’accès à l’API sur une durée déterminée. OAuth2 est également un excellent moyen d’authentifier un client pour lui prodiguer les autorisations nécessaires pour la consommation de l’API. +- Utiliser une clé d’API ainsi qu’une clé secrète permet de reconnaitre les applications accédant à l’API. Cela permet également de signer les requêtes effectuées par celles-ci. + +## REST vs SOAP + +La première raison pour laquelle ces deux APIs sont comparées est sans doute que pendant très longtemps, avant l’apparition de l’API REST, SOAP a été la référence en termes d’utilisation des interfaces. En effet, ayant vu le jour en 1998, c’est un protocole se basant sur XML permettant d’interagir avec de nombreuses sortes d’autres protocoles tels que HTTP, UDP, TCP, etc. + +Cependant, malgré cette puissance qu’il détient, SOAP a tendance à occuper plus de bande passante et par conséquent de devenir assez lent. De plus, il nécessite l’apprentissage du XML et une certaine coordination entre le concepteur du code client et serveur afin d’éviter les erreurs qui peuvent être fatales pour chacun d’eux. Il n’est donc pas assez flexible pour que les applications actuelles puissent évoluer. + +C’est à cause de tout cela que, de nos jours, la plupart des développeurs privilégient l’utilisation d’une API RESTful. + +# Conception d'une API REST + +## Ressources + +La première étape consiste à identifier les ressources exploitables à travers l'API et comment elles sont exploitables. + +Cette étape est à mettre en lien avec les droits sur la Base de données ou les droits sur le système de fichier. + +## Endpoint et opération + +Il faut ensuite définir les endpoints, c'est à dire les ressources et les relations à mettre en place, à partir de là les endpoint devrait apparaitre de manière trés simple. + +Les opérations seront quant à elles le prolongement direct des droits sur votre base de onnées pour chacune des ressources. + +## Requêtes + +Reste à mettre en place les contraintes techniques lié au développement d'un API REST : + +- Format consommable en entrée : + - Query parameters + - Headers + - Content-type acceptables en entrée +- Format de donnée délivrable en sortie +- Authentification +- Headers de sécurité + +# Spécificité d'une API Vitis + +L'API PHP de Vitis va vous permettre de définir vos ressources et des les rendre exploitables facilement. + +Au niveau des spécificté s des requêtes : +- En entrée sont pris en compte + - les query parameters + - Les body dont le content-type est de type + - Multipart/Form-data + - application/x-www-urlencode + - application/json +- Le header accpet permet de définir le format de récupération de la donnée, deux valeur possible : + - application/json + - application/xml +- Un token JWE ou systéme custom équivalent est utilisé pour gérer l'authentification. + + +Une bonne partie de la sécurité est géré en flux commun avant l'arrivée dans votre code. + +Le tout s'appuyant sur le framework Symfony. \ No newline at end of file diff --git a/source/concept/rest/images/archi-api.png b/source/concept/rest/images/archi-api.png new file mode 100644 index 0000000000000000000000000000000000000000..0438d03e8d6a564d345e4d779ff96dd450985149 Binary files /dev/null and b/source/concept/rest/images/archi-api.png differ diff --git a/source/concept/rest/index.rst b/source/concept/rest/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..3bfa1a2d89d83180a599e43aae22d6bf02891ea2 --- /dev/null +++ b/source/concept/rest/index.rst @@ -0,0 +1,14 @@ +API REST +============================================ + + +Nous allons parler ici de la conception d'une API REST. + +A quoi ça sert, pourquoi l'utiliser, comment ça fonctionne ? + +============================================ + +.. toctree:: + :maxdepth: 2 + + general.md \ No newline at end of file diff --git a/source/conf.py b/source/conf.py index b92a9230e04a6c7568bad6b90618176866714641..7aca07e83907017a20b3d4c90441f3bade0b0a08 100644 --- a/source/conf.py +++ b/source/conf.py @@ -3,6 +3,8 @@ import os from sphinx_markdown_parser.parser import MarkdownParser from datetime import datetime #from recommonmark.transform import AutoStructify +from sphinx.highlighting import lexers +from pygments.lexers.web import PhpLexer source_parsers = { '.md': 'CommonMarkParser', @@ -139,3 +141,8 @@ html_theme_options = { 'includehidden': True, 'titles_only': False } + + +lexers['php'] = PhpLexer(startinline=True, linenos=1) +lexers['php-annotations'] = PhpLexer(startinline=True, linenos=1) +primary_domain = 'php' \ No newline at end of file diff --git a/source/dev-vitis/index.rst b/source/dev-vitis/index.rst index 60aeec1d4efbd3b05fb8e30c9ed627520b5fd49e..bc930bd8fdba9793d24e3d75cd9ce2f634f2cf8c 100644 --- a/source/dev-vitis/index.rst +++ b/source/dev-vitis/index.rst @@ -1,4 +1,4 @@ -Documentation Veremes sur les méthodes de développement internes +Méthodes de développement internes ================================================================ .. image:: /images/Veremes_Black.svg diff --git a/source/exploitation/index.rst b/source/exploitation/index.rst index 4d1a0bdcd9721f7d2c4ae8df970f82122cf12694..3fedfbb64e8eae736f2ebf48f8bd77bb692b028f 100644 --- a/source/exploitation/index.rst +++ b/source/exploitation/index.rst @@ -1,4 +1,4 @@ -Documentation Veremes sur les prrocédures d'exploitation +Procédures d'exploitation ============================================= .. image:: /images/Veremes_Black.svg diff --git a/source/tools/index.rst b/source/tools/index.rst index 88d8dd7b394c941b2b1fdf679f382736b71876cc..fffcc604df9118c6da6f68c8303d6068b1d80dde 100644 --- a/source/tools/index.rst +++ b/source/tools/index.rst @@ -1,4 +1,4 @@ -Documentation Veremes sur les outils utilisés +Outils utilisés ============================================= .. image:: /images/Veremes_Black.svg