Fermer

avril 21, 2023

10 astuces de refactorisation C # impressionnantes

10 astuces de refactorisation C # impressionnantes


Bien que de nombreuses ressources faciles à utiliser soient disponibles pour aider à la refactorisation, vous ne les connaissez peut-être pas. Découvrez ces 10 conseils pour vous aider à effectuer une refactorisation efficace.

Ce que nous pouvons dire avec certitude, c’est que là où il y a création de code, il y aura aussi refactoring. Après tout, le code écrit aujourd’hui est l’héritage de demain, en particulier lorsqu’il s’agit de technologies Microsoft telles que .NET qui reçoivent plusieurs mises à jour chaque année.

En tant que développeurs, nous devons toujours être au courant des dernières améliorations apportées à la technologie dans laquelle nous travaillons pour en tirer le meilleur parti. Créer quelque chose qui ne sera pas obsolète dans quelques années, voire quelques mois, est impossible. Par conséquent, une autre base de code devient héritée et éligible pour la refactorisation.

Pour que nous soyons efficaces dans la refactorisation, plusieurs ressources peuvent nous aider, certaines restructurant simplement le code, d’autres via l’IDE Visual Studio. Continuez à lire pour apprendre 10 conseils pour vous aider à effectuer une refactorisation efficace.

L’importance de la refactorisation

Le refactoring est une technique qui consiste essentiellement à effectuer de petites transformations sur le code d’une manière qui ne modifie pas son comportement. Bien que petites, ces transformations facilitent la maintenance du code et visent à améliorer les performances d’une application.

Le refactoring est extrêmement important dans une équipe de développement car c’est ainsi que les programmeurs peuvent démontrer la valeur réelle de leurs performances dans le code existant. De plus, la refactorisation du code présente de nombreux avantages à court et à long terme, tels que :

  • Agilité: Un code bien écrit permet aux développeurs d’identifier et de résoudre plus rapidement un problème dans le code.
  • Expérience utilisateur: Avec moins de plantages et de meilleures performances, le logiciel devient plus facile à utiliser et offre une meilleure expérience à l’utilisateur final.
  • Modernisation: Le code refactorisé offre la possibilité de moderniser les bibliothèques et de placer l’entreprise propriétaire du code devant ses concurrents car elle utilise des technologies de pointe déjà consolidées sur le marché.

Refactorisation en C#

Le langage de programmation C# a toujours été en constante évolution et, dernièrement, les efforts de Microsoft pour transformer C# en un langage moins cérémonieux et avec de meilleures performances sont notables.

En ce qui concerne les nouveaux systèmes, nous sommes libres d’utiliser toutes les fonctionnalités de pointe mises à disposition par les dernières versions de C#, mais qu’en est-il du code hérité ? Ce code a été écrit alors que bon nombre de ces fonctionnalités n’existaient pas encore ou n’étaient pas utilisées pour une raison quelconque. Dans de tels cas, une refactorisation est nécessaire.

Voici une liste de conseils pour refactoriser le code en C#. Tout d’abord, je partagerai du code mal écrit, puis comment il serait possible de créer une meilleure version refactorisée. Certains exemples mettent également en évidence des conseils sur l’utilisation des fonctionnalités de Visual Studio pour effectuer une refactorisation plus rapidement.

Vous pouvez accéder au code source avec tous les exemples sur ce lien.

1. Au lieu de Foreach, utilisez LINQ

Foreach est l’une des méthodes les plus courantes utilisées par les programmeurs pour filtrer une liste de valeurs. Cependant, bien que son exécution soit efficace, sa syntaxe pollue généralement le code, car pour trouver une certaine valeur dans la liste, il est nécessaire de recourir à certains opérateurs de condition tels que if et else Par exemple. Pour rendre le code plus lisible, une excellente approche consiste à utiliser les ressources disponibles dans LINQ, comme on peut le voir dans l’exemple ci-dessous.

var sellers = Seller.AllSellers();
var smallSellers = new List<Seller>();

