JavaRush /Blog Java /Random-FR /Règles du code : le pouvoir d'une dénomination appropriée...

Règles du code : le pouvoir d'une dénomination appropriée, les bons et les mauvais commentaires

Publié dans le groupe Random-FR
Règles d'écriture de code : le pouvoir d'une dénomination correcte, des bons et des mauvais commentaires - 1 À quelle fréquence avez-vous dû comprendre le code de quelqu’un d’autre ? Quand, au lieu de quelques heures, vous passez des journées juste à comprendre la logique de ce qui se passe. Le plus drôle, c’est que pour celui qui a écrit ce code, tout est clair et très transparent. Et ce n'est pas surprenant : après tout, le code parfait ou idéal est un concept très vague, car chaque développeur a respectivement sa propre vision du monde et du code. Plus d'une fois, j'ai été confronté à une situation où mon collègue et moi avons examiné le même code et avions des opinions différentes sur son exactitude et sa propreté. Règles d'écriture de code : le pouvoir d'une dénomination correcte, les bons et les mauvais commentaires - 2C'est un sentiment familier, n'est-ce pas ? Cependant, il convient de respecter certains points éprouvés qui, en fin de compte, joueront en notre faveur, car si vous laissez votre code dans l'état dans lequel vous souhaiteriez vous-même le recevoir, le monde serait un peu plus heureux et nettoyeur. Règles d'écriture de code : le pouvoir d'une dénomination correcte, les bons et les mauvais commentaires - 3Dans notre dernier article sur les règles d'écriture du code (ou plutôt un petit guide), nous avons abordé un peu les recommandations pour écrire le système dans son ensemble et ses éléments tels que les objets, leurs interfaces, classes, méthodes et variables. J'y ai brièvement mentionné la dénomination correcte de certains éléments. Aujourd'hui, je voudrais parler exactement de cela, car les noms corrects facilitent grandement la lisibilité du code. Nous clôturerons le sujet du code correct à l'aide de réflexions et de petits exemples de commentaires dans le code - est-ce bon ou moins bon. Alors, commençons.

Nom correct

Les noms corrects améliorent la lisibilité du code, ce qui permet de gagner du temps lors de la familiarisation, car il est beaucoup plus facile d'utiliser une méthode lorsque le nom décrit grossièrement sa fonctionnalité. Puisque tout dans le code est constitué de noms (variables, méthodes, classes, objets fichier, etc.), ce point devient très important lors de la création d'un code correct et propre. Sur la base de ce qui précède, le nom doit indiquer pourquoi, par exemple, une variable existe, ce qu'elle fait et comment elle est utilisée. Je noterai encore et encore que le meilleur commentaire pour décrire une variable est son nom correct. Règles d'écriture de code : le pouvoir d'une dénomination correcte, les bons et les mauvais commentaires - 4

Nommer les interfaces

Les interfaces utilisent généralement des noms commençant par une lettre majuscule et écrits en casse camel (CamelCase). C'était une bonne pratique lors de l'écriture d'une interface de la préfixer avec un I pour la désigner comme une interface (par exemple IUserService), mais c'est assez moche et distrayant. Dans de tels cas, il est préférable d'écrire sans (UserService) et d'ajouter -Impl (UserServiceImpl) à son implémentation. Eh bien, ou en dernier recours, ajoutez le préfixe C (CUserService) à son implémentation.

Noms de classe

Tout comme les interfaces, les noms sont en majuscules et utilisent le style camel (CamelCase). Peu importe le type d’apocalypse qui se produit, peu importe la rapidité des délais, mais rappelez-vous jamais, le nom d’une classe ne doit jamais être un verbe ! Les noms de classe et d'objet doivent être des noms et leurs combinaisons (UserController, UserDetails, UserAccount, etc.). Vous ne devez pas fournir le nom de chaque classe avec l'abréviation de cette application, car cela ne ferait qu'ajouter une complexité inutile (par exemple, nous avons une application de migration de données utilisateur et nous ajouterons un UDM à chaque classe - UDMUserDeatils, UDMUserAccount, UDMUserController ).

