Articles
Codifier la sauce secrète
16 septembre 2019 • 6 min de lecture

Chaque application a sa sauce secrète, sa raison d’exister. Codifier la sauce secrète est essentiel pour écrire des applications maintenables et réussies.
Attendez. Qu’est-ce que codifier ? Patience mon ami, nous y arriverons.
Commençons par une hypothèse :
Vous venez d’être promu Ingénieur Logiciel Principal (Félicitations !). La première tâche de votre PDG est de créer un nouveau produit pour l’entreprise. C’est une application comptable développée de zéro. Les dirigeants estiment qu’avoir une solution comptable personnalisée leur donnera un avantage sur la concurrence.
Quelques mois ont passé, la plupart des préoccupations transversales sont développées (bravo !). L’équipe se concentre maintenant sur la partie savoureuse de l’application : le domaine métier (la sauce secrète). C’est là que commence la codification de la sauce secrète.
Codifier, c’est mettre une structure autour d’un concept essentiel dans le domaine métier.
En comptabilité, le ratio prix (P) bénéfice (E) (ratio P/E) est une mesure des bénéfices d’une entreprise. Un ratio P/E élevé suggère une forte croissance des bénéfices dans le futur. Le ratio P/E est calculé en prenant la valeur marchande par action (prix de l’action) divisée par le bénéfice par action (profit – dividendes / nombre d’actions en circulation).
Une implémentation simple, et j’argumente, naïve :
public class Metric
{
public string Name { get; set; }
public decimal Value {get; set}
public int Order {get; set;}
}
public class AccountingSummary
{
public Metric[] GetMetrics(decimal price, decimal earnings)
{
var priceEarningsRatio = price/earnings;
var priceEarningsRatioMetric = new Metric
{
Name = "P/E Ratio",
Value = priceEarningsRatio,
Order = 0
}
return new [] {priceEarningsRatioMetric};
}
}
Si ceci n’est utilisé qu’à un seul endroit, c’est correct. Que se passe-t-il si vous utilisez le ratio P/E dans d’autres zones ?
Comme ici dans PriceEarnings.cs
var priceEarningsRatio = price/earnings;
Et ici dans AccountSummary.cs
var priceEarningsRatio = price/earnings;
Et là-bas dans StockSummary.cs
var priceEarningsRatio = price/earnings;
Le ratio P/E est central à cette application, mais la façon dont il est implémenté, codé en dur à divers endroits, fait que l’importance du ratio P/E se perd dans un océan de code. C’est juste un autre arbre dans la forêt.
Vous vous exposez aussi au risque de changer le ratio à un endroit mais pas à l’autre. Cela peut perturber les calculs en aval. Ces types d’erreurs sont notoirement difficiles à trouver.
Souvent, les testeurs supposeront que si cela fonctionne dans une zone, c’est correct dans toutes les zones. Pourquoi l’application n’utiliserait-elle pas le même code pour générer le ratio P/E pour toute l’application ? N’est-ce pas le but de la Programmation Orientée Objet ?
Je peux imaginer une erreur comme celle-ci arrivant en production et n’étant découverte qu’lors d’une visite de votre dirigeant qui exige de savoir pourquoi les calculs de ratio P/E de la SEC sont différents de ce que l’entreprise a déposé. Ce n’est pas une bonne position.
Revisitons notre implémentation du ratio P/E et voyons comment nous pouvons améliorer notre première tentative.
Dans les systèmes comptables, les formules sont importantes, mettons une structure autour des formules en ajoutant une interface :
public interface IFormula
{
decimal Calculate<T>(T model);
}
Chaque formule est maintenant implémentée avec cette interface nous donnant cohérence et prévisibilité.
Voici notre ratio P/E amélioré après avoir implémenté notre interface :
Nous avons ajouté un PriceEarningsModel pour passer les données nécessaires dans notre méthode Calculate.
public class PriceEarningsModel
{
public decimal Price {get; set;}
public decimal Earnings {get; set;}
}
En utilisant notre PriceEarningsModel, nous avons créé une implémentation de l’interface IFormula pour le ratio P/E.
public class PriceEarningsRatioFormula : IFormula
{
public decimal Calculate<PriceEarningsModel>(PriceEarningsModel model)
{
return model.Price / model.Earnings;
}
}
Nous avons maintenant codifié le ratio P/E. C’est un concept de première classe dans notre application. Nous pouvons l’utiliser n’importe où. Il est testable, et un changement impacte toute l’application.
Pour rappel, voici l’implémentation avec laquelle nous avons commencé :
public class Metric
{
public string Name { get; set; }
public decimal Value {get; set}
public int Order {get; set;}
}
public class AccountingSummary
{
public Metric[] GetMetrics(decimal price, decimal earnings)
{
var priceEarningsRatio = price/earnings;
var priceEarningsRatioMetric = new Metric
{
Name = "P/E Ratio",
Value = priceEarningsRatio,
Order = 0
}
return new [] {priceEarningsRatioMetric};
}
}
C’est simple et fait le travail. Le problème est que le ratio P/E, qui est un concept central dans notre application comptable, ne ressort pas. Les ingénieurs non familiers avec l’application ou le domaine métier ne comprendront pas son importance.
Notre implémentation améliorée utilise notre nouvelle classe ratio P/E. Nous injectons la classe PriceEarningsRatioFormula dans notre classe AccountSummary.
Nous remplaçons notre ratio P/E codé en dur par notre nouvelle classe PriceEarningsRatioFormula
.
public class AccountingSummary
{
private PriceEarningsRatioFormula _peRatio;
public AccountingSummary(PriceEarningsRatioFormula peRatio)
{
_peRatio = peRatio;
}
public Metric[] GetMetrics(decimal price, decimal earnings)
{
var priceEarningsRatio = _peRatio.Calculate(new PriceEarningsModel
{
Price = price,
Earnings = earnings
});
var priceEarningsRatioMetric = new Metric
{
Name = "P/E Ratio",
Value = priceEarningsRatio,
Order = 0
}
return new [] {priceEarningsRatioMetric};
}
}
On pourrait argumenter qu’il y a un peu plus de travail avec la PriceEarningsRationFormula par rapport à l’implémentation précédente et je serais d’accord. Il y a un peu plus de cérémonie mais les bénéfices valent largement la petite augmentation de code et de cérémonie.
D’abord, nous gagnons la capacité de changer le ratio P/E pour toute l’application. Nous avons aussi une seule implémentation à déboguer si des défauts surviennent.
Enfin, nous avons codifié le concept de la PriceEarningsRatioFormula dans l’application. Quand un nouvel ingénieur rejoint l’équipe, il saura que les formules sont essentielles à l’application et au domaine métier.
Il existe d’autres méthodes de codification (encapsuler) du domaine, comme les microservices et les assemblages. Chaque approche a ses avantages et inconvénients, vous et votre équipe devrez décider ce qui est le mieux pour votre application.
Enchâsser les concepts clés du domaine dans des classes et interfaces crée des composants réutilisables et des frontières conceptuelles. Rendant une application plus facile à raisonner, réduisant les défauts et abaissant les barrières à l’intégration de nouveaux ingénieurs.
Auteur : Chuck Conway se spécialise dans l’ingénierie logicielle et l’IA générative. Connectez-vous avec lui sur les réseaux sociaux : X (@chuckconway) ou visitez-le sur YouTube.