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 montre comment concevoir des objets pour qu’ils ne changent jamais après leur création. Vous allez créer une classe Money dans laquelle chaque opération renvoie un nouvel objet au lieu de modifier l’original — un modèle qui rend votre code plus sûr et plus facile à comprendre.

Vous allez organiser votre code sur deux fichiers :

  • Money.cs : créez une classe Money immuable dans l’espace de noms Finance. Votre système monétaire 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 plus jamais changer
    • Une méthode Add(decimal value) qui renvoie un nouvel objet Money avec le montant augmenté (même devise)
    • Une méthode Subtract(decimal value) qui renvoie un nouvel objet Money avec le montant diminué (même devise)
    • Une méthode Convert(string newCurrency, decimal rate) qui renvoie un nouvel objet Money avec le montant multiplié par le taux et la nouvelle devise
    • Une méthode GetDisplay() qui renvoie une chaîne au format "{Amount} {Currency}"
    Souvenez-vous : aucune de ces méthodes ne doit modifier l’objet original — elles renvoient toutes de nouvelles instances de Money !
  • Program.cs : dans votre fichier principal, démontrez l’immuabilité en pratique. Créez un objet Money initial, puis effectuez des opérations dessus tout en conservant des références vers l’original et vers les 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 doit être :

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

Remarquez que l’objet Money original affiche toujours 100.00 USD même après l’appel à Add() — c’est cela, l’immuabilité ! La méthode Add() a créé un objet complètement nouveau avec 150.00 USD, en 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

Entraînez-vous par vous-même : Compilateur C# en ligne