foreach (var seller in sellers)
{
    if (seller.SmallSeller)
    {
        smallSellers.Add(seller);
    }
}
var sellers = Seller.AllSellers();
var smallSellers = (from seller in sellers where seller.SmallSeller select seller).ToList();

ou

var sellers = Seller.AllSellers();
var smallSellers = (sellers.Where(seller => seller.SmallSeller)).ToList();

💡 Si vous utilisez Visual Studio, vous pouvez utiliser une ressource disponible qui effectue le travail de refactorisation pour vous. Placez simplement votre curseur sur le foreach code et cliquez sur l’icône de l’ampoule, et l’option « Convertir en LINQ » apparaîtra. Cela permet de prévisualiser le résultat du refactoring, comme le montre l’image ci-dessous :

Refactorisation de Visual Studio

2. Attribuez aux méthodes une responsabilité unique

Un problème très courant rencontré dans les refactorisations concerne les méthodes qui ont plus d’une responsabilité, c’est-à-dire qu’elles sont utilisées pour effectuer plusieurs actions, ce qui rend le code confus et difficile à comprendre. Lorsque nous créons des méthodes qui ont une seule responsabilité, nous pouvons organiser le code et le rendre plus propre et plus facile à comprendre.

Dans l’exemple ci-dessous, nous avons une méthode chargée de faire plusieurs choses dans la première version.

Tout d’abord, une recherche est effectuée pour renvoyer tous les vendeurs. Ensuite, il vérifie si les champs obligatoires du nouveau vendeur sont remplis. Si l’un d’entre eux est vide, un message d’erreur est retourné. Sinon, il vérifie si ce vendeur existe déjà dans la liste ; s’il existe déjà, un message d’erreur est renvoyé, sinon, le nouveau vendeur est ajouté à la base de données.


    public string CreateSeller(Seller seller)
    {
        var sellers = _context.Sellers;

        string requiredFieldsMessage = string.Empty;

        if (string.IsNullOrEmpty(seller.Name))
        {
            requiredFieldsMessage += "Name is required";
        }
        if (string.IsNullOrEmpty(seller.ContactEmail))
        {
            requiredFieldsMessage += "Email is mandatory";
        }
        if (!string.IsNullOrEmpty(requiredFieldsMessage))
            return requiredFieldsMessage;

        if (sellers.Contains(seller))
            return "Seller already exists";

        _context.Add(seller);
        _context.SaveChanges();
        return "Success";
    }

Voici l’occasion de créer des méthodes distinctes, chacune avec sa propre responsabilité.

Pour cela, nous allons créer trois nouvelles méthodes. Nous allons également changer le nom de la méthode principale pour la rendre plus adaptée à sa fonction principale.


public string CreateSellerProcess(Seller seller)
    {
        bool sellerAlreadyExists = SellerAlreadyExistsVerify(seller);

        if (sellerAlreadyExists)
            return "Seller already exists";

        string requiredFieldsMessage = ValidateFields(seller);

        if (!string.IsNullOrEmpty(requiredFieldsMessage))
            return requiredFieldsMessage;

        CreateNewSeller(seller);
        return "Success";
    }

    public bool SellerAlreadyExistsVerify(Seller seller)
    {
        var sellers = Seller.AllSellers();

        return sellers.Contains(seller);
    }

    public string ValidateFields(Seller seller)
    {
        string requiredFieldsMessage = string.Empty;

        if (string.IsNullOrEmpty(seller.Name))
        {
            requiredFieldsMessage += "Name is required";
        }
        if (string.IsNullOrEmpty(seller.ContactEmail))
        {
            requiredFieldsMessage += "Email is mandatory";
        }
        return requiredFieldsMessage;
    }

    public void CreateNewSeller(Seller seller)
    {
        _context.Add(seller);
        _context.SaveChanges();
    }

