JavaRush /Blogue Java /Random-PT /Regras do código: o poder da nomenclatura adequada, dos c...

Regras do código: o poder da nomenclatura adequada, dos comentários bons e ruins

Publicado no grupo Random-PT
Regras para escrever código: o poder da nomenclatura correta, comentários bons e ruins - 1 Quantas vezes você teve que entender o código de outra pessoa? Quando, em vez de algumas horas, você passa dias só para entender a lógica do que está acontecendo. O engraçado é que para quem escreveu esse código tudo é claro e muito transparente. E isso não é surpreendente: afinal, código perfeito ou ideal é um conceito muito vago, pois cada desenvolvedor tem sua visão de mundo e de código, respectivamente. Mais de uma vez me deparei com uma situação em que meu colega e eu analisamos o mesmo código e tínhamos opiniões diferentes sobre sua correção e limpeza. Regras para escrever código: o poder da nomenclatura correta, comentários bons e ruins - 2É um sentimento familiar, não é? No entanto, existem alguns pontos testados pelo tempo que devem ser respeitados, que no final farão o nosso favor, porque se você deixar seu código no estado em que gostaria de recebê-lo, o mundo ficaria um pouco mais feliz e limpo. Regras para escrever código: o poder da nomenclatura correta, comentários bons e ruins - 3Em nosso último artigo sobre as regras de escrita de código (ou melhor, um pequeno guia), tocamos um pouco nas recomendações para escrever o sistema como um todo e seus elementos como objetos, suas interfaces, classes, métodos e variáveis. Lá mencionei brevemente a nomenclatura correta de certos elementos. Hoje eu gostaria de falar exatamente sobre isso, pois nomes corretos facilitam muito a legibilidade do código. Encerraremos o tópico do código correto com a ajuda de reflexões e pequenos exemplos de comentários no código - isso é bom ou não. Então vamos começar.

Nomenclatura correta

Nomes corretos melhoram a legibilidade do código, economizando tempo de familiarização, pois é muito mais fácil usar um método quando o nome descreve aproximadamente sua funcionalidade. Como tudo no código consiste em nomes (variáveis, métodos, classes, objetos de arquivo, etc.), este ponto se torna muito importante ao criar um código correto e limpo. Com base no acima exposto, o nome deve transmitir o significado do porquê, por exemplo, de uma variável existir, o que ela faz e como é usada. Observarei repetidas vezes que o melhor comentário para descrever uma variável é seu nome correto. Regras para escrever código: o poder da nomenclatura correta, comentários bons e ruins - 4

Nomeando Interfaces

As interfaces normalmente usam nomes que começam com letra maiúscula e são escritos em camel case (CamelCase). Costumava ser uma boa prática, ao escrever uma interface, prefixá-la com um I para designá-la como uma interface (por exemplo, IUserService), mas isso é bastante feio e perturbador. Nesses casos, é melhor escrever sem ele (UserService) e adicionar -Impl (UserServiceImpl) à sua implementação. Bem, ou como último recurso, adicione o prefixo C (CUserService) à sua implementação.

Nomes de classe

Assim como as interfaces, os nomes são maiúsculos e usam o estilo camelo (CamelCase). Não importa que tipo de apocalipse esteja acontecendo, não importa quão rápidos sejam os prazos, mas nunca, lembre-se, o nome de uma aula nunca deve ser um verbo! Os nomes de classes e objetos devem ser substantivos e suas combinações (UserController, UserDetails, UserAccount e assim por diante). Você não deve fornecer o nome de cada classe com a abreviatura deste aplicativo, pois isso apenas adicionará complexidade desnecessária (por exemplo, temos um aplicativo de migração de dados do usuário e adicionaremos um UDM a cada classe - UDMUserDeatils, UDMUserAccount, UDMUserController ).

Nomes de métodos

Geralmente os nomes dos métodos começam com uma letra minúscula, mas também usam o estilo camel (CamelCase). Acima falamos sobre o fato de que nomes de classes nunca deveriam ser verbos. Aqui a situação é diametralmente oposta: os nomes dos métodos devem ser verbos ou suas combinações com verbos: findUserById, findAllUsers, createUser e assim por diante. Ao criar um método (bem como variáveis ​​e classes), para evitar confusão, use uma abordagem de nomenclatura. Por exemplo, para encontrar um usuário, o método pode ser escrito como getUserById ou findUserById. E mais uma coisa: não use humor nos nomes dos métodos, pois eles podem não entender a piada, bem como o que esse método faz.

