Menu
Coddy logo textTech

Patterns d'immuabilité

Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy — leçon 34 sur 70.

L'immuabilité pousse l'encapsulation à son extrême logique : une fois qu'un objet est créé, il ne peut plus jamais changer. Cela élimine des catégories entières de bogues, car vous n'avez jamais à vous soucier de voir quelque chose modifier vos données de manière inattendue.

La manière la plus simple de créer une classe immuable est d'utiliser des champs readonly avec un constructeur qui définit toutes les valeurs, et de ne fournir aucun setter :

public class Point
{
    public readonly int X;
    public readonly int Y;
    
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

Une fois qu'un Point est créé, ses coordonnées ne peuvent pas changer. Mais que faire si vous avez besoin d'une version modifiée ? Au lieu de modifier l'objet existant, vous en retournez un nouveau :

public Point Move(int deltaX, int deltaY)
{
    return new Point(X + deltaX, Y + deltaY);
}

Le point d'origine reste inchangé tandis que vous obtenez un nouveau point avec des valeurs mises à jour. Ce modèle est utilisé partout dans .NET - les chaînes de caractères, par exemple, sont immuables. Lorsque vous appelez ToUpper(), vous obtenez une nouvelle chaîne plutôt que de modifier l'originale.

Les objets immuables sont intrinsèquement sûrs pour les threads car aucun code ne peut les modifier après leur création. Ils sont également plus faciles à appréhender car vous savez que leur état ne changera jamais de manière inattendue.

challenge icon

Défi

Facile

Construisons un système monétaire immuable qui démontre comment les objets peuvent être conçus pour ne jamais changer après leur création. Vous allez créer une classe Money où chaque opération retourne un nouvel objet au lieu de modifier l'original - un modèle qui rend votre code plus sûr et plus facile à raisonner.

Vous organiserez votre code sur deux fichiers :

  • Money.cs : Créez une classe Money immuable dans l'espace de noms Finance. Votre argent doit avoir :
    • Deux champs readonly : Amount (decimal) et Currency (string)
    • Un constructeur qui définit les deux valeurs - une fois créé, un objet Money ne peut jamais changer
    • Une méthode Add(decimal value) qui retourne un nouvel objet Money avec le montant augmenté (même devise)
    • Une méthode Subtract(decimal value) qui retourne un nouvel objet Money avec le montant diminué (même devise)
    • Une méthode Convert(string newCurrency, decimal rate) qui retourne un nouvel objet Money avec le montant multiplié par le taux et la nouvelle devise
    • Une méthode GetDisplay() qui retourne une chaîne de caractères au format "{Amount} {Currency}"
    Rappelez-vous : aucune de ces méthodes ne doit modifier l'objet original - elles retournent toutes de toutes nouvelles instances de Money !
  • Program.cs : Dans votre fichier principal, démontrez l'immuabilité en action. Créez un objet Money initial, puis effectuez des opérations sur celui-ci tout en conservant des références à l'original et aux résultats. Cela prouvera que l'original ne change jamais, même après plusieurs opérations.

Vous recevrez quatre entrées :

  • Montant initial (decimal)
  • Devise initiale (string)
  • Montant à ajouter (decimal)
  • Taux de conversion vers EUR (decimal)

Affichez la sortie dans ce format :

Original: {GetDisplay()}
After add: {GetDisplay()}
Original unchanged: {GetDisplay()}
Converted: {GetDisplay()}

Par exemple, si les entrées sont 100.00, USD, 50.00, et 0.85, la sortie devrait être :

Original: 100.00 USD
After add: 150.00 USD
Original unchanged: 100.00 USD
Converted: 127.50 EUR

Remarquez comment l'objet Money original affiche toujours 100.00 USD même après l'appel de Add() - c'est l'immuabilité ! La méthode Add() a créé un tout nouvel objet avec 150.00 USD, laissant l'original intact. La conversion est effectuée sur le résultat de l'opération d'ajout.

Essayez vous-même

using System;
using Finance;

class Program
{
    public static void Main(string[] args)
    {
        // Lire les entrées
        decimal initialAmount = Convert.ToDecimal(Console.ReadLine());
        string initialCurrency = Console.ReadLine();
        decimal amountToAdd = Convert.ToDecimal(Console.ReadLine());
        decimal conversionRate = Convert.ToDecimal(Console.ReadLine());

        // TODO: Créer un objet Money initial avec le montant et la devise initiaux

        // TODO: Afficher l'argent original en utilisant GetDisplay()

        // TODO: Appeler Add() sur l'original et stocker le résultat dans une nouvelle variable

        // TODO: Afficher le résultat après l'ajout en utilisant GetDisplay()

        // TODO: Afficher à nouveau l'original pour prouver qu'il est inchangé

        // TODO: Convertir le résultat ajouté en EUR en utilisant le taux de conversion

        // TODO: Afficher l'argent converti en utilisant GetDisplay()
    }
}
quiz iconTestez-vous

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