Earn More by Sharing What You Love
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!

Tim Corey
35m 50s
Les modèles de conception sont des solutions réutilisables à des problèmes courants de développement de logiciels, fournissant des modèles pour structurer et mettre en œuvre un code orienté objet d'une manière plus efficace et plus facile à maintenir. Ils aident les développeurs à résoudre les problèmes liés à la création, à la structure et à la communication d'objets de manière flexible et évolutive. Les modèles de conception sont des concepts de meilleures pratiques qui guident les développeurs dans l'écriture d'un meilleur code. L'un des principes fondamentaux de la conception de logiciels est le principe de responsabilité unique (SRP), qui fait partie des principes SOLID.
Dans sa vidéo, "Design Patterns : Single Responsibility Principle Explained Practically in C# (The S in SOLID)", Tim Corey explore le principe de responsabilité unique (SRP), en soulignant son importance dans la conception de logiciels et en donnant des indications pratiques sur la manière de le mettre en œuvre efficacement. Cet article offre un aperçu concis des principaux points à retenir de cette vidéo, en soulignant l'importance de l'ASR dans la création d'un code propre et facile à maintenir.
Dans la conception de logiciels, les principes SOLID sont essentiels pour créer un code maintenable et évolutif. Ils veillent à ce que le code soit facile à comprendre, à tester et à modifier. Les cinq principes - principe de responsabilité unique (SRP), principe d'ouverture/fermeture (OCP), principe de substitution de Liskov (LSP), principe de séparation des interfaces (ISP) et principe d'inversion des dépendances (DIP) - font partie intégrante de la conception orientée objet et peuvent être appliqués dans le cadre de modèles de conception pour rendre les solutions plus robustes.
En appliquant des modèles de conception en C#, les développeurs peuvent résoudre des problèmes courants plus efficacement. Qu'il s'agisse de créer des objets, de définir des structures arborescentes ou d'assurer la réutilisation d'instances uniques, les modèles de conception fournissent des solutions prédéfinies qui améliorent l'architecture logicielle. Les modèles tels que la méthode Factory, le Builder et le Singleton fournissent des solutions flexibles et réutilisables, tandis que les modèles comportementaux et structurels aident à gérer la complexité et à améliorer la communication au sein des systèmes. En apprenant et en utilisant ces modèles, les développeurs peuvent construire des systèmes plus faciles à maintenir et à étendre.
Tim aborde le concept d'ASR, en soulignant qu'il est essentiel pour les développeurs de s'assurer que leur code respecte les meilleures pratiques. L'ASR stipule qu'une classe ne doit avoir qu'une seule responsabilité ou raison de changer. Ce principe permet de maintenir un code propre, maintenable et évolutif.
Tim met en place une application console simple en C# qui demande le nom et le prénom de l'utilisateur, valide ces noms, puis génère un nom d'utilisateur. L'implémentation initiale viole le principe SRP, ce qui constitue une excellente occasion de démontrer comment remanier le code pour qu'il adhère à ce principe.
Tim explique l'ASR en soulignant les multiples responsabilités au sein de la classe initiale :
Chacune de ces responsabilités représente une raison différente pour laquelle la classe doit changer, ce qui constitue une violation de l'ASR.
Tim montre comment remanier le code pour suivre l'ASR en extrayant chaque responsabilité dans sa propre classe. Cette approche garantit que chaque classe a une seule raison d'être modifiée, ce qui rend le code plus modulaire et plus facile à maintenir.
Tim fournit un exemple pratique de remaniement :
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Welcome to my application");
Console.Write("Enter your first name: ");
string firstName = Console.ReadLine();
Console.Write("Enter your last name: ");
string lastName = Console.ReadLine();
if (string.IsNullOrWhiteSpace(firstName) || string.IsNullOrWhiteSpace(lastName))
{
Console.WriteLine("You did not give us valid information!");
Console.ReadLine();
return;
}
var userName = $"{firstName.Substring(0, 1)}{lastName}".ToLower();
Console.WriteLine($"Your username is {userName}");
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
}Imports System
Module Program
Sub Main(args As String())
Console.WriteLine("Welcome to my application")
Console.Write("Enter your first name: ")
Dim firstName As String = Console.ReadLine()
Console.Write("Enter your last name: ")
Dim lastName As String = Console.ReadLine()
If String.IsNullOrWhiteSpace(firstName) OrElse String.IsNullOrWhiteSpace(lastName) Then
Console.WriteLine("You did not give us valid information!")
Console.ReadLine()
Return
End If
Dim userName = $"{firstName.Substring(0, 1)}{lastName}".ToLower()
Console.WriteLine($"Your username is {userName}")
Console.WriteLine("Press enter to close...")
Console.ReadLine()
End Sub
End ModuleTout d'abord, Tim crée une classe pour gérer les messages standard affichés à l'utilisateur. Ce cours permettra de gérer les messages de bienvenue et les messages de fin.
public class StandardMessages
{
public static void WelcomeMessage()
{
Console.WriteLine("Welcome to my application");
}
public static void EndApplication()
{
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
public static void ShowValidationErrorMessage()
{
Console.WriteLine("You did not give us valid information!");
}
}Public Class StandardMessages
Public Shared Sub WelcomeMessage()
Console.WriteLine("Welcome to my application")
End Sub
Public Shared Sub EndApplication()
Console.WriteLine("Press enter to close...")
Console.ReadLine()
End Sub
Public Shared Sub ShowValidationErrorMessage()
Console.WriteLine("You did not give us valid information!")
End Sub
End ClassDans la classe Program, remplacez les appels directs à Console.WriteLine et Console.ReadLine par des appels aux méthodes de la classe StandardMessages :
class Program
{
static void Main(string[] args)
{
StandardMessages.WelcomeMessage();
// Other code...
StandardMessages.EndApplication();
}
}Module Program
Sub Main(args As String())
StandardMessages.WelcomeMessage()
' Other code...
StandardMessages.EndApplication()
End Sub
End ModuleEnsuite, Tim crée une classe pour capturer le nom et le prénom de la personne. Cette classe sera chargée de recueillir les données de l'utilisateur et de renvoyer un objet Person.
public class PersonDataCapture
{
public static Person Capture()
{
Person output = new Person();
Console.Write("Enter your first name: ");
output.FirstName = Console.ReadLine();
Console.Write("Enter your last name: ");
output.LastName = Console.ReadLine();
return output;
}
}Public Class PersonDataCapture
Public Shared Function Capture() As Person
Dim output As New Person()
Console.Write("Enter your first name: ")
output.FirstName = Console.ReadLine()
Console.Write("Enter your last name: ")
output.LastName = Console.ReadLine()
Return output
End Function
End ClassVous avez également besoin d'une classe Person pour contenir le nom et le prénom de l'utilisateur.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}Public Class Person
Public Property FirstName As String
Public Property LastName As String
End ClassDans la classe Program, remplacez la gestion de la saisie directe de l'utilisateur par un appel à PersonDataCapture.Capture :
class Program
{
static void Main(string[] args)
{
StandardMessages.WelcomeMessage();
Person user = PersonDataCapture.Capture();
// Other code...
StandardMessages.EndApplication();
}
}Module Program
Sub Main(args As String())
StandardMessages.WelcomeMessage()
Dim user As Person = PersonDataCapture.Capture()
' Other code...
StandardMessages.EndApplication()
End Sub
End ModuleEnsuite, Tim crée une classe pour gérer la validation du nom et du prénom de la personne. Cette classe sera chargée de s'assurer que les noms ne comportent pas d'espace nul ou d'espace blanc.
public class PersonValidator
{
public static bool Validate(Person person)
{
if (string.IsNullOrWhiteSpace(person.FirstName))
{
StandardMessages.ShowValidationErrorMessage("first name");
return false;
}
if (string.IsNullOrWhiteSpace(person.LastName))
{
StandardMessages.ShowValidationErrorMessage("last name");
return false;
}
return true;
}
}Public Class PersonValidator
Public Shared Function Validate(person As Person) As Boolean
If String.IsNullOrWhiteSpace(person.FirstName) Then
StandardMessages.ShowValidationErrorMessage("first name")
Return False
End If
If String.IsNullOrWhiteSpace(person.LastName) Then
StandardMessages.ShowValidationErrorMessage("last name")
Return False
End If
Return True
End Function
End ClassDans la classe Program, remplacez le code de validation par un appel à PersonValidator.Validate :
class Program
{
static void Main(string[] args)
{
StandardMessages.WelcomeMessage();
Person user = PersonDataCapture.Capture();
if (!PersonValidator.Validate(user))
{
StandardMessages.EndApplication();
return;
}
// Other code...
StandardMessages.EndApplication();
}
}Module Program
Sub Main(args As String())
StandardMessages.WelcomeMessage()
Dim user As Person = PersonDataCapture.Capture()
If Not PersonValidator.Validate(user) Then
StandardMessages.EndApplication()
Return
End If
' Other code...
StandardMessages.EndApplication()
End Sub
End ModuleTim déplace la logique de génération de nom d'utilisateur et de création de compte dans une nouvelle classe AccountGenerator.
Création de la classe AccountGenerator :
public class AccountGenerator
{
public static void CreateAccount(Person user)
{
string username = $"{user.FirstName.Substring(0, 1)}{user.LastName}".ToLower();
Console.WriteLine($"Your username is: {username}");
}
}Public Class AccountGenerator
Public Shared Sub CreateAccount(user As Person)
Dim username As String = $"{user.FirstName.Substring(0, 1)}{user.LastName}".ToLower()
Console.WriteLine($"Your username is: {username}")
End Sub
End ClassMise à jour de la classe principale :
class Program
{
static void Main(string[] args)
{
StandardMessages.WelcomeMessage();
Person user = PersonDataCapture.Capture();
bool isUserValid = PersonValidator.Validate(user);
if (!isUserValid)
{
StandardMessages.EndApplication();
return;
}
AccountGenerator.CreateAccount(user);
StandardMessages.EndApplication();
}
}Module Program
Sub Main(args As String())
StandardMessages.WelcomeMessage()
Dim user As Person = PersonDataCapture.Capture()
Dim isUserValid As Boolean = PersonValidator.Validate(user)
If Not isUserValid Then
StandardMessages.EndApplication()
Return
End If
AccountGenerator.CreateAccount(user)
StandardMessages.EndApplication()
End Sub
End Module
Dans cette dernière section, Tim Corey résume les avantages et la mise en œuvre du principe de responsabilité unique (SRP) à travers le processus de refactorisation du code de démonstration. Il souligne les avantages de diviser l'application en classes plus petites et plus ciblées.
Maintenance simplifiée du code :
Chaque classe a une responsabilité unique, ce qui facilite la localisation des modifications à apporter. Par exemple, la logique de capture des données utilisateur est clairement placée sous PersonDataCapture.
Cette structure simplifie la compréhension, car toute personne cherchant à modifier la validation de l'utilisateur sait qu'elle doit consulter PersonValidator.
Amélioration de la lisibilité :
StandardMessages.WelcomeMessage();
Person user = PersonDataCapture.Capture();
bool isUserValid = PersonValidator.Validate(user);
if (!isUserValid)
{
StandardMessages.EndApplication();
return;
}
AccountGenerator.CreateAccount(user);
StandardMessages.EndApplication();StandardMessages.WelcomeMessage()
Dim user As Person = PersonDataCapture.Capture()
Dim isUserValid As Boolean = PersonValidator.Validate(user)
If Not isUserValid Then
StandardMessages.EndApplication()
Return
End If
AccountGenerator.CreateAccount(user)
StandardMessages.EndApplication()Réduction de la complexité :
Les petites classes dont les responsabilités sont ciblées ont tendance à comporter moins de lignes de code, ce qui facilite leur compréhension et leur maintenance.
Exemple : Les méthodes de la classe StandardMessages sont concises et servent des objectifs uniques, tels que l'affichage d'un message de bienvenue ou la fin de l'application.
public class StandardMessages
{
public static void WelcomeMessage()
{
Console.WriteLine("Welcome to my application");
}
public static void EndApplication()
{
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
public static void ShowValidationErrorMessage(string fieldName)
{
Console.WriteLine($"You did not give us a valid {fieldName}!");
}
}Public Class StandardMessages
Public Shared Sub WelcomeMessage()
Console.WriteLine("Welcome to my application")
End Sub
Public Shared Sub EndApplication()
Console.WriteLine("Press enter to close...")
Console.ReadLine()
End Sub
Public Shared Sub ShowValidationErrorMessage(fieldName As String)
Console.WriteLine($"You did not give us a valid {fieldName}!")
End Sub
End Class
Facilité de modification du code :
Étant donné que chaque classe a une seule raison de changer, la modification du code en réponse à de nouvelles exigences devient simple.
Exemple : S'il s'agit de modifier le message de fin, la modification s'effectue uniquement dans la méthode StandardMessages.EndApplication.
Meilleur débogage et meilleure collaboration :
Avec des classes plus petites et bien définies, le débogage devient plus simple car vous pouvez facilement localiser l'emplacement d'un problème.
Les nouveaux développeurs peuvent s'intégrer plus rapidement, en comprenant la structure claire et les responsabilités de chaque classe.
Tim répond à une préoccupation commune, à savoir que l'application de l'ASR donne lieu à un trop grand nombre de classes, ce qui alourdit le projet :
Navigation et compréhension :
Des outils comme IntelliSense dans Visual Studio facilitent la navigation dans plusieurs classes. Par exemple, en appuyant sur F12, on accède directement à la définition des méthodes ou des classes.
Le fait d'avoir de nombreux petits éléments gérables peut faciliter la compréhension de l'ensemble de l'application par rapport à de grandes classes monolithiques.
Performance et stockage :
Equilibre et excès :
Tim conseille de trouver un équilibre. Si la responsabilité d'une classe devient trop importante, examinez si elle a plusieurs raisons de changer, ce qui indiquerait qu'elle a besoin d'être divisée davantage.
Il suggère que si vous devez faire défiler une classe de manière extensive dans Visual Studio, il se peut qu'elle soit trop grande et qu'il faille la diviser.
Tim encourage les développeurs à appliquer progressivement l'ASR, en particulier dans les bases de code existantes. Commencez par de petites modifications et un nouveau code pour vous aligner sur les principes de l'ASR. Cette approche incrémentale garantit des transitions plus fluides et une amélioration continue.
L'exemple de refactorisation de Tim Corey montre comment le respect du principe de responsabilité unique (SRP) permet d'obtenir un code plus propre et plus facile à maintenir. En divisant les responsabilités en classes plus petites et plus ciblées, les développeurs peuvent améliorer la lisibilité, le débogage et la collaboration au sein de leurs bases de code. Ce principe fondamental des modèles de conception SOLID ouvre la voie à des principes plus avancés et à de meilleures pratiques en matière de développement logiciel.
Pour obtenir des informations plus détaillées et des exemples de code, veuillez regarder sa vidéo et visiter son canal pour d'autres vidéos sur les modèles de conception.
Do you create content for developers working with .NET, C#, Java, Python, or Node.js? Turn your expertise into extra income!
Join our newsletter, you’ll get exclusive access on article updates. We value your privacy