Notez que dans cette nouvelle version, les responsabilités pour chaque méthode ont été séparées. Nous avons une méthode pour vérifier si le vendeur existe déjà dans la base de données et une autre méthode pour valider les champs remplis. Et, enfin, nous avons une méthode pour sauvegarder la fiche si elle a passé les validations précédentes. Ainsi, le code est devenu beaucoup plus compréhensible et plus cohérent grâce à des validations mieux élaborées.

3. Passer de synchrone à asynchrone

La programmation asynchrone présente un grand avantage dans la mesure où il est possible d’exécuter de longues tâches en arrière-plan pendant que des tâches plus rapides sont en cours d’exécution. Un scénario qui peut souvent prendre beaucoup de temps concerne les transactions dans les bases de données, il est donc toujours conseillé d’utiliser fonctions asynchrones.

Dans l’exemple ci-dessous, nous avons d’abord un exemple de mise à jour synchrone des enregistrements dans la base de données. S’il y a peu d’enregistrements dans la base de données, cette exécution sera probablement rapide. Mais s’il y a beaucoup d’enregistrements, cela peut prendre du temps, et dans ce cas les autres opérations devront attendre d’être lancées. Ce n’est pas très performant.


public void UpdateSellers(Seller seller)
    {
        var sellerEntity = _context.Sellers.Find(seller.Id);

        _context.Entry(sellerEntity).CurrentValues.SetValues(seller);
    }

Ci-dessous, nous pouvons voir la même méthode mais effectuée de manière asynchrone. Notez que nous utilisons ORM Entity Framework Core dans cet exemple, qui a des méthodes asynchrones natives. De cette manière, la persistance dans la base de données devient plus performante car elle ne verrouille pas d’autres actions dans le code.


public async void UpdateSellersAsync(Seller seller)
{
    var sellerEntity = await _context.Sellers.FindAsync(seller.Id);
      _context.Entry(sellerEntity).CurrentValues.SetValues(seller);
      _context.SaveChangesAsync();
}

4. Générer des constructeurs pour simplifier les classes et les valeurs

L’utilisation de constructeurs est considérée comme une bonne pratique. Grâce à eux, nous parvenons à définir des valeurs par défaut, à modifier l’accès et à rendre plus explicites les valeurs nécessaires pour instancier une classe, en plus de maintenir un code plus propre lorsqu’une classe est appelée.

Remarquez dans l’exemple ci-dessous comment les classes sont instanciées sans constructeurs. La classe avec le constructeur est plus simple car on n’a pas besoin de déclarer les champs, il suffit de passer les valeurs par paramètre.

public void OrderProcess()
    {
        var orderWithoutConstructor = new OrderWithoutConstructor()
        {
            CustomerId = "14797513080",
            ProductId = "p69887424099",
            Value = 100
        };

        var orderWithConstructor = new OrderWithConstructor("14797513080", "p69887424099", 100);
    }

💡 Si vous utilisez Visual Studio, il est possible de générer le générateur via une action rapide, comme indiqué dans le GIF ci-dessous.

Générer un constructeur

5. Éliminer les chaînes If/Else

If et else les chaînes sont très courantes dans les refactorings et, bien qu’elles fonctionnent, elles rendent le code sale et difficile à comprendre. Pour éviter ce genre de problème, une alternative est d’utiliser la fonction native C#, switch.

Avec switchon parvient à obtenir le même résultat que if, mais d’une manière plus organisée et facile à comprendre. Ci-dessous, le même exemple, utilisant d’abord le if conditions et deuxièmement en utilisant le switch.

if (customer.Step == Steps.Start)
        {
            
        }
        if (customer.Step == Steps.InsertPhoneNumber)
        {
            
        }
        if (customer.Step == Steps.PhoneNumberOrEmailToVerify)
        {
            
        }
        if (customer.Step == Steps.VerifyToken)
        {
            
        }
        if (customer.Step == Steps.DownloadApp)
        {
            
        }
        if (customer.Step == Steps.WithLogin)
        {
            
        }
        if (customer.Step == Steps.Finished)
        {
            
        }
switch (customer.Step)
        {
            case Steps.Start:
                
                break;
            case Steps.InsertPhoneNumber:
                
                break;
            case Steps.PhoneNumberOrEmailToVerify:
                
                break;
            case Steps.VerifyToken:
                
                break;
            case Steps.DownloadApp:
                
                break;
            case Steps.WithLogin:
                
                break;
            case Steps.Finished:
                
                break;
            default:
                
                break;
        }

💡 Dans Visual Studio, il est possible d’utiliser une fonctionnalité qui remplit automatiquement la totalité switch structure. Tapez simplement le switch condition et cliquez ci-dessous, et toute la structure est créée, comme on peut le voir dans le GIF ci-dessous :

Générer un commutateur

6. Générer des interfaces

Les interfaces en C# sont des objets qui représentent des contrats, garantissant que le comportement de l’interface sera respecté dans les classes qui les implémentent.

Il est très courant de trouver des classes qui n’implémentent pas d’interfaces dans les refactorings. Pour résoudre ce problème, nous pouvons utiliser une fonction Visual Studio appelée Extract Interface qui génère automatiquement une interface basée sur la classe sélectionnée, comme illustré dans l’exemple ci-dessous :

Générer l'interface

7. Éliminez les variables inutiles

Bien qu’utiles, les variables sont souvent inutiles et polluent le code, le rendant plus difficile à lire.

Considérez toujours s’il est vraiment nécessaire d’utiliser une variable – il est souvent possible d’utiliser l’opérateur ternaire (?) ou une fonctionnalité LINQ comme le Any() méthode par exemple, comme on le voit dans l’exemple ci-dessous :

    public bool SmallSellerVerify(List<Seller> sellers)
    {
        var result = false;

        foreach (var seller in sellers)
        {
            if (seller.SmallSeller == true)
            {
                result = true;
            }
            else
            {
                result = false;
            }
        }
        return result;
    }


public bool SmallSellerVerifyRefactored(List<Seller> sellers) => sellers.Any(s => s.SmallSeller) ? true : false;


public bool SmallSellerVerifyRefactoredTwo(List<Seller> sellers) => sellers.Any(s => s.SmallSeller);

8. Renommer efficacement

Renommer des méthodes ou des variables peut prendre du temps si vous ne savez pas comment utiliser les bonnes ressources. Imaginez que vous renommiez une méthode utilisée par des dizaines de classes. Pour rationaliser cette tâche, une fonctionnalité de Visual Studio renommera l’objet dans toutes ses références.

Faites simplement un clic droit sur le nom que vous souhaitez renommer et choisissez « Renommer », entrez le nouveau nom et cliquez sur « Appliquer ».

Remane 1

Remane 2

9. Supprimer les utilisations inutiles

Suppression inutile using instances est toujours une bonne pratique dans les refactorisations, car cela laisse le code propre, avec moins de lignes.

Visual Studio a une fonctionnalité pour faciliter la suppression. Placez simplement le curseur sur un using qui n’est pas utilisé, cliquez sur l’icône de l’ampoule et choisissez l’option « Supprimer les utilisations inutiles ». Dans la fenêtre ouverte, vous aurez des options de suppression au niveau du document, du projet ou de la solution.

Supprimer les utilisations inutiles

10. Générer des méthodes automatiquement

En tant que développeurs, nous avons souvent besoin de gagner du temps, et une fonction très utile de Visual Studio est que vous pouvez générer des méthodes automatiquement. Écrivez simplement votre déclaration et transmettez les arguments d’entrée, puis cliquez sur l’icône de l’ampoule et choisissez l’option « Générer la méthode », comme indiqué dans le GIF ci-dessous :

Générer la méthode

Conclusion

Comme on le voit dans l’article, la refactorisation est une tâche omniprésente dans la journée du développement logiciel, et pour faciliter ce travail, il existe de nombreuses ressources, surtout si vous utilisez Visual Studio.

Ainsi, lors de la prochaine refactorisation que vous ferez, n’oubliez pas de revoir ces conseils et de les mettre en pratique.




Source link