Noms des méthodes

Habituellement, les noms des méthodes commencent par une petite lettre, mais ils utilisent également le style camel (CamelCase). Nous avons parlé ci-dessus du fait que les noms de classes ne devraient jamais être des verbes. Ici, la situation est diamétralement opposée : les noms des méthodes doivent être des verbes ou leurs combinaisons avec des verbes : findUserById, findAllUsers, createUser, etc. Lors de la création d'une méthode (ainsi que de variables et de classes), pour éviter toute confusion, utilisez une seule approche de dénomination. Par exemple, pour rechercher un utilisateur, la méthode peut être écrite sous la forme getUserById ou findUserById. Et encore une chose : n'utilisez pas d'humour dans les noms des méthodes, car ils pourraient ne pas comprendre la blague, ni ce que fait cette méthode.

Noms de variables

Dans la plupart des cas, les noms de variables commencent par une lettre minuscule et utilisent également Camelcase, sauf dans les cas où la variable est une constante globale. Dans de tels cas, toutes les lettres du nom sont écrites en majuscules et les mots sont séparés par un trait de soulignement - « _ ». Lorsque vous nommez des variables, vous pouvez utiliser un contexte significatif pour plus de commodité. En d'autres termes, lorsqu'une variable fait partie de quelque chose de plus grand - par exemple, firstName, lastName, status - dans de tels cas, vous pouvez ajouter un préfixe indiquant l'objet dont cette variable fait partie. Par exemple : userFirstName, userLastName, userStatus. Vous devez également éviter les noms similaires pour les variables lorsqu'elles ont des significations complètement différentes. Antonymes courants pour les variables :
  • début/fin
  • premier Dernier
  • verrouillé/déverrouillé
  • min max
  • suivant précédent
  • ancien nouveau
  • ouvert/fermé
  • visible/invisible
  • cible Source
  • source/destination
  • haut/bas

Noms de variables courts

