Programmation orientée objet
Cédric BRASSEUR
Mis à jour le 24/03/2025
### 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
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
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
Concevoir, maintenir et
exploiter facilement de gros logiciels.
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.
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.
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 !
Ce sont les différents types permettant de stocker des nombres, qu'ils soient entiers ou à virgules.
Gestion des entiers :
Gestion des décimaux :
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 :
Gestion des caractères :
Ce sont les différents types permettant de stocker une valeur binaire, (ou null) : true ou false.
true
false
Réalisations d'opérations arithmétiques, binaires et opérations sur les types
Arithmétiques ?
Réalisation d'opérations de comparaisons en utilisant des opérateurs binaires (&&, || , !)
Binaires ?
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.
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.
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
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
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.
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
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.
POO
Une classe est une structure contenant des propriétés et des méthodes qui lui sont propres. C'est un modèle.
Une propriété est une variable rendu disponible dans la classe.
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.
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 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.
Permet de créer un ou plusieurs objets respectant le modèle.
Définir une classe "User" ayant pour propriétés :
Ajoutez un constructeur permettant de valoriser Name, Firstname et Language. De plus initialiser le Date avec Date = DateTime.Now;
Ajoutez ensuite deux méthodes :
Faites un destructeur qui affiche que l'objet est détruit.
Instanciez un objet et utilisez les méthodes créées précédemment.
En .Net il existe 5 modificateurs d'accès :
Chacun permet un comportement différent concernant l'accès à une propriété ou une méthode
Ces modificateurs d'accès mènent à un des grands principes de la POO.
L'encapsulation !
L'avantage est là :
On peut réaliser des vérifications dans notre classe
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
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) !!
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.
Il existe 4 grands principes en POO à respecter
(le plus possible)
Exercice de POO (Bases)
Créez une classe Chrono.
Cette classe doit simuler un compteur et proposer deux méthodes :
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
Nous allons appréhender certains concepts permettant de vous simplifier la vie en POO :
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 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.
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
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
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
Certains mots clés sont à connaître pour l'héritage :
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
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
Voyons un exemple plus complet ensemble...
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
Une composition est une agrégation particulière : toutes les instances de B contenues dans A sont supprimées lorsque A est supprimée.
Autre exemple plus complexe (pour revoir un peu d'orienté objet supplémentaire)
Instanciation
Exercice Orienté Objet
Réaliser une composition entre Author et Book.
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);
}
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)
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
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 Orienté Objet
Réaliser une abstraction entre une classe Fruit et deux classes Orange, Fraise
A noter : La classe Fruit ne doit pas pouvoir être instanciée.
Les trois éléments sont utilisées pour réaliser de la réutilisation de code descendante :
Exercice plus complet sur les interfaces
Envoyer le fichier "Exercice_interface.md"
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 ?
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
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 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 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 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
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.
POO
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 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.
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
Nous pouvons décider nous même de lever une exception avec l'instruction "throw".
On lève une
exception de type InvalidCastException
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 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 :
Une méthode d'ajout :
Une méthode de division :
Implémenter le try catch qu'il faut dans votre program.cs
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
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)
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é.
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 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.
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 :
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
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 :
Un exemple simple d'API, qui retourne juste une blague Chuck Norris :
https://api.chucknorris.io/jokes/random
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
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 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 !
Schéma (simplifié) du fonctionnement d'une API :
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
On peut utiliser une classe classique pour nos DTOs, mais en .Net, les records offrent certains avantages et une simplicité d'écriture.
Les avantages
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
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
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
Explications sur Swagger, son utilité et son utilisation (live)
Explications sur Postman, son utilité et son utilisation (live)
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.
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.
Step 1
Envoyer Workshop Step 1
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.
Schéma dans l'API
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)
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
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)
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
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
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é
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
Step 2
Envoyer Workshop Step 2
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.
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 :
MSTest est un framework de tests que l'on va utiliser tout au long de notre formation.
Les choses à savoir :
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 :
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 :
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
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 :
Pas ramassé mais c'est un bon exercice !
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
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 !
Nous pouvons directement utiliser le code pour créer notre base de données
On utilise la méthode static pour utiliser le Singleton.
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.
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)
Un exemple de modification...
Un exemple de suppression...
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 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.
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 de gestion d'une base de données avec SQLCommand
Envoyer le workshop "workshop_SQLCommand.md"
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.
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.
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
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" }
);
}
Réalisez un ORM pour réaliser des opérations CRUD sur un système :
L'objectif est de créer 3 objets :
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
Trois couches
Chaque couche a son propre objectif et ces couches ne communiquent que d'une seule manière avec les autres.
Modèle
Contrôleur
Vue
En utilisation normale,
la plupart des Frameworks le gère pour vous
Si s'en est ?
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 :
Exemples de Frameworks MVC :
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)
MVC
Exercice Orienté Objet
Réalisation d'un Pattern MVC
Deux possibilités :
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
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)
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.
Améliorations du jeu du serpent utilisé jusqu'à maintenant. Plusieurs possibilités :
En distanciel, peu d'intérêts à faire un QCM.
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 ?)