Nomes de variáveis

Na maioria dos casos, os nomes das variáveis ​​começam com letra minúscula e também usam Camelcase, exceto nos casos em que a variável é uma constante global. Nesses casos, todas as letras do nome são escritas em maiúsculas e as palavras são separadas por um sublinhado - “_”. Ao nomear variáveis, você pode usar um contexto significativo por conveniência. Ou seja, quando existe uma variável como parte de algo maior - por exemplo, firstName, lastName, status - nesses casos você pode adicionar um prefixo indicando o objeto do qual esta variável faz parte. Por exemplo: userFirstName, userLastName, userStatus. Você também precisa evitar nomes semelhantes para variáveis ​​quando elas têm significados completamente diferentes. Antônimos comuns para variáveis:
  • começo/fim
  • primeiro último
  • bloqueado/desbloqueado
  • mínimo máximo
  • próximo/anterior
  • antigo/novo
  • aberto/fechado
  • visível/invisível
  • origem/destino
  • fonte de destino
  • cima baixo

Nomes curtos de variáveis

Quando temos variáveis ​​como x ou n ou algo parecido, não vemos imediatamente a intenção da pessoa que escreveu o código. Não é óbvio o que o método n faz: requer um pensamento mais cuidadoso (e isso leva tempo, tempo, tempo). Por exemplo, temos um campo - o id do usuário responsável, e em vez de algum nome como x ou apenas id, chamaremos essa variável de ResponsibleUserId, o que aumenta imediatamente a legibilidade e o significado. No entanto, nomes curtos como n têm seu lugar como alterações locais em métodos pequenos, onde o bloco de código com essa alteração é apenas algumas linhas de código e o nome do método descreve perfeitamente o que acontece lá. Um desenvolvedor, ao ver tal variável, entende sua importância secundária e escopo muito limitado. Como resultado, existe alguma dependência do comprimento do nome da variável: quanto maior for, mais global será a variável e vice-versa. Por exemplo, um método para encontrar o último usuário salvo por data:
public User findLastUser() {
   return findAllUsers().stream()
           .sorted((x, y) -> -x.getCreatedDate().compareTo(y.getCreatedDate()))
           .findFirst()
           .orElseThrow(() -> new ResourceNotFoundException("Any user doesn't exist "));
}
Aqui usamos nomes abreviados xey para definir a classificação do fluxo e esquecê-los.

Comprimento ideal

Vamos continuar com o tópico do comprimento do nome. O comprimento ideal do nome está em algum lugar entre o comprimento do nome MaximumNumberOfUsersInTheCurrentGroup e n. Ou seja, os muito curtos sofrem com a falta de significado, e os muito longos esticam o programa sem aumentar a legibilidade, e eles simplesmente têm preguiça de escrevê-los todas as vezes. Não levando em consideração o caso acima, para variáveis ​​com nome abreviado como n, você precisa manter o comprimento em aproximadamente 8 a 16 caracteres. Esta não é uma regra estrita: é mais uma diretriz.

Pequenas diferenças

Não posso ignorar diferenças sutis nos nomes, porque essa também é uma prática ruim, já que você pode simplesmente ficar confuso ou perder muito tempo percebendo pequenas diferenças nos nomes. Por exemplo, a diferença entre InvalidDataAccessApiUsageException e InvalidDataAccessResourceUsageException é difícil de detectar à primeira vista. Além disso, muitas vezes pode surgir desinformação ao usar L e O minúsculos, porque podem ser facilmente confundidos com 1 e 0: em algumas fontes a diferença é mais óbvia, em outras nem tanto.

Parte semântica

Precisamos colocar a parte semântica nos nomes, mas não exagerar nos sinônimos, já que, por exemplo, UserData e UserInfo na verdade têm o mesmo significado, e teremos que nos aprofundar um pouco mais no código para entender qual objeto específico precisamos . Evite palavras não informativas, por exemplo, firstNameString: por que precisamos da palavra string? Um nome pode ser um objeto do tipo data? Claro que não: portanto, simplesmente - firstName. Como exemplo, gostaria de mencionar variáveis ​​booleanas, por exemplo, flagDelete. A palavra bandeira não carrega nenhum significado semântico. Teria sido mais razoável chamá-lo de isDelete.

Desinformação

