Derniers tips / Mémos
Modélise nativement « exactement l'un de ces types », avec un switch exhaustif vérifié par le compilateur.
Fin des state machines générées par le compilateur : moins d'allocations et des stack traces enfin lisibles.
Recherche sémantique directement dans SQL Server 2025, sans base vectorielle séparée, en LINQ typé.
Framework UI cross-platform pour .NET : Windows, macOS, Linux, iOS, Android et WebAssembly.
Découvrez les nouvelles APIs asynchrones pour la compression ZIP et les améliorations de performance dans .NET 10
Principes SOLID en C#
Parce que c'est souvent demandé en entretien, c'est utile d'avoir un rappel rapide.
SOLID regroupe 5 principes qui aident à concevoir un code orienté objet maintenable : responsabilité unique, ouverture/fermeture, substitution de Liskov, ségrégation d'interface, inversion des dépendances.
Principes SOLID
S — Single Responsibility (Responsabilité unique)
Une classe doit n'avoir qu'une seule raison de changer. Séparer les responsabilités réduit le couplage.
// SRP: OrderService handles order logic, ILogger handles logging
public interface ILogger
{
void Log(string message);
}
public class FileLogger : ILogger
{
public void Log(string message)
{
// ...
}
}
public class OrderService
{
private readonly ILogger _logger;
public OrderService(ILogger logger)
{
_logger = logger;
}
public void PlaceOrder(Order order)
{
// business logic
_logger.Log("Order placed");
}
}O — Open/Closed (Ouvert/Fermé)
Les entités doivent être ouvertes à l'extension mais fermées à la modification. Utiliser l'héritage ou la composition pour étendre le comportement.
// OCP: extend behavior via inheritance or new implementations
public interface IDiscount
{
decimal Apply(decimal amount);
}
public class NoDiscount : IDiscount
{
public decimal Apply(decimal amount) => amount;
}
public class SeasonalDiscount : IDiscount
{
public decimal Apply(decimal amount) => amount * 0.9m;
}L — Liskov Substitution (Substitution de Liskov)
Les sous-types doivent pouvoir remplacer les types de base sans altérer le comportement attendu.
// LSP: a Square should be usable where a Rectangle is expected
public class Rectangle
{
public virtual int Width { get; set; }
public virtual int Height { get; set; }
public int Area() => Width * Height;
}
public class Square : Rectangle
{
public override int Width
{
set
{
base.Width = base.Height = value;
}
}
public override int Height
{
set
{
base.Width = base.Height = value;
}
}
}I — Interface Segregation (Ségrégation des interfaces)
Préférer plusieurs interfaces spécifiques plutôt qu'une seule interface générale. Les clients ne dépendent que des méthodes qu'ils utilisent.
// ISP: small, focused interfaces
public interface IPrinter
{
void Print(Document d);
}
public interface IScanner
{
void Scan(Document d);
}
public class MultiFunctionPrinter : IPrinter, IScanner
{
public void Print(Document d)
{
}
public void Scan(Document d)
{
}
}D — Dependency Inversion (Inversion des dépendances)
Dépendre d'abstractions (interfaces), pas d'implémentations concrètes. Injecter les dépendances de haut niveau via des interfaces.
// DIP: high-level modules depend on abstractions
public interface IRepository<T>
{
void Add(T item);
}
public class SqlRepository<T> : IRepository<T>
{
public void Add(T item)
{
// persist
}
}
public class Service
{
private readonly IRepository<Order> _repo;
public Service(IRepository<Order> repo)
{
_repo = repo;
}
public void Save(Order o)
{
_repo.Add(o);
}
}Résumé
Appliquer SOLID augmente la testabilité et la maintenabilité, mais demande une discipline et peut accroître le nombre de types.
Avantages
- Meilleure testabilité et séparation des préoccupations
Inconvénients
- Plus de classes/interfaces à gérer, sur-ingénierie si mal appliqué
Bonnes pratiques
- Favoriser des interfaces petites et explicites; préférer l'injection de dépendances; éviter les classes trop générales.