Lorsque nous avons des variables comme x ou n ou quelque chose comme ça, nous ne voyons pas immédiatement l'intention de la personne qui a écrit le code. Ce que fait la méthode n n'est pas évident : elle nécessite une réflexion plus réfléchie (et c'est du temps, du temps, du temps). Par exemple, nous avons un champ - l'identifiant de l'utilisateur responsable, et au lieu d'un nom comme x ou simplement id, nous appellerons cette variable responsableUserId, ce qui augmente immédiatement la lisibilité et la signification. Cependant, les noms courts comme n ont leur place en tant que modifications locales apportées aux petites méthodes, où le bloc de code avec cette modification ne représente que quelques lignes de code, et le nom de la méthode décrit parfaitement ce qui s'y passe. Un développeur, voyant une telle variable, comprend son importance secondaire et sa portée très limitée. En conséquence, il existe une certaine dépendance à la longueur du nom de la variable : plus il est long, plus la variable est globale et vice versa. A titre d'exemple, une méthode pour rechercher le dernier utilisateur enregistré par date :
public User findLastUser() {
   return findAllUsers().stream()
           .sorted((x, y) -> -x.getCreatedDate().compareTo(y.getCreatedDate()))
           .findFirst()
           .orElseThrow(() -> new ResourceNotFoundException("Any user doesn't exist "));
}
Ici, nous utilisons les noms courts x et y pour définir le tri des flux et les oublions.

Longueur optimale

Continuons le sujet de la longueur du nom. La longueur de nom optimale se situe quelque part entre la longueur de nom maximumNumberOfUsersInTheCurrentGroup et n. Autrement dit, les programmes trop courts souffrent d'un manque de sens, et les programmes trop longs étirent le programme sans ajouter de lisibilité, et ils sont tout simplement trop paresseux pour les écrire à chaque fois. Sans tenir compte du cas ci-dessus, pour les variables avec un nom court comme n, vous devez maintenir la longueur à environ 8 à 16 caractères. Il ne s’agit pas d’une règle stricte : plutôt d’une ligne directrice.

Petites différences

Je ne peux pas ignorer les différences subtiles dans les noms, car c'est aussi une mauvaise pratique, car vous pouvez simplement vous perdre ou passer beaucoup de temps supplémentaire à remarquer des différences mineures dans les noms. Par exemple, la différence entre InvalidDataAccessApiUsageException et InvalidDataAccessResourceUsageException est difficile à repérer d'un seul coup d'œil. De plus, des informations erronées peuvent souvent survenir lors de l'utilisation de petits L et O, car ils peuvent facilement être confondus avec 1 et 0 : dans certaines polices, la différence est plus évidente, dans d'autres moins.

Partie sémantique

Nous devons mettre la partie sémantique dans les noms, mais pas surjouer avec les synonymes, puisque, par exemple, UserData et UserInfo ont en fait la même signification, et nous devrons creuser un peu plus dans le code pour comprendre de quel objet spécifique nous avons besoin . Évitez les mots non informatifs, par exemple firstNameString : pourquoi avons-nous besoin de la chaîne de mots ? Un nom peut-il être un objet de type date ? Bien sûr que non : donc simplement - prénom. A titre d'exemple, je voudrais mentionner les variables booléennes, par exemple flagDelete. Le mot drapeau n’a aucune signification sémantique. Il aurait été plus raisonnable de l'appeler - isDelete.

Désinformation

Je voudrais également dire quelques mots sur les noms incorrects. Disons que nous avons le nom userActivityList et que l'objet ainsi nommé n'est pas du type List, mais un autre conteneur ou objet personnalisé pour le stockage. Cela peut dérouter le programmeur moyen : il serait préférable de l'appeler quelque chose comme userActivityGroup ou userActivities.

Recherche

L'un des inconvénients des noms courts et simples est qu'ils sont difficiles à trouver dans une grande quantité de code, car qu'est-ce qui serait plus facile à trouver : une variable appelée nom ou NAME_FOR_DEFAULT_USER ? Bien sûr, la deuxième option. Il est nécessaire d'éviter les mots (lettres) fréquents dans les noms, car cela ne ferait qu'augmenter le nombre de fichiers trouvés lors de la recherche, ce qui n'est pas bon. Nous tenons à vous rappeler que les programmeurs passent plus de temps à lire du code qu'à l'écrire, alors faites attention à la dénomination des éléments de votre application. Mais que se passe-t-il si vous ne parvenez pas à le nommer avec succès ? Que se passe-t-il si le nom d’une méthode ne décrit pas bien ses fonctionnalités ? C'est là que cela entre en jeu, notre prochain élément concerne les commentaires.

commentaires

Règles d'écriture de code : le pouvoir d'une dénomination correcte, les bons et les mauvais commentaires - 5Rien ne vaut un commentaire pertinent, mais rien n'encombre un module comme des commentaires dénués de sens, obsolètes ou trompeurs. C'est une arme à double tranchant, n'est-ce pas ? Néanmoins, vous ne devriez pas traiter les commentaires comme un bien sans ambiguïté : plutôt comme un moindre mal. Après tout, un commentaire, par essence, est une compensation pour une pensée exprimée sans succès dans le code. Par exemple, nous les utilisons pour transmettre d'une manière ou d'une autre l'essence de la méthode si elle s'avère trop déroutante. Dans une telle situation, il est préférable de refactoriser correctement le code plutôt que d’écrire des notes descriptives. Plus le commentaire est ancien, pire c'est, car le code a tendance à grandir et à évoluer, mais le commentaire peut rester le même, et plus il va loin, plus ces notes deviennent douteuses. Les commentaires inexacts sont bien pires que l’absence de commentaires, car ils prêtent à confusion et trompent, donnant de fausses attentes. Et même si nous avons un code très délicat, cela vaut toujours la peine de ne pas le commenter, mais de le réécrire.

Types de commentaires

  • les commentaires légaux sont des commentaires laissés au début de chaque fichier de code source pour des raisons juridiques, telles que :

    * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
    * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.

  • commentaires informatifs : commentaires qui fournissent une explication du code (fournissant des informations supplémentaires ou l'intention d'une section donnée du code.

    Par exemple:

    /*
    * Объединяет пользователя из бд и пришедшего для обновления
    * Когда в requestUser поле пустое, оно заполняется старыми данными из foundUser
    */
    private User mergeUser(User requestUser, User foundUser) {
           return new User(
           foundUser.getId(),
           requestUser.getFirstName() == null ? requestUser.getFirstName() : foundUser.getFirstName(),
           requestUser.getMiddleName() == null ? requestUser.getMiddleName() : foundUser.getMiddleName(),
           requestUser.getLastName() == null ? requestUser.getLastName() : foundUser.getLastName(),
           requestUser.getAge() == null ? requestUser.getAge() : foundUser.getAge()
           );
           }

    Dans ce cas, vous pouvez vous passer de commentaires, puisque le nom de la méthode et ses arguments, couplés à la fonctionnalité très transparente, se décrivent assez bien.

  • commentaire d'avertissement - un commentaire dont le but est d'avertir les autres développeurs des conséquences indésirables d'une action (par exemple, pourquoi le test a été marqué comme @Ignore) :

    // Слишком долго отрабатывает
    // Не запускайте, если не располагаете избытком времени
    @Ignore
    @Test
    public void someIntegrationTest() {
           ……
           }
  • TODO - commentaires qui sont des notes pour l'avenir qui devront être faits, mais qui, pour une raison quelconque, ne peuvent pas être faits maintenant. Il s’agit d’une bonne pratique, mais elles doivent néanmoins être révisées régulièrement pour supprimer celles qui ne sont pas pertinentes afin d’éviter l’encombrement.

    Un exemple serait :

    //TODO: Add a check for the current user ID (when will be created security context)
    
    @Override
    public Resource downloadFile(File file) {
           return fileManager.download(file);
           }

    Ici, nous notons que nous devons ajouter une vérification de l'utilisateur qui télécharge (dont nous extrairons l'identifiant du contexte de sécurité) avec celui qui a enregistré.

  • commentaire de renforcement - un commentaire qui souligne l'importance d'une circonstance qui, à première vue, peut sembler insignifiante.

    À titre d'exemple, un élément d'une méthode qui remplit une base de données de test avec des scripts :

    Stream.of(IOUtils.resourceToString("/fill-scripts/" + x, StandardCharsets.UTF_8)
           .trim()
           .split(";"))
           .forEach(jdbcTemplate::update);
    // Вызов trim() очень важен, убирает возможные пробелы в конце скрипта
    // чтобы при считке и разбивке на отдельные requestы не было пустых

  • javaDoc - commentaires qui décrivent l'API de certaines fonctionnalités pour un usage général. Probablement les commentaires les plus utiles, car une API documentée est beaucoup plus facile à utiliser, mais ils peuvent aussi devenir obsolètes, comme toutes les autres. Par conséquent, n'oubliez pas que la principale contribution à la documentation ne réside pas dans les commentaires, mais dans le bon code.

    Un exemple de méthode de mise à jour utilisateur tout à fait normale :

    /**
    * Обновляет передаваемые поля для пользователя по id.
    *
    * @param id  id обновляемого пользователя
    * @param user пользователь с заполненными полями для обновления
    * @return обновленный пользователь
    */
           User update(Long id, User user);

Mauvais scripts de commentaires

Règles d'écriture de code : le pouvoir d'une dénomination correcte, les bons et les mauvais commentaires - 7
  • commentaire marmonnant - commentaires qui sont généralement écrits à la hâte, dont le sens n'est clair que pour le développeur qui les a écrits, puisque lui seul voit la situation avec les nuances auxquelles il se réfère.

    Considérez cet exemple :

    public void configureSomeSystem() {
           try{
           String configPath = filesLocation.concat("/").concat(CONFIGURATION_FILE);
           FileInputStream stream = new FileInputStream(configPath);
           }  catch (FileNotFoundException e) {
           //В случае отсутствия конфигурационного file, загружается конфигурация по умолчанию
          }
    }

    Qui charge ces paramètres ? Ont-ils déjà été téléchargés ? La méthode est-elle destinée à intercepter les exceptions et à appeler les paramètres par défaut ? Trop de questions se posent, dont les réponses ne peuvent être obtenues qu'en approfondissant l'étude d'autres parties du système.

  • un commentaire redondant est un commentaire qui ne porte aucune charge sémantique, car ce qui se passe dans une section de code donnée est déjà clair (ce n'est pas plus facile à lire que le code).

    Regardons un exemple :

    public class JdbcConnection{
    public class JdbcConnection{
       /**
        * Журнальный компонент, связанный с текущим классом
        */
       private Logger log = Logger.getLogger(JdbcConnection.class.getName());
    
       /**
        * Создаёт и возвращает connection с помощью входящих параметров
        */
       public static Connection buildConnection(String url, String login, String password, String driver) throws Exception {
           Class.forName(driver);
           connection = DriverManager.getConnection(url, login, password);
           log.info("Created connection with db");
           return connection;
       }

    A quoi servent de tels commentaires si on voit déjà tout parfaitement

  • faux commentaires - commentaires qui ne correspondent pas à la vérité et ne font qu'induire en erreur (désinformer). Tel que:

    /**
    * Вспомогательный метод, закрывает соединение со сканером, если isNotUsing истинно
    */
    private void scanClose(Scanner scan, boolean isNotUsing) throws Exception {
       if (!isNotUsing) {
           throw new Exception("The scanner is still in use");
       } scan.close();
    }

    Quel est le problème avec ce commentaire ? Et le fait qu'il nous ment un peu, car la connexion est fermée si isNotUsing = false, mais pas l'inverse, comme nous le dit la marque.

  • commentaires obligatoires - commentaires qui sont considérés comme obligatoires (Javadoc), mais qui en fait sont parfois inutilement encombrés, peu fiables et inutiles (vous devez vous demander si de tels commentaires sont nécessaires ici).

    Exemple:

    /**
    *  Creation пользователя по переданным параметрам
    * @param firstName Name созданного пользователя
    * @param middleName среднее Name созданного пользователя
    * @param lastName фамorя созданного пользователя
    * @param age возраст созданного пользователя
    * @param address addressс созданного пользователя
    * @return пользователь который был создан
    */
    User createNewUser(String firstName, String middleName, String lastName, String age, String address);

    Seriez-vous capable de comprendre ce que fait la méthode sans ces commentaires ? Très probablement oui, donc les commentaires dans ce cas n'ont plus de sens.

  • les commentaires du journal sont des commentaires qui sont parfois ajoutés au début d'un module à chaque fois qu'il est modifié (quelque chose comme un journal des modifications apportées).

    /**
    *  Записи ведутся с 09 января 2020;
    **********************************************************************
    *  09.01.2020  : Обеспечение соединения с БД с помощью Jdbc Connection;
    *  15.01.2020  : Добавление интерфейсов уровня дао для работы с БД;
    *  23.01.2020  : Добавление интеграционных тестов для БД;
    *  28.01.2020  : Имплементация интерфейсов уровня дао;
    *  01.02.2020  : Разработка интерфейсов для сервисов,
    *  согласно требованиям прописанным в user stories;
    *  16.02.2020  : Имплементация интерфейсов сервисов
    *  (реализация бизнес логики связанной с работой БД);
    *  25.02.2020  : Добавление тестов для сервисов;
    *  08.03.2020  : Празднование восьмого марта(Миша опять в хлам);
    *  21.03.2020  : Рефакторинг сервис слоя;
    */

    À une certaine époque, ce passage était justifié, mais avec l'avènement des systèmes de gestion de code source (par exemple, Git), cela est devenu un encombrement et une complication inutiles du code.

  • commentaires liens vers les auteurs - commentaires dont le but est d'indiquer la personne qui a écrit le code, afin que vous puissiez la contacter et discuter de comment, quoi et pourquoi :

    * @author  Bender Benderovich

    Encore une fois, les systèmes de contrôle de version se souviennent parfaitement de qui a ajouté ce code et quand, et cette approche est inutile.

  • le code commenté est un code qui a été commenté pour une raison ou une autre. Une des pires habitudes, parce que vous l’avez commenté et oublié, et que les autres développeurs n’ont tout simplement pas le courage de le supprimer (et si c’était quelque chose de précieux).

    //    public void someMethod(SomeObject obj) {
    //    .....
    //    }

    En conséquence, ils s’accumulent comme des déchets. En aucun cas, un tel code ne doit être laissé. Si vous en avez vraiment besoin, n’oubliez pas le système de contrôle de version.

  • les commentaires non évidents sont des commentaires qui décrivent quelque chose d'une manière inutilement complexe.

    /*
        * Начать с массива, размер которого достаточен для хранения
        * всех byteов данных (плюс byteы фильтра) с запасом, плюс 300 byte
        * для данных заголовка
        */
    this.dataBytes = new byte[(this.size * (this.deep + 1) * 2)+300];

    Un commentaire doit expliquer le code, pas besoin d'une explication elle-même. Qu'est ce qu'il y a ici? Que sont les « octets de filtre » ? Qu'est-ce que +1 a à voir avec ça ? Pourquoi exactement 300 ?

Si vous décidez d'écrire des commentaires, voici quelques conseils pour les utiliser :
  1. Utilisez des styles faciles à entretenir : entretenir des styles trop fantaisistes et exotiques peut être ennuyeux et prendre beaucoup de temps.
  2. N'utilisez pas de commentaires à la fin des lignes qui font référence à des lignes simples : cela crée une grande pile de commentaires et il est difficile de trouver un commentaire expressif pour chaque ligne.
  3. Lorsque vous créez un commentaire, essayez de répondre à la question « pourquoi » plutôt que « comment ».
  4. Évitez les raccourcis. Comme je l'ai dit plus haut, nous n'avons pas besoin d'explication pour le commentaire : le commentaire est l'explication.
  5. Vous pouvez utiliser des commentaires pour marquer les unités de mesure et la plage de valeurs acceptables.
  6. Placez les commentaires à proximité du code qu'ils décrivent.
Par conséquent, je voudrais quand même vous rappeler : les meilleurs commentaires sont l'absence de commentaire, et à sa place, un nom correct dans l'application. En règle générale, la plupart du temps, nous travaillerons déjà avec du code prêt à l'emploi, le maintiendrons et le développerons. C'est beaucoup plus pratique lorsque ce code est facile à lire et à comprendre, car un mauvais code gêne, met des bâtons dans les roues et la hâte est son fidèle compagnon. Et plus nous avons de mauvais code, plus les performances diminuent, nous devons donc le refactoriser de temps en temps. Mais si dès le début vous essayez d'écrire du code pour lequel les développeurs ultérieurs ne voudront pas vous trouver et vous tuer, vous devrez alors le refactoriser moins souvent. Mais cela sera toujours nécessaire, car les conditions et les exigences du produit changent constamment, complétées par l'ajout de connexions supplémentaires, et il n'y a pas d'échappatoire. Enfin, je vous laisse quelques liens intéressants pour vous familiariser avec ce sujet ici , ici et ici je suppose que c'est tout pour moi aujourd'hui, merci à tous ceux qui lisent)) Règles d'écriture de code : le pouvoir d'une dénomination correcte, les bons et les mauvais commentaires - 8
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION