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.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
Nã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);
Плохие сценарии комментариев
-
бормочущий комментарий — комментарии, которые обычно пишут на скорую руку, смысл которых понятен только разработчику, писавшего их, так 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?
- Use estilos que sejam fáceis de manter: manter estilos muito sofisticados e exóticos pode ser chato e demorado.
- 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.
- Ao criar um comentário, tente responder à pergunta “por que” em vez de “como”.
- Evite abreviações. Como disse acima, não precisamos de explicação para o comentário: o comentário é a explicação.
- Você pode usar comentários para marcar as unidades de medida e a faixa de valores aceitáveis.
- Coloque comentários próximos ao código que eles descrevem.
GO TO FULL VERSION