Também gostaria de dizer algumas palavras sobre nomenclatura incorreta. Digamos que temos o nome userActivityList e o objeto assim nomeado não é do tipo List, mas algum outro contêiner ou objeto personalizado para armazenamento. Isso pode confundir o programador médio: seria melhor chamá-lo de algo como userActivityGroup ou userActivities.

Procurar

Uma das desvantagens dos nomes curtos e simples é que eles são difíceis de encontrar em uma grande quantidade de código, pois o que seria mais fácil de encontrar: uma variável chamada nome ou NAME_FOR_DEFAULT_USER? Claro, a segunda opção. É necessário evitar palavras (letras) de ocorrência frequente nos nomes, pois isso só aumentará a quantidade de arquivos encontrados durante a busca, o que não é bom. Gostaríamos de lembrar que os programadores passam mais tempo lendo código do que escrevendo, portanto, esteja atento à nomenclatura dos elementos da sua aplicação. Mas e se você não conseguisse nomeá-lo com sucesso? E se o nome de um método não descrever bem sua funcionalidade? É aqui que entra em jogo, nosso próximo item são os comentários.

Comentários

Правила написания codeа: сила правильных именований, хорошие и плохие комментарии - 5Não há nada como um comentário relevante, mas nada atrapalha um módulo como comentários sem sentido, desatualizados ou enganosos. É uma faca de dois gumes, não é? Ainda assim, você não deve tratar os comentários como um bem inequívoco: antes, como um mal menor. Afinal, um comentário, em sua essência, é uma compensação por um pensamento expresso sem sucesso no código. Por exemplo, nós os usamos para transmitir de alguma forma a essência do método, caso ele seja muito confuso. Em tal situação, é melhor refatorar corretamente o código em vez de escrever notas descritivas. Quanto mais antigo o comentário, pior, porque o código tende a crescer e evoluir, mas o comentário pode permanecer o mesmo, e quanto mais longe ele vai, mais duvidosas ficam essas notas. Comentários imprecisos são muito piores do que nenhum comentário, porque confundem e enganam, dando falsas expectativas. E mesmo que tenhamos um código muito complicado, ainda vale a pena não comentá-lo, mas sim reescrevê-lo.

