POO
Programmation orientée objet

Cédric BRASSEUR
Mis à jour le 24/03/2025
Cédric BRASSEUR
- Ancien étudiant de l'Exia.cesi
- 4 ans consultant chez Amaris, placé chez Euro Information Dev
- Auto-entrepreneur depuis début 2020 (Création de sites web, applications mobiles & formateur)
Et vous ?
- Nom, prénom
- Etudes réalisées
- Connaissances sur l'orienté objet...
- Autres infos appréciées

Plan du cours
### L'orienté objet - Introduction
- Passage du diagramme de classes à l'orienté objet
- Mise en place de l'environnement Visual Studio
- Les bases de l'orienté objet
### Intéragir avec une base de données
- Présentation des outils d'interrogation de BDD
- Workshop de mise en place d'un projet orienté objet communiquant avec une base de données
### Concepts avancés
- Présentation des tests unitaires avec MSTest
- Mettre en place & Interroger une API
- Workshop de mise en place et interrogation d'une API
- Introduction sécurité concernant les APIs
- Plugins ReSharper
- Présentation du Framework MVC
- Utilisation d'un micro framework MVC pour un développement fullstack
- Révision rapide des Designs Patterns
### Mise en pratique et exercices

POO
Objectifs de la semaine
-
Appréhender le paradigme objet
-
Implémenter un projet et le modéliser en orientée objet
-
Interagir avec une base de données SQL








Introduction à la POO
Historique, cas d'utilisation, bases
Début de la Programmation orientée objet avec Simula, puis Smalltalk
Appliqué dans de nombreux langages : Eiffel, C++ ou encore Objective C
Java orienté objet
.Net orienté objet (C#, VB,...)
Toujours autant d'actualité dans les développements
1970
1980
1990
1995
2000
1995
Aujd
P
O
O
Historique
Concevoir, maintenir et
exploiter facilement de gros logiciels.
Les cas d'utilisations
La programmation orientée objet est très utilisée dans le monde de l'informatique et a pour vocation a rester très présente dans les prochaines années
Motivation ?
Avantages ?
Modularité, abstraction,
productivité, réutilisabilité, tests automatisés et encapsulation.
IDE : Visual Studio & environnement .Net
Normalement, vous avez déjà installé Visual Studio.
L'environnement .Net que l'on souhaite utiliser pour cette formation est le .Net Core (3.1 si possible).
Dans un premier temps nous allons créer un projet Console, celui-ci permettant d'afficher des éléments dans un terminal.
Visual Studio a de nombreux avantages pouvant vous aider à développer en orienté objet, nous allons en voir quelques uns ensemble.
Un des grands intérêt est également le debug permettant de faire du pas à pas pour comprendre ce que fais le programme.
Rappels de programmation
- Types primitifs
- Opérateurs
- Opérations (conditions, boucles, ...)
- Ils sont stockés dans la RAM pour un accès plus rapide
- Ils s'opposent aux types wrapper (String, Int, Char, ...)
Les types primitifs
Ce sont des types de variables basiques, contenant leurs propres espaces mémoires pour des variables numériques, alphanumériques ou booléennes.
Primitifs ?

Nous en reparlerons plus tard !
Les types primitifs : Numériques
Ce sont les différents types permettant de stocker des nombres, qu'ils soient entiers ou à virgules.

Gestion des entiers :
- byte (1 octet) : entre -128 et +127.
- short (2 octets) : entre -32768 et +32767
- int (4 octets) : entre -2000000000 et +2000000000
- long (8 octets) : entre −9×10^18 à 9×10^18
Gestion des décimaux :
- double : codés sur 8 octets (c’est à dire 64 bit)
- float : codés sur 4 octets (c’est à dire 16 bit)
- decimal : codés sur 16 octets (c’est à dire 128 bit)
Les types primitifs : Chaînes & Caractères
Ce sont les différents types permettant de stocker des chaînes alphanumériques ou un caractère alphanumérique.

Gestion des chaînes de caractères :
- string : une succession de caractères stockés dans une variable
Gestion des caractères :
- char : Un simple caractère stocké dans une variable
Les types primitifs : Booléens
Ce sont les différents types permettant de stocker une valeur binaire, (ou null) : true ou false.
true
false
Les opérateurs
Réalisations d'opérations arithmétiques, binaires et opérations sur les types
Arithmétiques ?

Les opérateurs binaires
Réalisation d'opérations de comparaisons en utilisant des opérateurs binaires (&&, || , !)
Binaires ?


Les opérateurs de conversions
Réalisation d'opérations de conversions de types vers d'autres types (lorsque c'est possible). Plusieurs possibilités s'offrent à nous, je conseille le TryParse + Parse avec gestion d'erreur que l'on reverra plus tard.

Les opérations (if)
If permet de réaliser une (ou plusieurs) conditions dans le code, grâce aux mots clés if, else if et else il est possible d'enchaîner autant de condition que l'on souhaite.

Les opérations (for)
For permet de réaliser une succession d'opérations identiques à un ensemble d'éléments prédéfinis. Il permet de parcourir une liste d'éléments pour les afficher par exemple.

Initialisation du compteur
Condition de
sortie
Pas sur le compteur chaque itération
Les opérations (foreach)
Foreach va permettre de réaliser un ensemble d'instructions pour chaque éléments d'une liste (ou un tableau, tant que c'est IEnumerable, mais nous en reparlerons également !)

Elément accessible dans le foreach
Les opérations (switch)
Switch va permettre de différencier un élément pour en réaliser une succession d'instructions. Le fonctionnement est similaire à une condition if, mais la syntaxe est différente.


- La modélisation permet d'avoir les classes, méthodes et propriétés nécessaires à la réalisation d'un projet
- Après cette modélisation, vous pouvez démarrer vos développements
POO & UML
Vous avez vu l'UML et les Design Patterns, le diagramme de classes et la notion la plus proche de l'orienté objet en termes de programmation. Vous pouvez utiliser des outils pour générer votre diagramme de classe dans le code directement.
Modélisation

Les bases de la POO
Programmation Orienté Objet
-
Création de classes : Structure contenant des propriétés et des méthodes qui lui sont propres. C'est un modèle qui est défini pour un futur objet.
-
Instanciation d'objets : Permet de créer des objets respectant le modèle de la classe.
- Constructeurs : Permet de gérer la ou les façons dont les objets sont créés.

POO
Les classes
Une classe est une structure contenant des propriétés et des méthodes qui lui sont propres. C'est un modèle.

Les propriétés
Une propriété est une variable rendu disponible dans la classe.

Le constructeur
Un (ou plusieurs) constructeur permet de réaliser des opérations et spécifier la création d'un objet. On l'utilise très fréquemment pour valoriser les propriétés d'une classe.

Le destructeur
Un destructeur permet de réaliser une action particulière lors de la destruction de l'objet (soit manuelle, soit automatiquement à la fin d'un script).

Les méthodes
Les méthodes sont l'équivalent d'une fonction que l'on a déjà vu, mais elle sera propre a l'objet, en général elle permet de réaliser des opérations avec les propriétés de l'objet.

L'instanciation d'un objet
Permet de créer un ou plusieurs objets respectant le modèle.

Exercice
Définir une classe "User" ayant pour propriétés :
- Name (Le nom de l'utilisateur)
- Firstname (Le prénom de l'utilisateur)
- Language (La langue de l'utilisateur)
- Date (La date de création de l'objet)
Ajoutez un constructeur permettant de valoriser Name, Firstname et Language. De plus initialiser le Date avec Date = DateTime.Now;
Ajoutez ensuite deux méthodes :
- La première donne des informations de l'utilisateur (Nom, Prénom, Date de création) dans un Console.Writeline() ,
- La seconde permet de changer la langue de l'utilisateur et la retourner.
Faites un destructeur qui affiche que l'objet est détruit.
Instanciez un objet et utilisez les méthodes créées précédemment.
Modificateurs d'accès
En .Net il existe 5 modificateurs d'accès :
- Public / Private
- Protected
- Internal / Protected Internal
Chacun permet un comportement différent concernant l'accès à une propriété ou une méthode




Modificateurs d'accès
Ces modificateurs d'accès mènent à un des grands principes de la POO.

L'encapsulation !
- Définir une propriété en privé
- Proposer des Getters / Setters en public quand nécessaire.

L'avantage est là :
On peut réaliser des vérifications dans notre classe
Modificateurs d'accès
Aparté sur les normes de déclaration d'une propriété privée, elle est définie en camelCase, avec un underscore en préfixe.
On nomme notre
variable privée avec un préfixe _ et en camelCase

Modificateurs d'accès
C# peut auto-implémenter ce système pour vous, c'est les premiers getters / setters que l'on a vu et que l'on a pas évoqué plus que ça jusque là.
Propriété auto-implémentée. Le compilateur créer une propriété privée.

Un getter spécifique basé sur la Birthdate et la date du jour +
Pas de Setter !
Une classe doit être dans un état valide (stable) !!
Indexeurs
Les indexeurs permettent de gérer une structure en format tableau.
Dictionnaire générique permettant d'avoir un couple Clé / Valeur.
Mot clé this à utiliser comme propriété, on reprend la syntaxe vue avant.

Les 4 grands principes
Il existe 4 grands principes en POO à respecter
(le plus possible)
- Encapsulation : On vient de le voir, permettant de laisser la responsabilité à la classe concernée.
- Héritage : Partage de code descendant, nous y reviendrons plus tard
- Abstraction : Mise à disposition de contrat qui peuvent être surchargés, nous y reviendrons plus tard.
- Polymorphisme : Moyen de proposer plusieurs signatures pour une même méthode, apportant une certaine flexibilité, nous y reviendrons plus tard

Exercice StopWatch
Exercice de POO (Bases)
Créez une classe Chrono.
Cette classe doit simuler un compteur et proposer deux méthodes :
- Start : Démarre le timer
- Stop : Arrête le timer
Le but est d'appeler Start, puis Stop et d'avoir une durée dans un TimeSpan (Type comme DateTime)
Affichez la durée dans la console.
On doit également pouvoir l'utiliser plusieurs fois, on doit donc pouvoir le démarrer et l'arrêter autant de fois que l'on souhaite.
Nous ne devons pas pouvoir démarrer plusieurs fois notre compteur d'affilé. Ni le stopper s'il n'est pas démarré.
Bonus : Donc la classe doit throw une InvalidOperationException si c'est le cas.
On fera une revue de code avec un étudiant et je proposerai un corrigé.
Si vous décommentez,
ça doit soit fonctionner quand même ou lever une exception

Concepts avancées de POO
Nous allons appréhender certains concepts permettant de vous simplifier la vie en POO :
- Interface
- Abstraction
- Polymorphisme
- Encapsulation (déjà vu)
- Gestion des erreurs
- ...
Les concepts avancés
Nous allons parcourir une majeure partie des concepts avancés de la POO qui vous seront utiles pour réaliser vos projet orientés objets.
Sommaire rapide

L'héritage
L'héritage permet de partager des propriétés et méthodes entre les classes, il suffit d'utiliser le mot clé extends pour que cette classe (fille) hérite de la classe de base (mère).
Le partage de code s'effectue de manière descendante uniquement.
L'héritage (code)


Classe mère
Classe fille
Instanciation

Attention ici !
On peut utiliser les propriétés et méthodes de la mère et de la fille grâce à l'héritage
L'héritage (exemple)
Le but de cet exemple est de mettre en place de l'héritage pour un "Animal". Les classes pouvant en hérité sont "Hibou", "Dragon" et "Tigre".
Animal
Hibou
Dragon
Tigre
L'héritage (exemple)
Classe mère
Classes filles
Instanciation
Chaque animal a sa
propre définition de walk, sauf le tigre qui marche normalement.



Note : new permet de redéfinir la méthode mère
L'héritage (particularités)
Certains mots clés sont à connaître pour l'héritage :
- new : Permet la redéfinition d'une fonction de la class mère.
- base : Permet de se référer à un élément de la classe mère (par exemple, le constructeur)
- virtual : Permet de rendre une
méthode de la classe mère
redéfinissable qu'une seule
fois par une classe fille. - sealed : Permet de redéfinir et
sceller la méthode virtual
de la classe mère qu'une
seule fois (erreur sinon) - override : permet de rendre la
méthode abstraite
(on y reviendra)

Exercice
Réaliser de l'héritage
Cette fois-ci, vous devez réaliser de l'héritage entre une classe mère "Personne" et deux classes filles "Etudiant" et "Formateur".
La personne a un nom et un prénom.
Le formateur a un sujet à traiter.
L'étudiant a une note.
Chaque classe fille possèdera donc 3 propriétés et peuvent les setter à leur convenance. Réalisez les classes et le Program.cs permettant d'implémenter cet héritage et appelez les getters pour réaliser des Console.WriteLine() des 3 propriétés pour le Formateur et pour l'Etudiant dans une méthode d'affichage
Vous devez donc implémenter les getters et setters vous même.
PS : Pas besoin que le formateur puisse modifier la note de l'étudiant, il suffit juste que vos différentes classes filles aient leurs propres ajouts de méthodes par rapport aux propriétés demandées.
- // TODO: Clarifier
- // Si la méthode est virtuelle, le méthode appelée est celle du type de la classe fille
- // Si la méthode n'est pas virtuelle et redéfinie avec le mot clé new, la méthode appelée est celle du type de l'objet (mère)
- // Utiliser new que dans les cas particulier nécessitant d'appeler la méthode de la classe mère
- // Conseiller d'oublier le new ???
TODO
Les interfaces
Les interfaces sont à considérer comme des contrats à respecter, elles contiennent des propriétés et des signatures de méthodes qui seront à implémenter dans la classe héritant de cette interface
Contient une propriété et une méthode qui devra être redéfinie dans les classes implémentant


Contient une propriété et une méthode qui devra être redéfinie dans les classes implémentant
Ici, Cat doit forcément avoir une propriété Name et une méthode MakeSound qui respectent le contrat de l'interface
Les interfaces
Voyons un exemple plus complet ensemble...
Association / Agrégation
Une association traduit un lien entre une classe A et une classe B (appel de méthode par exemple).
L'agrégation est une association particulière : l'objet A possède une ou plusieurs instances de B.

Instanciation

La composition
Une composition est une agrégation particulière : toutes les instances de B contenues dans A sont supprimées lorsque A est supprimée.

La composition
Autre exemple plus complexe (pour revoir un peu d'orienté objet supplémentaire)



Instanciation
Exercice
Exercice Orienté Objet
Réaliser une composition entre Author et Book.
- Author doit avoir
- une propriété public Name et une propriété Email,
- vous devez créer un constructeur pour remplir ces propriétés.
- Book doit avoir
- une propriété public Authors (List<Author>), Price et Name.
- Un constructeur pour set Name et Price. (Et initialiser la liste Authors = new List<Author>(); )
- A vous de trouver comment réaliser une composition entre ces deux classes.
- Pour tester votre code voici ce qui doit fonctionner :
var book = new Book("Name", 10);
book.AddAuthor("Cédric", "cdric.brasseur@gmail.com");
book.AddAuthor("Jean", "jean@gmail.com");
Console.WriteLine("Book name : {0}", book.Name);
Console.WriteLine("Book price : {0}", book.Price);
foreach (Author author in book.GetAuthors())
{
Console.WriteLine("Author name : {0}", author.Name);
Console.WriteLine("Author email : {0}", author.Email);
}
Les classes abstraites
Une classe abstraite (mère) permet de définir les signatures des méthodes et les propriétés qui seront partagés à la classe qui va étendre cette classe abstraite (fille)


Les classes abstraites
L'intérêt principal des classes abstraites est d’informer l’utilisateur (la classe fille) de cette classe qu’une instance de cette dernière n’a pas d’utilité a être instanciée. Exemple : vous devez gérer un centre de location de véhicules (voiture, camion, vélo ….). Vous avez très certainement une classe Vehicule, dont héritera Velo, Voiture, Camion…
Mais le centre de location n'aura jamais besoin d'instancier un Vehicule.
Les classes abstraites peuvent également posséder des méthodes abstraites. Ce sont des méthodes qui ne possèdent pas de corps, et qui devront obligatoirement être surchargée par les classes qui en hérite
Les classes abstraites
Un autre exemple pour mieux comprendre... Nous avons une classe abstraite Shape et deux classes filles Square & Circle.



Impossible
d'instancier une forme,
Shape est un concept abstrait
Hérite de Shape
Ce qui lui en donne les propriétés & force à redéfinir "Draw"
Ajouter exemple virtual
Exercice
Exercice Orienté Objet
Réaliser une abstraction entre une classe Fruit et deux classes Orange, Fraise
- la classe abstraite Fruit doit avoir
- une propriété public Color,
- une méthode abstraite Eat
- Orange doit avoir
- un constructeur pour remplir la propriété Color provenant de Fruit (l'abstraction dont il hérite)
- redéfinir la méthode Eat (avec un override) pour préciser qu'on mange une orange dans un Console.WriteLine()
- Fraise doit avoir
- redéfinir la méthode Eat (avec un override) pour préciser qu'on mange une fraise dans un Console.WriteLine()
- (Cette classe n'a effectivement pas de constructeur, on ne veut pas lui assigner de couleur)
- redéfinir la méthode Eat (avec un override) pour préciser qu'on mange une fraise dans un Console.WriteLine()
A noter : La classe Fruit ne doit pas pouvoir être instanciée.

Différences entre interfaces, héritage et abstraction
Les trois éléments sont utilisées pour réaliser de la réutilisation de code descendante :
-
Interface : Contrat à respecter, permet de définir un ensemble de fonctionnalités à redéfinir dans une classe
-
Héritage : Une classe de démarrage qui propose des fonctionnalités qui sont réutilisables par les classes filles
- Abstraction : Forcer l'implémentation de sous classe, une classe abstraite ne peut pas être instanciée
Exercice
Exercice plus complet sur les interfaces
Envoyer le fichier "Exercice_interface.md"
- Le garbage collector peut les supprimer beaucoup plus rapidement
- Logiquement parlant (code), ça a un sens a part entière
- Le compilateur ajoute le mot clé readonly automatiquement si la propriété n'est pas modifiée plusieurs fois
Les propriétés readonly
Il faut savoir qu'il est possible de déclarer des propriétés comme étant valorisable qu'une seule fois. En .Net, ça se déclare avec le mot clé readonly.
Pourquoi ?

Les propriétés static
Le mot clé static, sur une méthode par exemple permet de ne pas avoir à instancier un objet pour en utiliser une méthode statique.


La classe peut aussi
être static pour empêcher son instanciation mais c'est optionnel.
De cette façon, tout doit être static dans la classe déclarée en static
Les propriétés static
Il est possible de mélanger méthodes et propriétés statiques avec des méthodes et propriétés non static, mais attention aux portées de variable (on y revient plus loin)
Ici, la classe n'est pas déclarée static ce qui permet le mélange

Le polymorphisme
Le polymorphisme est un principe de la POO permettant de proposer des surcharges de méthodes ou "Method Overloading".
Les trois méthodes
ont le même nom mais pas la même signature
(paramètres)
Instanciation


Le polymorphisme
Le polymorphisme est un principe de la POO permettant d'utiliser un type de plus bas niveau en héritage si celui-ci en hérite :

Classe de base (abstraite)

Implémentations (concret)


Suite sur la slide suivante !
Le polymorphisme
Le polymorphisme est un principe de la POO permettant d'utiliser un type de plus bas niveau en héritage si celui-ci en hérite :
Code utilisateur
Utilisation


Un exemple plus complet
Pour vous expliquer avec un exemple concret les principes de la POO, je vais vous montrer un code qui reste assez propre, mais qui ne respecte pas les principes de la POO.
Nous verrons ensuite comment réaliser ce même code mais plus proprement, en respectant les principes de la POO.
Démonstration

POO
- Chaque namespace propose sa propre portée
- Il est possible d'importer des namespaces pour en utiliser les classes
- Il est également possible de faire référence à d'autres projets
Les namespaces
Nous nous y confrontons enfin dans l'exemple précédent (parce que je me suis simplifié la vie, à tort, jusqu'ici) : Les namespaces !
Sachez qu'un namespace a son importance concernant la visibilité des autres classes des autres namespaces.
Portée





Exercice
Exercice Orienté Objet
Réaliser du polymorphisme (Cet exercice n'est pas facile)
Le but de cet exercice est de trouver pourquoi ce code n'est pas suffisamment performant et essayer de l'améliorer avec les principes que l'on a vu ensemble.
Je vais vous aiguiller un peu en vous expliquant ce qui est attendu, mais il va falloir de l'inspiration pour cet exercice il n'est pas simple !
La problématique à implémenter est un service de notifications multi-plateforme (Mail, SMS, SocialMedia) pour pouvoir alerter avec tous les services de notifications que la vidéo a été encodée, tout en respectant les principes de POO.
Nous ferrons un corrigé après pour expliquer ce que nous aurions pu faire pour rendre le code plus modulaire, évolutif et surtout qu'il n'ai pas à être modifié.
Envoyer le zip avec le "mauvais" code.
La gestion des erreurs
Un point important que nous n'avons pas vraiment abordé est la gestion des erreurs. Il est possible de gérer les erreurs en .Net et nous devons même le faire systématiquement.
try/catch/finally
Plusieurs catch possibles, pour gérer différents types d'exceptions

La gestion des erreurs
Nous pouvons décider nous même de lever une exception avec l'instruction "throw".
On lève une
exception de type InvalidCastException

La gestion des erreurs
Il est également possible de créer ses propres types d'Exceptions
Tous les types d'Exceptions existantes ici :
https://docs.microsoft.com/fr-fr/dotnet/standard/design-guidelines/using-standard-exception-types


Exercice
Exercice Orienté Objet
Réaliser une exception simple
Le but de cet exercice est de mettre en place une classe "Calculator" qui prend deux propriétés a valoriser via le constructeur :
- int NumberOne
- int NumberTwo
Une méthode d'ajout :
- Si NumberOne ou NumberTwo est supérieur à 1000, lever une exception de type custom "TooHighNumberException"
Une méthode de division :
- Si NumberTwo vaut 0, lever une exception custom "CantDivideByZeroException"
Implémenter le try catch qu'il faut dans votre program.cs
Exercice
Exercice Orienté Objet
Réaliser une stack avec gestion d'exceptions
Le but de cet exercice est de réaliser une Stack d'entiers en LIFO (last in, first out).
Réalisez une classe StackLifo avec 4 méthodes
- void Push(int number) : Ajoute un chiffre au début de la stack. Ne peut pas excéder 10 éléments, sinon lève une exception de type FullStackException (exception custom)
- int Pop() : Supprime le dernier élément de la liste et retourne cet élément. Lève une exception EmptyStackException (custom) si la stack est vide.
- void Clear() : Vide l'intégralité de la stack et lève également une EmptyStackException si la stack est vide.
- int Count() : Retourne listeItems.Count;
Voici le code qui doit fonctionner chez vous (ou lever la bonne exception)
Bonus : Adaptez le code dans le Program.cs afin d'intercepter correctement les erreurs en fonction du type d'erreur qui peut intervenir sur votre stack (en utilisant plusieurs catch différents)

Aparté Linq
Très rapidement, je souhaitais vous montrer quelques possibilités avec Linq. Nous allons uniquement survolé le sujet, vous pourrez vous exercer de votre côté.

Aparté Resharper
Resharper est un outil permettant de vous aider à coder proprement, il va analyser la syntaxe de votre code et vous proposer d'éventuelles améliorations.
Honnêtement, je ne l'ai pas utilisé depuis 5 ans malheureusement, alors je préfère juste évoquer le sujet et vous laisser vous informer sur cet excellent outil !

Workshop
Workshop Orienté Objet
Réaliser un jeu du serpent.
Je propose une simple simulation de jeu du serpent (plateau)
La console demande deux noms de joueurs (Console.ReadLine();) OU pour simplifier ces noms peuvent être en dur dans le code.
- Les joueurs lancent un dé (1-6) au tour par tour, ils doivent arriver à la case 50.
- S'ils dépassent 50, le joueur retourne directement à la case 25. Jusqu'à ce qu'un des deux gagne la partie.
Le jeu acclame le joueur par son nom à la fin.
(Aucune autre interaction utilisateur nécessaire, juste de l'affichage en ligne de commande, au tour par tour de la position des joueurs, vous pouvez demander une entrée utilisateur pour passer au tour suivant ou enchaîner les tours sans arrêt jusqu'à ce qu'un joueur atteigne la case 50.)
Votre objectif est de réaliser ce mini projet en orienté objet, il vous faut donc à minima une classe Game, pour démarrer la partie.
Bonus pour ceux qui finissent tôt :
- Implémenter des cases bonus et malus : 3 cases pour avancer de X cases et 3 cases pour reculer de X cases sur le plateau (faites en sortes que ces cases ne puissent pas être les mêmes OU pour les expérimentés faites une génération de ces cases automatiques sans que ça puisse se chevaucher.)
- Proposez l'utilisation (une fois par joueur et par partie) d'un super dé (1-12) et si ce lancé tombe sur une case malus, celle-ci ne peut pas faire reculer le joueur.
- Améliorez le jeu en y implémentant vos idées !
L'exercice va prendre du temps, c'est normal, posez des questions, prenez le temps c'est un exercice sympa à faire et on va le retravailler par la suite !
Revue de code + Ramassage pour notation
Créer une API avec .Net (version Controller)
Une API, c'est quoi ?
L'API (Application Programming Interface) est un élément de votre projet extrêmement utilisé dans de nombreux contextes.
Elle permet (en général) de faire le lien entre deux éléments, par exemple :
- Le lien entre votre front et votre back, le front appelle le back en passant par l'API
- Le lien vers d'autres API, par exemple, l'API du gouvernement pour avoir des adresses ou recevoir la météo
Un exemple simple d'API, qui retourne juste une blague Chuck Norris :
https://api.chucknorris.io/jokes/random
Une API, c'est quoi ?
Vous l'avez remarqué si vous avez cliqué sur le lien de la slide précédente, le format de retour d'une API est très généralement du JSON.
{
"categories": [],
"created_at": "2020-01-05 13:42:24.696555",
"icon_url": "https://api.chucknorris.io/img/avatar/chuck-norris.png",
"id": "kR5RQ_S7QwWbcmF18s9upA",
"updated_at": "2020-01-05 13:42:24.696555",
"url": "https://api.chucknorris.io/jokes/kR5RQ_S7QwWbcmF18s9upA",
"value": "Chuck Norris invented airplanes because he was tired of being
the only person that could fly."
}
En plus de ce json, l'appel à une API (donc à une URL, en http / https) retourne un code retour pour connaître le type de reponse de l'API. On le verra un poil plus tard ça.
HEAD
PATCH
DELETE
POST
OPTIONS
Modification d'un contenu (complet)
Comme GET mais pour le header (méta)
Mise à jour de contenu (partiel)
Ajout de contenu
Suppression de contenu
Retourne les ressources disponibles
Les requêtes - REST
Il existe plusieurs types de requêtes pour une API, chacune ayant un objectif précis. Dont 5 sont les plus fréquentes (en gras : GET, PUT, UPDATE, POST, DELETE)
PUT
GET
Récupération d'un contenu
Lors de la requête, on va donc avoir également un type de requête associé à la demande
Les requêtes - REST
Les statut code de retour (Code status), les plus fréquents, car il en existe beaucoup d'autres....
Code | Nom | Description | Cas d'utilisation courants |
---|---|---|---|
200 | OK | Requête réussie | Récupération d'une ressource (GET) |
201 | Created | Ressource créée avec succès | Création d'une ressource (POST) |
204 | No Content | Requête réussie, mais aucune réponse | Suppression d'une ressource (DELETE) |
400 | Bad Request | Requête mal formulée ou invalide | Données manquantes ou incorrectes dans une requête |
401 | Unauthorized | Authentification requise | Jeton d'authentification manquant ou invalide |
404 | Not Found | Ressource non trouvée | Identifiant de ressource inexistant |
500 | Internal Server Error | Erreur interne du serveur | Exception ou bug inattendu côté serveur |
Merci ChatGPT pour ce joli tableau !
Les requêtes - REST
Schéma (simplifié) du fonctionnement d'une API :

Les DTOs
Un DTO (Data Transfer Object) est un objet de transfert de données, son objectif est de définir la structure des éléments entrants et sortants d'une API

Les records
On peut utiliser une classe classique pour nos DTOs, mais en .Net, les records offrent certains avantages et une simplicité d'écriture.
Les avantages
- Syntaxe plus courte et simple
- Immutable (utile pour les DTOs)
- Egalité réalisée sur la structure et non par référence
- Copie facile avec with
- Sérialisation en JSON simplifiée (et même automatisée en .Net)
public record ItemDto(Guid Id, string Name, string Description, decimal Price);
public record CreateItemDto([Required] string Name, [Required] string Description, [Range(0,100)] decimal Price);
public record UpdateItemDto([Required] string Name, [Required] string Description, [Range(0, 100)] decimal Price);
Exemple de record
Les controllers
Un contrôleur est une classe qui va définir les différentes routes de notre API, c'est à dire les requêtes qui peuvent être réalisés par un client.
[ApiController]
[Route("items")]
public class ItemsController : ControllerBase
{
[HttpGet]
public IEnumerable<ItemDto> Get()
{
return items;
}
[HttpGet("{id}")]
public ActionResult<ItemDto> GetById(Guid id)
{
var item = items.Where(item => item.Id == id).FirstOrDefault();
if (item == null)
{
return NotFound();
}
return item;
}
[HttpPost]
public ActionResult<ItemDto> Create(CreateItemDto createItemDto)
{
var item = new ItemDto(Guid.NewGuid(), createItemDto.Name, createItemDto.Description, createItemDto.Price);
items.Add(item);
return CreatedAtAction(nameof(GetById), new { id = item.Id }, item);
}
//...
}
Exemple de controller
Les extensions
On remarquera rapidement qu'il sera nécessaire de convertir un élément (Entity, donc côté base de données) en DTO, pour simplifier celà, on utilise les extensions en .Net.
Ici, ça nous permettra de transformer une entité en DTO
public static class ItemsExtension
{
public static ItemDto AsDto(this Item item)
{
return new ItemDto(item.Id, item.Name, item.Description, item.Price);
}
}
// La méthode AsDto est maintenant appelable sur n'importe quel objet de type Item
Exemple d'extension
La "documentation" de votre API - Swagger
Explications sur Swagger, son utilité et son utilisation (live)
Exploiter son API - Postman
Explications sur Postman, son utilité et son utilisation (live)
Les interfaces - REST
Utilisation de Postman
Postman est un outil de requêtage REST très pratique.
Conseillé sous Windows
& Mac

Il permet de faire tout type de requêtes, je vous conseille de paramétrer pour chaque requête l'authentification basique avec votre compte CouchDB.

Création d'une API
Je vais vous faire suivre un workshop très guidé afin de mettre en place une première API en .Net en utilisant les notions que l'on a vu au préalable.
Exercice - Step 1

Step 1
Envoyer Workshop Step 1
Intégrer le repository pattern et une base de données MongoDB
Un repository, c'est quoi ?
Le repository pattern est une façon bien complexe de définir un principe très simple : On va simplement mettre nos classes et éléments d'accès aux données dans un dossier et le séparer des autres éléments. Autrement dit, on va éviter de mélanger nos éléments d'accès aux données à nos controller.
L'avantage est que ça simplifie grandement le changement de base de données si un jour on souhaite en changer.
En général, on couple cette notion à l'injection de dépendances, que l'on verra un peu après dans cette partie.
Un repository, c'est quoi ?
Schéma dans l'API

Utilisation de MongoDB
MongoDB est une base de données NoSQL orientée Documents.
Chaque document est en json.
On utilise souvent MongoDB lorsque l'on réalise des microservices car c'est scalable et fait pour simplifier la scalabilité (horizontale)

Installation de MongoDB
Nous allons démarrer un conteneur MongoDB avec Docker
Les commandes à réaliser sont :
- Récupérer l'image mongo
docker pull mongo
- Start mongo container :
docker run --name mongodb -d -p 27017:27017 mongo
- Arriver dans le terminal de commande du conteneur :
docker exec -it mongodb bash
- Démarrer mongo en invite de commande (dans docker) :
mongosh
**Vous êtes connecté sur mongo sur docker !**
Via Docker
Petite démo MongoDB
Juste pour vous montrer un peu comment ça marche avant l'exercice, je vais vous montrer comment on peut utiliser MongoDB à travers les différentes méthodes proposées.
De même, nous allons installer une extension dans VSCode pour pouvoir simplement parcourir nos base de données MongoDB
La chaîne de connexion est :
Documentation !!!
Documentation des commandes
Documentation !!!
Documentation !!!
mongodb://{HOST}:{PORT}
mongodb://localhost:27017 (de manière générale en local)
MongoDB en .Net
Pour utiliser MongoDB avec .Net, il nous faut ajouter le package Nuget MongoDB.Driver
Ensuite, nous pouvons facilement exploiter les classes MongoDB pour les classes MongoDB pour réaliser notre CRUD avec notre base de données en MongoDB (orienté document)
Je vais vous montrer un exemple de code et vous aurez le workshop guidé en fin de tutoriel pour pratiquer et comprendre comment l'utiliser
MongoDB en .Net
Pour utiliser MongoDB avec .Net, il nous faut ajouter le package Nuget MongoDB.Driver
Ensuite, nous pouvons facilement exploiter les classes MongoDB pour les classes MongoDB pour réaliser notre CRUD avec notre base de données en MongoDB (orienté document)
Je vais vous montrer un exemple de code et vous aurez le workshop guidé en fin de tutoriel pour pratiquer et comprendre comment l'utiliser
L'injection de dépendance
Vous l'avez sûrement compris dans la slide précédente, mais l'injection de dépendance permet d'éviter de se lier à une implémentation concrète d'une classe en plus de permettre de délier les éléments et éviter les dépendances directes. Ceci rendant le code plus modulaire et évolutif.
En .Net, on peut même paramétrer directement l'injection de dépendance dans nos Settings de départ (fichier Program.cs) afin de pouvoir définir comment l'injection de dépendance doit être gérée.
Nous allons voir un exemple ensemble et vous allez également pouvoir pratiquer avec le workshop guidé
Ajouter le repository pattern et l'injection de dépendances
Je vais vous faire suivre un workshop très guidé afin de mettre en place le repository pattern avec MongoDB et appliquer l'injection de dépendances
Exercice - Step 2

Step 2
Envoyer Workshop Step 2
Les tests unitaires
Importance des tests
L'objectif premier de réaliser des tests sur son application est de limité d'envoyer des erreurs en production.
On va donc tester les développements réalisés à chaque changement et surtout avant chaque mise en production, ce qui rend l'application plus robuste mais ne la rend pas infaillible.

- L'utilisation d'une CI/CD force la réalisation de tests et surtout de s'assurer qu'ils passent,
- L'identification des problèmes est donc réalisée bien plus tôt et plus simplement car tout est cloisonné,
- Plus de productivité (si industrialisé) et donc plus de rendement.
Les tests unitaires
Un test unitaire est utilisé afin de pouvoir vérifier atomiquement que chaque élément de notre code. On va donc vérifier que le code produit bien le résultat attendu.

A savoir :
- Systématique pour chaque projet !
- Réfléchir efficacement à ce qui doit être testé, inutile de tester si 1 + 1 = 2.
- Test Driven Development (TDD): Méthodologie récente visant à démarrer ses développements par des tests unitaires
MSTest est un framework de tests que l'on va utiliser tout au long de notre formation.
Les choses à savoir :
- Le test se fait sur une classe tout à fait normale
- Il suffit de mettre les attributs [TestClass] au dessus de la classe
- Et [TestMethod] au dessus de chaque méthode qui sera considérée comme un test
MSTest - Introduction

MSTest est un framework de tests que l'on va utiliser tout au long de notre formation. Au cas où voici la liste des attributs MsTests :
- [TestClass] : Attribut définissant une classe comme une classe de test
- [TestMethod] : Méthode de test traduit comme un test
- [TestInitialize] : Méthode exécutée avant chaque TestMethod
- [TestCleanup] : Méthode exécutée après chaque TestMethod
- [ClassInitialize] : Méthode d'initialisation de classe
- [ClassCleanup] : Méthode de destruction de classe
- [AssemblyInitialize] : Méthode d'initialisation d'assemblie
- [AssemblyCleanup] : Méthode de nettoyage de l'assemblie
- [TestCategory("name")] : Catégorise un ou plusieurs tests
- [Ignore] : Ignore un test
MSTest - Attributs
Il est également possible de réaliser des assertions, visant à vérifier qu'un contenu correspond à ce qui est attendu, quelque soit la comparaison effectuée.
Exemples :
- Assert.IsTrue(booleanValue);
- Assert.AreEqual(a, b);
- Assert.IsNull(element);
- ...
MSTest - Assertions

Si besoin de plus d'informations sur la réalisation de tests MSTest, visitez :
https://docs.microsoft.com/fr-fr/dotnet/core/testing/unit-testing-with-mstest
MSTest - Documentation

Exercice
Exercice Orienté Objet
Réaliser des tests unitaires.
Ajouter des classes de tests unitaires sur votre jeu du serpent.
Pour vous faciliter la vie, vous allez devoir passer en public pas mal d'éléments, c'est dommage pour l'encapsulation mais ici l'exercice est de traiter les tests unitaires. (Nous aurions dû gérer nos namespaces et passer les éléments en internal pour mieux faire)
Voici quelques tests à implémenter :
- Au démarrage d'une partie il y a bien au moins 2 joueurs
- Les 2 joueurs sont bien à la Position 0 au début d'une partie
- Un lancé de dé retourne bien un chiffre entre 1 et 6.
- Le lancé de dé modifie correctement la position du joueur
- Si le joueur dépasse 50, il revient automatiquement à la case 25
- Si un joueur atteint 50, la partie est bien terminée
- ...
Pas ramassé mais c'est un bon exercice !
Interagir avec une base de données en POO
CRUD et opérations basiques
Nous allons voir ensemble plusieurs opérations possibles en SQL avec SqlClient (SqlConnection & SqlCommand)
C
R
U
D
reate : Création de nouveaux éléments dans la BDD
ead : Lecture d'éléments dans la BDD
pdate : Modification dans la BDD
elete : Suppression dans la BDD
Mais d'abord, il faut se connecter
Pour se connecter, nous allons utiliser la classe SqlConnection, prenant en paramètre une chaîne de connexion.
On en profite pour
ouvrir la connexion avec la méthode Open().
Vous pouvez mettre en place un Singleton pour votre objet de connexion à la base de données !


Créer la BDD
Nous pouvons directement utiliser le code pour créer notre base de données

On utilise la méthode static pour utiliser le Singleton.
Peupler la BDD
De la même manière, on peut créer une table et y insérer des données.
Utilisation de StringBuilder uniquement pour rendre la requête plus lisible.

Insérer des données
Un exemple d'insertion de données avec des requêtes paramétrées (plus sécurisés qu'une requête non paramétrées grâce à l'échappement des données, ou assainissement)
Retourne le nombre de lignes affectées par la dernière commande
Ajout de paramètres
dits assainis (pour éviter les injections SQL)

Modifier des données
Un exemple de modification...

Supprimer des données
Un exemple de suppression...

Lire des données
Un exemple de lecture de données...

On utilise un objet SqlDataReader sur lequel on itère grâce à un while.
Pour chaque ligne retournée par la requête, une itération du while sera appelée avec accès aux données de l'enregistrement
Workshop
Workshop d'ajout d'une base de données pour le jeu du serpent.
Le but de cet exercice est assez simple, vous devez faire en sorte d'enregistrer en base de données le nombre de parties jouées, le nombre de parties terminées ainsi que le score (du joueur 1) pour chaque partie.
- Game(Id, Nombre de tours, Score J1, Score J2)
* Nombre de tours oublié dans le corrigé
Utilisez le singleton proposé pour la connexion à la BDD
Faites en sortes de réaliser quelques parties et avoir un affichage quelque part avant le lancement de la partie résumant les informations insérées en base de données.
Workshop plus complet
Workshop de gestion d'une base de données avec SQLCommand
Envoyer le workshop "workshop_SQLCommand.md"
ORM
Object Relational Mapping : Permet de traduire les tables et relations en objets directement, ou traduire des objets et leurs liens en tables et relations.
Souvent très pratique pour le gain de temps qu'il procure.
Mais peut parfois s'avérer inadapté à certains cas d'utilisation complexe des données.

- Framework proposant un gestion de modèle d'entité relationnelles (ou non)
- Adapté pour du Code First ou Base First.
- Très utilisé dans le monde .Net
Petit exemple avec Entity
Pour montrer comment peut fonctionner un ORM en Code First, je vous montre un exemple de projet utilisant Entity en tant qu'ORM pour manipuler des données depuis une application console.

A vous de suivre ce workshop guidé
Pour une première expérience simple avec Entity, je vous propose un workshop quasiment 100% guidé pour vous faire la main avec le framework.

Envoyer Workshop_Entity_Simple.md
A retenir
Préparer la migration de la base de données
dotnet ef migrations add InitialCreate
Appliquer la migration de la base de données
dotnet ef database update
DBSet, pour créer une nouvelle table selon un modèle
dotnet ef migrations add InitialCreate
public DbSet<Animal> Animals { get; set; }
Configuration de la BDD
dotnet ef migrations add InitialCreate
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=localhost\SQLEXPRESS;
Database=DBName;Trusted_Connection=True;Encrypt=False");
}
Initialiser avec des données
dotnet ef migrations add InitialCreate
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Client>().HasData(
new Client { ClientId = 1, Name = "Cédric" }
);
}
Exercice - ORM
Réalisez un ORM pour réaliser des opérations CRUD sur un système :
L'objectif est de créer 3 objets :
- Order (Id, Created, Items)
- OrderItem (Id, Quantity, Product)
- Product (Id, Price, Description)
Puis réaliser des opérations de CRUD sur ces différents objets depuis votre Program.cs. Référez vous à ce tuto : https://softchris.github.io/pages/dotnet-orm.html#create-the-database
Vous pouvez soit suivre le tuto à la lettre pour utiliser SQLite ou mixer avec le workshop précédent pour utiliser SQL Server
Utilisation d'un Framework MVC
Comment fonctionne une architecture MVC ?
Trois couches
Chaque couche a son propre objectif et ces couches ne communiquent que d'une seule manière avec les autres.

Modèle
- C’est la définition des structures de vos données et c’est dans les modèles que l’on implémente les méthodes de requêtage de la base de données.
Contrôleur
- C’est la logique de code qui prend des décisions et qui altère les données. Il est l’intermédiaire entre la vue et le modèle. Il va également contrôler les droits d’accès par exemple.
Vue
- Les différents éléments qui vont composer votre interface, que ça soit la partie « html » (balises) ou la partie « css » (style) ainsi que les assets et autres ressources de votre interface.

Schéma avec routing
En utilisation normale,
la plupart des Frameworks le gère pour vous
Architecture MVC : Avantages
- Meilleure séparation et organisation du code,
- Diminution de la complexité lors de la conception (normalement),
- Conception claire et efficace,
- Possibilité de réutilisation de code dans d’autres projets
- Un gain de temps en termes de maintenance et pour les évolutions de l’application,
- Plus simple de séparer les tâches aux ressources sur le projet, on peut même faire en fonction des affinités de chacun (BDD, code métier, design,…)
- Plus de facilité pour implémenter des tests unitaires cohérents.

Architecture MVC : Inconvénients
- Éventuel cloisonnement et spécialisation des développeurs, ce qui les rends potentiellement incapable de corriger le bug d’un collègue, ou lorsqu’il y’a du turnover dans les équipes,...
- Architecture plus complexe, peu intéressante pour des petits projets,
- La multiplication du nombre de fichiers représente une charge de mise en place et de formation non négligeable dans un projet.

Si s'en est ?
Les frameworks MVC
Ce sont des frameworks utilisant l’architecture MVC sur lesquels vous aller vous greffer pour réaliser vos développements.
C’est un gain de temps, mais parfois ça peut être contraignant :
- Fonctionnalités non disponible dans le framework ou mise à jour de framework,
- Complexité d’adaptation au framework, par exemple Laravel est complexe à prendre en main mais c’est assez puissant,
- Lourdeur du framework à prendre en considération systématiquement.
Exemples de Frameworks MVC :
- ASP.NET MVC,
- Ruby on rails,
- Laravel,
- Angular Js,
- React,
- Directus,
- Symfony,
Un exemple de mise en place
Nous allons ensemble faire un exemple et voir les particularités de réalisation d'un projet avec un Framework MVC (avant de faire un exercice simple)
Démonstration

MVC
Exercice
Exercice Orienté Objet
Réalisation d'un Pattern MVC
Deux possibilités :
- Suivre le tutoriel suivant : https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro?view=aspnetcore-9.0
Pour ceux qui finissent plus vite, suivez la suite du tuto ici : https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/complex-data-model?view=aspnetcore-9.0
Modifier le jeu du Serpent afin de réaliser une architecture MVC propre mais perso, sans framework. (Tout en gardant le jeu fonctionnel et les enregistrements en base de données demandés)
Sécurité (intro)
Utilisation d'Identity pour gérer nos utilisateurs et les tokens d'authentification ainsi que les rôles et autorisations
- Expliquer ce qu'est un token JWT + refresh token
- Comment le mettre en place
- Identity et ce que ça gère pour nous (version cookie)
- Exemple & exercice
Bonnes pratiques
Clean Code & TDD
Nous allons rapidement entrevoir une autre formation que je donne pour évoquer quelques bonnes pratiques et vous présenter la méthodologie TDD (qui a de l'avenir et qui pourra vous servir, mais sachez qu'elle n'est pas à assimiler pour cette formation, ni même pour votre année d'étude courante)
Clean Code & TDD
Design Patterns
Retour à une formation sur les Design Patterns pour la compléter et la terminer
Même si je pense que nous n'aurons pas suffisament de temps, nous pourrons éventuellement terminer de voir les Design patterns qui n'avaient pas tous pu être vu en formation Modélisation.
Design Patterns
Evaluations
Améliorations du jeu du serpent utilisé jusqu'à maintenant. Plusieurs possibilités :
- Ajouter des tests unitaires
- Implémenter de nouvelles fonctionnalités de jeu
- Proposer un moyen d'avoir plus de 2 joueurs (et sauvegarder en BDD)
- Respecter les principes du Clean Code
- Modéliser le projet en Framework MVC
- Ou autres, proposez...
Evaluation

Partie théorique
En distanciel, peu d'intérêts à faire un QCM.
Partie pratique
BON COURAGE !
(après c'est fini)
Evaluation Programmation Orientée Objet
Réalisation d'un projet complet en POO, en mettant en place un Framework MVC (en équipe, sur une journée complète ?)
programmation-orientee-objet
By Cėdric Brasseur
programmation-orientee-objet
Formation sur la programmation orientée objet
- 682