Introduction : les deux faces d'une même médaille
\n\nImaginez que vous construisez une maison. Vous pouvez prendre des blocs prêts à l'emploi (classes, objets, héritage) et assembler une structure complexe — c'est la programmation orientée objet (POO). Ou vous pouvez penser comme un mathématicien : "je prends des données, je leur applique une fonction pure et j'obtiens un nouveau résultat, sans rien modifier" — c'est la programmation fonctionnelle.
\n\nEn C#, les deux paradigmes cohabitent de manière étonnante. Et si vous écrivez dans ce langage, vous vous poserez tôt ou tard la question : "Et si je fais cela de travers ? Peut-être devrais-je utiliser davantage LINQ et moins de classes ?"
\n\nDans cet article, nous ne débattrons pas de ce qui est mieux. Nous allons comprendre en quoi l'approche fonctionnelle diffère de la POO en C#, quand chacune est réellement utile, et quand elle nuit. Et oui, il y aura beaucoup de code. C'est parti !
\n\n1. La POO en C# : un classique qui fonctionne
\n\nLa programmation orientée objet repose sur l'état et le comportement. Vous avez une classe qui stocke des données (champs, propriétés) et des méthodes qui modifient ces données.
Exemple : une application de gestion de commandes pour une boutique en ligne.
\n\npublic class Order\n{\n public int Id { get; set; }\n public List<string> Items { get; private set; }\n public decimal TotalPrice { get; private set; }\n\n public Order(int id)\n {\n Id = id;\n Items = new List<string>();\n TotalPrice = 0;\n }\n\n public void AddItem(string itemName, decimal price)\n {\n Items.Add(itemName);\n TotalPrice += price;\n }\n\n public void ApplyDiscount(decimal percent)\n {\n TotalPrice -= TotalPrice * (percent / 100);\n }\n}\n\nQue voyons-nous ? Encapsulation : TotalPrice ne peut pas être modifié directement — uniquement via des méthodes. L'état de l'objet change au fil du temps : nous ajoutons des articles, appliquons des réductions. C'est de la POO pure.
Avantages de la POO en C#
\n- \n
- Modèle compréhensible du monde réel : Commande, Client, Produit — tout comme dans la vie. \n
- Réutilisation via l'héritage et les interfaces. \n
- Gestion de la complexité grâce à la division en petits objets. \n
Inconvénients de la POO
\n- \n
- Effets secondaires : une méthode peut modifier l'état, et vous perdez facilement le contrôle. \n
- Complexité des tests : il faut créer des objets, simuler des dépendances. \n
- Redondance : parfois, il est plus simple d'écrire une fonction que de créer une classe entière. \n
2. L'approche fonctionnelle en C# : LINQ et bien plus
\n\nLa programmation fonctionnelle repose sur les fonctions pures (sans effets secondaires) et l'immuabilité des données. En C#, elle est particulièrement visible dans LINQ, les expressions lambda et le travail avec les collections.
\n\nRésolvons le même problème — la gestion d'une commande — mais de manière fonctionnelle.
\n\n// Enregistrement immuable (record)\npublic record Order(int Id, List<string> Items, decimal TotalPrice);\n\npublic static class OrderFunctions\n{\n public static Order AddItem(Order order, string item, decimal price)\n {\n var newItems = order.Items.Append(item).ToList();\n return order with { Items = newItems, TotalPrice = order.TotalPrice + price };\n }\n\n public static Order ApplyDiscount(Order order, decimal percent)\n {\n return order with { TotalPrice = order.TotalPrice * (1 - percent / 100) };\n }\n}\n\n// Utilisation\nvar order = new Order(1, new List<string>(), 0);\norder = OrderFunctions.AddItem(order, "Ordinateur portable", 50000);\norder = OrderFunctions.ApplyDiscount(order, 10);\n\nVous avez remarqué ? Nous ne modifions pas l'objet d'origine. Chaque fois, une nouvelle instance est créée avec with. Cela élimine les modifications accidentelles.
Et