Implémentation du masquage de données
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy. Leçon 33 sur 70.
La dissimulation des données va au-delà de la simple utilisation de champs private. Il s'agit de concevoir votre classe de manière à ce que les détails d'implémentation interne soient complètement invisibles pour le code extérieur, en n'exposant que ce qui est nécessaire via une interface publique propre.
Considérez une classe qui suit le mot de passe d'un utilisateur. Vous ne voulez pas que quiconque accède au mot de passe brut - pas même pour le lire :
public class UserAccount
{
private string passwordHash;
public void SetPassword(string password)
{
passwordHash = HashPassword(password);
}
public bool VerifyPassword(string password)
{
return HashPassword(password) == passwordHash;
}
private string HashPassword(string password)
{
return password.GetHashCode().ToString();
}
}Remarquez qu'il n'y a aucun moyen de récupérer le mot de passe ou même le hachage. Le code externe peut seulement définir un mot de passe ou en vérifier un - le mécanisme de stockage interne est complètement caché. La méthode HashPassword est également privée car il s'agit d'un détail d'implémentation qui pourrait changer sans affecter la façon dont la classe est utilisée.
Cette approche protège votre classe contre une mauvaise utilisation et vous donne la liberté de modifier les éléments internes plus tard. Si vous décidez d'utiliser un algorithme de hachage différent, aucun code externe ne sera interrompu car rien ne dépendait de la manière dont le mot de passe était stocké.
Défi
FacileConstruisons un système de portefeuille sécurisé qui démontre une véritable dissimulation des données. Vous allez créer un portefeuille numérique dont le solde est complètement protégé contre tout accès direct : le code externe peut uniquement effectuer des dépôts, des retraits et vérifier si des transactions sont possibles, mais ne peut jamais voir ni manipuler directement le solde réel.
Vous organiserez votre code sur deux fichiers :
Wallet.cs: créez une classeWalletdans l’espace de nomsFinancequi conserve son solde complètement masqué. Le portefeuille doit avoir :- un champ privé pour stocker le solde (decimal)
- une méthode privée
FormatBalance()qui renvoie le solde formaté comme une chaîne monétaire telle que"$123.45"— il s’agit d’un utilitaire interne qui ne doit pas être exposé - une méthode publique
Deposit(decimal amount)qui ajoute le montant au solde uniquement si celui-ci est positif, en renvoyanttrueen cas de réussite etfalsedans le cas contraire - une méthode publique
Withdraw(decimal amount)qui soustrait le montant du solde uniquement si celui-ci est positif et ne dépasse pas le solde actuel, en renvoyanttrueen cas de réussite etfalsedans le cas contraire - une méthode publique
CanAfford(decimal amount)qui renvoietruesi le solde est supérieur ou égal au montant, etfalsedans le cas contraire - une méthode publique
GetStatement()qui utilise en interne la méthode privéeFormatBalance()et renvoie"Current balance: {formatted balance}"
Program.cs: dans votre fichier principal, créez unWalletet effectuez une série de transactions à l’aide de valeurs saisies. Montrez comment le portefeuille protège son état interne tout en fournissant des fonctionnalités utiles par l’intermédiaire de son interface publique.
Vous recevrez trois entrées :
- Montant du dépôt initial (decimal)
- Montant du retrait à tenter (decimal)
- Montant pour lequel vérifier la possibilité de paiement (decimal)
Affichez la sortie dans ce format :
Deposit {amount}: {True/False}
{GetStatement() result}
Withdraw {amount}: {True/False}
{GetStatement() result}
Can afford {amount}: {True/False}Par exemple, si les entrées sont 100.50, 30.25 et 80.00, la sortie doit être :
Deposit 100.50: True
Current balance: $100.50
Withdraw 30.25: True
Current balance: $70.25
Can afford 80.00: FalseL’idée essentielle est que le code externe ne touche jamais directement au champ du solde. Même la chaîne contenant le solde formaté passe par une méthode publique qui utilise en interne un utilitaire privé. Il s’agit de la dissimulation des données : les détails d’implémentation sont complètement invisibles, et vous êtes libre de modifier la manière dont le solde est stocké ou formaté sans casser le code qui utilise votre portefeuille !
Essayez vous-même
using System;
using Finance;
class Program
{
public static void Main(string[] args)
{
// Lire les valeurs d'entrée
decimal depositAmount = Convert.ToDecimal(Console.ReadLine());
decimal withdrawAmount = Convert.ToDecimal(Console.ReadLine());
decimal checkAmount = Convert.ToDecimal(Console.ReadLine());
// TODO: Créer une instance de Wallet
// TODO: Effectuer un dépôt et afficher le résultat au format : "Deposit {amount}: {True/False}"
// TODO: Afficher le relevé en utilisant GetStatement()
// TODO: Effectuer un retrait et afficher le résultat au format : "Withdraw {amount}: {True/False}"
// TODO: Afficher le relevé en utilisant GetStatement()
// TODO: Vérifier la capacité de paiement et afficher le résultat au format : "Can afford {amount}: {True/False}"
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesEspaces de noms et directivesIntro aux classes et objetsLe mot-clé 'this'Méthodes et paramètresChamps vs PropriétésConstructeursInitialiseurs d'objetsRécapitulatif - Calculatrice simple4Héritage
Syntaxe de base de l'héritage (:)Le mot-clé 'base'Mots-clés Virtual & OverrideClasses scelléesLa classe de base 'object'Récapitulatif - Hiérarchie des employés7Fonctionnalités avancées
Surcharge d'opérateursIndexeurs (this[])Redéfinition de ToString()Méthodes d'extensionRécapitulatif - Liste personnalisée10Patrons de conception - Partie 1
Introduction aux patrons de conceptionSingleton Thread-SafePatron FabriquePatron Observateur (Événements)Patron Stratégie2Propriétés et membres statiques
Propriétés auto-implémentéesPropriétés en lecture/écriture seuleChamps et méthodes statiquesClasses statiquesMembres à corps d'expression5Polymorphisme & Interfaces
Polymorphisme : Compilation vs ExécutionInterface vs Classe AbstraiteInterfaces MultiplesInterfaces ExplicitesUpcasting & DowncastingRécapitulatif - Calculateur de Formes8Concepts avancés de la POO
Composition plutôt qu'héritageGénériques (Classes et Méthodes)Délégués et ÉvénementsAttributs et RéflexionIDisposable et l'instruction usingBases de l'Injection de Dépendances11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Architecture des classes
Données d'instance vs statiquesMots-clés 'readonly' & 'const'Champs de supportRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Modificateurs d'accèsPropriétés pour l'encapsulationImplémentation du masquage de donnéesPatterns d'immuabilitéRécapitulatif - Dossiers d'étudiants12Projet : Système de gestion de bibliothèque
Structure du projetModèles Livre et UtilisateurLogique du système d'empruntLINQ pour la rechercheInterface Console / Interface d'administrationTests unitaires (NUnit/xUnit)Entraînez-vous par vous-même : Compilateur C# en ligne