Tipos de comentários

  • comentários legais são comentários deixados no início de cada arquivo de código-fonte por motivos legais, como:

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

  • Comentários informativos são comentários que fornecem uma explicação do código (fornecendo informações adicionais ou a intenção de um determinado trecho de código.

    Como um exemplo:

    /*
    * Объединяет пользователя из бд и пришедшего для обновления
    * Когда в 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()
           );
           }

    Nesse caso, você pode dispensar comentários, pois o nome do método e seus argumentos, aliados à funcionalidade bastante transparente, se descrevem muito bem.

  • comentário de aviso - um comentário cujo objetivo é alertar outros desenvolvedores sobre as consequências indesejáveis ​​de alguma ação (por exemplo, por que o teste foi marcado como @Ignore):

    // Слишком долго отрабатывает
    // Не запускайте, если не располагаете избытком времени
    @Ignore
    @Test
    public void someIntegrationTest() {
           ……
           }
  • TODO - comentários que são notas para o futuro que precisarão ser feitas, mas que por algum motivo não podem ser feitas agora. Esta é uma boa prática, mas eles ainda precisam ser revisados ​​regularmente para remover os irrelevantes e evitar confusão.

    Примером послужит:

    //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);
           }

    Тут мы помечаем, что нужно добавить проверку юзера, который скачивает (id которого мы вытащим из security контекста) с тем, кто сохранил.

  • усorвающий комментарий — комментарий, подчеркивающий важность Howого-то обстоятельства, что на первый взгляд может показаться несущественным.

    Как пример, кусочек метода, заполняющий тестовую БД, некими скриптами:

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

  • javaDoc — комментарии, которые описывают API определенного функционала для общего пользования. Наверное, самые полезные комментарии, так How с documentированным API в разы легче работать, но они также могут устаревать, How и любые другие. Поэтому не забываем, что главный вклад в documentацию вносится не комментариями, а хорошим codeом.

    Пример вполне обычного метода обновления пользователя:

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

Плохие сценарии комментариев

Правила написания codeа: сила правильных именований, хорошие и плохие комментарии - 7
  • бормочущий комментарий — комментарии, которые обычно пишут на скорую руку, смысл которых понятен только разработчику, писавшего их, так How только он видит ту ситуацию с теми нюансами, на которые он и ссылается.

    Рассмотрим данный пример:

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

    Кто загружает эти настройки? Были ли они загружены ранее? Метод предназначен для перехвата исключений и вызова дефолтных настроек? Слишком много вопросов возникает, ответы на которые можно получить лишь углубившись в изучение других частей системы.

  • избыточный комментарий — комментарий, который не несёт смысловой нагрузки, так How и так понятно что происходит в заданном участке codeа (он читается не проще, чем code).

    Смотрим пример:

    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;
       }

    Какой смысл таких комментариев, если мы и так всё прекрасно видим

  • недостоверные комментарии — комментарии, не соответствующие истине и лишь вгоняющие в заблуждение (дезинформирующие). Как например:

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

    What в этом комменте не так? А то, что он немножко врёт нам, ведь соединение закрывается, если isNotUsing = false, но ниHow не наоборот, How нам вещает пометка.

  • обязательные комментарии — комментарии, которые считают обязательными (Javadoc), но кои по факту иногда бывают излишне нагромождающими, недостоверными и ненужными (нужно задуматься, а нужны ли здесь такие комментарии).

    Пример:

    /**
    *  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);

    Смогли бы вы понять, что делает метод без этих комментариев? Скорее всего да, поэтому комментарии в этом случае стают бессмысленными.

  • журнальные комментарии — комментарии, которые иногда добавляют в начало модуля, при каждом его редактировании (что-то вроде журнала вносимых изменений).

    /**
    *  Записи ведутся с 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  : Рефакторинг сервис слоя;
    */

    Когда-то этот проход был оправдан, но с появлением систем управления исходным codeом (например — Git), это стало лишним нагромождением и усложнением codeа.

  • комментарии ссылки на авторов — комментарии, преднаmeaningм которых является, указание человека, писавшего code, чтобы можно было связаться и обсудить, How что и зачем:

    * @author  Bender Benderovich

    Опять же, системы контроля версий прекрасно запоминают, кто и когда добавил данный code, и подобный подход излишен.

  • código comentado é o código que foi comentado por um motivo ou outro. Um dos piores hábitos, porque você comentou e esqueceu, e outros desenvolvedores simplesmente não têm coragem de excluí-lo (e se for algo valioso).

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

    Como resultado, acumula-se como lixo. Sob nenhuma circunstância tal código deve ser deixado. Se você realmente precisar, não se esqueça do sistema de controle de versão.

  • comentários não óbvios são comentários que descrevem algo de uma maneira desnecessariamente complexa.

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

    Um comentário deve explicar o código, não precisa de uma explicação em si. O que está acontecendo aqui? O que são “bytes de filtro”? O que +1 tem a ver com isso? Por que exatamente 300?

Se você decidir escrever comentários, aqui estão algumas dicas para usá-los:
  1. Use estilos que sejam fáceis de manter: manter estilos muito sofisticados e exóticos pode ser chato e demorado.
  2. Não use comentários no final das linhas que se refiram a linhas únicas: isso cria uma grande pilha de comentários e é difícil encontrar um comentário expressivo para cada linha.
  3. Ao criar um comentário, tente responder à pergunta “por que” em vez de “como”.
  4. Evite abreviações. Como disse acima, não precisamos de explicação para o comentário: o comentário é a explicação.
  5. Você pode usar comentários para marcar as unidades de medida e a faixa de valores aceitáveis.
  6. Coloque comentários próximos ao código que eles descrevem.
Por isso, ainda gostaria de lembrar: os melhores comentários são a ausência de comentário e, em vez dele, a nomenclatura adequada no aplicativo. Via de regra, na maioria das vezes já estaremos trabalhando com código pronto, mantendo-o e expandindo-o. É muito mais conveniente quando esse código é fácil de ler e entender, porque códigos ruins atrapalham, atrapalham e a pressa é sua fiel companheira. E quanto mais código ruim tivermos, mais o desempenho cai, por isso precisamos refatorar de vez em quando. Mas se desde o início você tentar escrever um código para o qual os desenvolvedores subsequentes não vão querer encontrá-lo e matá-lo, você precisará refatorá-lo com menos frequência. Mas ainda será necessário, uma vez que as condições e requisitos do produto estão em constante mudança, complementados pela adição de conexões adicionais, e não há como escapar disso. Por fim, deixarei alguns links interessantes para vocês se familiarizarem com esse assunto aqui , aqui e aqui , acho que é tudo para mim hoje, obrigado a todos que leram)) Правила написания codeа: сила правильных именований, хорошие и плохие комментарии - 8
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION