JavaRush /Blog Java /Random-ES /Reglas del código: el poder de nombrar correctamente, bue...

Reglas del código: el poder de nombrar correctamente, buenos y malos comentarios

Publicado en el grupo Random-ES
Reglas para escribir código: el poder de nombrar correctamente, buenos y malos comentarios - 1 ¿Con qué frecuencia has tenido que entender el código de otra persona? Cuando, en lugar de un par de horas, dedicas días sólo a comprender la lógica de lo que está pasando. Lo curioso es que para la persona que escribió este código todo es claro y muy transparente. Y esto no es sorprendente: después de todo, el código perfecto o ideal es un concepto muy vago, porque cada desarrollador tiene su propia visión del mundo y del código, respectivamente. Más de una vez me encontré con una situación en la que mi colega y yo miramos el mismo código y teníamos opiniones diferentes sobre su corrección y limpieza. Reglas para escribir código: el poder de nombrar correctamente, buenos y malos comentarios - 2Es un sentimiento familiar, ¿no? Sin embargo, hay algunos puntos probados a lo largo del tiempo que se deben respetar y que, en última instancia, nos beneficiarán, porque si deja su código en el estado en el que le gustaría recibirlo, el mundo sería un poco más feliz y limpiador. Reglas para escribir código: el poder de nombrar correctamente, buenos y malos comentarios - 3En nuestro último artículo sobre las reglas para escribir código (o mejor dicho, una pequeña guía), abordamos un poco las recomendaciones para escribir el sistema en su conjunto y sus elementos como objetos, sus interfaces, clases, métodos y variables. Allí mencioné brevemente la denominación correcta de ciertos elementos. Hoy me gustaría hablar exactamente de esto, porque los nombres correctos facilitan mucho la legibilidad del código. Cerraremos el tema del código correcto con la ayuda de reflexiones y pequeños ejemplos de comentarios en el código: ¿es bueno o no tan bueno? Entonces empecemos.

Denominación correcta

Los nombres correctos mejoran la legibilidad del código y, en consecuencia, ahorran tiempo de familiarización, porque es mucho más fácil utilizar un método cuando el nombre describe aproximadamente su funcionalidad. Dado que todo en el código consta de nombres (variables, métodos, clases, objetos de archivo, etc.), este punto se vuelve muy importante al crear código limpio y correcto. Con base en lo anterior, el nombre debe transmitir el significado de por qué, por ejemplo, existe una variable, qué hace y cómo se usa. Señalaré una y otra vez que el mejor comentario para describir una variable es su nombre correcto. Reglas para escribir código: el poder de nombrar correctamente, buenos y malos comentarios - 4

Nombrar interfaces

Las interfaces suelen utilizar nombres que comienzan con una letra mayúscula y están escritos en mayúsculas y minúsculas (CamelCase). Solía ​​ser una buena práctica al escribir una interfaz anteponerle una I para designarla como una interfaz (por ejemplo, IUserService), pero esto es bastante feo y distrae. En tales casos, es mejor escribir sin él (UserService) y agregar -Impl (UserServiceImpl) a su implementación. Bueno, o como último recurso, agregue el prefijo C (CUserService) a su implementación.

Nombres de clase

Al igual que las interfaces, los nombres están en mayúscula y usan el estilo camel (CamelCase). No importa qué tipo de apocalipsis esté sucediendo, no importa qué tan rápidos sean los plazos, pero nunca, recuerda, ¡el nombre de una clase nunca debe ser un verbo! Los nombres de clases y objetos deben ser sustantivos y sus combinaciones (UserController, UserDetails, UserAccount, etc.). No debe proporcionar el nombre de cada clase con la abreviatura de esta aplicación, ya que esto solo agregará complejidad innecesaria (por ejemplo, tenemos una aplicación de migración de datos de usuario y agregaremos un UDM a cada clase: UDMUserDeatils, UDMUserAccount, UDMUserController). ).

Nombres de métodos

Generalmente los nombres de los métodos comienzan con una letra minúscula, pero también usan el estilo camel (CamelCase). Anteriormente hablamos sobre el hecho de que los nombres de las clases nunca deberían ser verbos. Aquí la situación es diametralmente opuesta: los nombres de los métodos deben ser verbos o sus combinaciones con verbos: findUserById, findAllUsers, createUser, etc. Al crear un método (así como variables y clases), para evitar confusiones, utilice un enfoque de nomenclatura. Por ejemplo, para buscar un usuario, el método se puede escribir como getUserById o findUserById. Y una cosa más: no utilices humor en los nombres de los métodos, porque es posible que no entiendan el chiste ni lo que hace este método.

Nombres de variables

En la mayoría de los casos, los nombres de las variables comienzan con una letra minúscula y también usan Camelcase, excepto en los casos en que la variable es una constante global. En tales casos, todas las letras del nombre se escriben en mayúsculas y las palabras están separadas por un guión bajo: "_". Al nombrar variables, puede utilizar un contexto significativo por conveniencia. En otras palabras, cuando hay una variable como parte de algo más grande (por ejemplo, nombre, apellido, estado), en tales casos puede agregar un prefijo que indique el objeto del que forma parte esta variable. Por ejemplo: nombre de usuario, apellido de usuario, estado de usuario. También es necesario evitar nombres similares para variables cuando tienen significados completamente diferentes. Antónimos comunes de variables:
  • comienzo/fin
  • primero último
  • bloqueado/desbloqueado
  • mínimo máximo
  • siguiente anterior
  • viejo nuevo
  • abierto/cerrado
  • visible invisible
  • origen Destino
  • origen Destino
  • arriba abajo

Nombres de variables cortos

Cuando tenemos variables como x o n o algo así, no vemos inmediatamente la intención de la persona que escribió el código. No es obvio qué hace el método n: requiere un pensamiento más reflexivo (y eso es tiempo, tiempo, tiempo). Por ejemplo, tenemos un campo: la identificación del usuario responsable, y en lugar de algún nombre como x o simplemente id, llamaremos a esta variable responsableUserId, lo que aumenta inmediatamente la legibilidad y el significado. Sin embargo, los nombres cortos como n tienen su lugar como cambios locales en métodos pequeños, donde el bloque de código con ese cambio es solo un par de líneas de código, y el nombre del método describe perfectamente lo que sucede allí. Un desarrollador, al ver tal variable, comprende su importancia secundaria y su alcance muy limitado. Como resultado, existe cierta dependencia de la longitud del nombre de la variable: cuanto más largo es, más global es la variable y viceversa. Como ejemplo, un método para encontrar el último usuario guardado por fecha:
public User findLastUser() {
   return findAllUsers().stream()
           .sorted((x, y) -> -x.getCreatedDate().compareTo(y.getCreatedDate()))
           .findFirst()
           .orElseThrow(() -> new ResourceNotFoundException("Any user doesn't exist "));
}
Aquí usamos nombres cortos xey para configurar la clasificación de la transmisión y nos olvidamos de ellos.

Longitud óptima

Continuamos con el tema de la longitud del nombre. La longitud óptima del nombre está entre la longitud máxima del nombre NumberOfUsersInTheCurrentGroup y n. Es decir, los demasiado cortos carecen de significado, los demasiado largos estiran el programa sin agregar legibilidad y simplemente son demasiado vagos para escribirlos cada vez. Sin tener en cuenta el caso anterior, para variables con un nombre corto como n, es necesario mantener la longitud entre 8 y 16 caracteres aproximadamente. Esta no es una regla estricta: más bien una pauta.

Pequeñas diferencias

No puedo ignorar las diferencias sutiles en los nombres, porque esto también es una mala práctica, ya que simplemente puedes confundirte o pasar mucho tiempo extra notando diferencias menores en los nombres. Por ejemplo, la diferencia entre InvalidDataAccessApiUsageException e InvalidDataAccessResourceUsageException es difícil de detectar de un vistazo. Además, a menudo puede surgir información errónea al utilizar L y O pequeñas, porque pueden confundirse fácilmente con 1 y 0: en algunas fuentes la diferencia es más obvia, en otras menos.

parte semántica

Necesitamos poner la parte semántica en los nombres, pero no exagerar con los sinónimos, ya que, por ejemplo, UserData y UserInfo en realidad tienen el mismo significado, y tendremos que profundizar un poco más en el código para comprender qué objeto específico necesitamos. . Evite palabras que no sean informativas, por ejemplo, firstNameString: ¿por qué necesitamos la palabra cadena? ¿Puede un nombre ser un objeto de tipo fecha? Por supuesto que no: por lo tanto, simplemente - nombre. Como ejemplo, me gustaría mencionar las variables booleanas, por ejemplo flagDelete. La palabra bandera no tiene ningún significado semántico. Sería más razonable llamarlo isDelete.

Desinformación

También me gustaría decir algunas palabras sobre los nombres incorrectos. Digamos que tenemos el nombre userActivityList y el objeto nombrado así no es del tipo Lista, sino algún otro contenedor u objeto personalizado para almacenamiento. Esto puede confundir al programador promedio: sería mejor llamarlo algo así como userActivityGroup o userActivities.

Buscar

Una de las desventajas de los nombres cortos y simples es que son difíciles de encontrar en una gran cantidad de código, porque ¿qué sería más fácil de encontrar: una variable llamada nombre o NAME_FOR_DEFAULT_USER? Por supuesto, la segunda opción. Es necesario evitar palabras (letras) que aparecen con frecuencia en los nombres, ya que esto sólo aumentará la cantidad de archivos encontrados durante la búsqueda, lo cual no es bueno. Nos gustaría recordarle que los programadores dedican más tiempo a leer código que a escribirlo, así que tenga cuidado con la denominación de los elementos de su aplicación. ¿Pero qué pasa si no lograste nombrarlo con éxito? ¿Qué pasa si el nombre de un método no describe bien su funcionalidad? Aquí es donde entra en juego, nuestro siguiente elemento son los comentarios.

Comentarios

Reglas para escribir código: el poder de nombrar correctamente, buenos y malos comentarios - 5No hay nada como un comentario relevante, pero nada satura un módulo como comentarios sin sentido, desactualizados o engañosos. Es un arma de doble filo, ¿no? Aún así, no debes tratar los comentarios como un bien inequívoco, sino más bien como un mal menor. Después de todo, un comentario, en esencia, es una compensación por un pensamiento expresado sin éxito en el código. Por ejemplo, los usamos para transmitir de alguna manera la esencia del método si resulta demasiado confuso. En tal situación, es mejor refactorizar correctamente el código en lugar de escribir notas descriptivas. Cuanto más antiguo es el comentario, peor, porque el código tiende a crecer y evolucionar, pero el comentario puede seguir siendo el mismo, y cuanto más avanza, más dudosas se vuelven estas notas. Los comentarios inexactos son mucho peores que ningún comentario, porque confunden y engañan, generando falsas expectativas. E incluso si tenemos un código muy complicado, vale la pena no comentarlo, sino reescribirlo.

tipos de comentarios

  • Los comentarios legales son comentarios que se dejan al principio de cada archivo de código fuente por motivos legales, como por ejemplo:

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

  • Los comentarios informativos son comentarios que proporcionan una explicación del código (proporcionando información adicional o la intención de un fragmento de código determinado).

    Como ejemplo:

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

    En este caso, puedes prescindir de los comentarios, ya que el nombre del método y sus argumentos, junto con la funcionalidad muy transparente, se describen bastante bien.

  • comentario de advertencia : un comentario cuyo propósito es advertir a otros desarrolladores sobre las consecuencias no deseadas de alguna acción (por ejemplo, por qué la prueba se marcó como @Ignore):

    // Слишком долго отрабатывает
    // Не запускайте, если не располагаете избытком времени
    @Ignore
    @Test
    public void someIntegrationTest() {
           ……
           }
  • TODO : comentarios que son notas para el futuro que será necesario hacer, pero que por alguna razón no se pueden hacer ahora. Esta es una buena práctica, pero aun así es necesario revisarlos periódicamente para eliminar los irrelevantes y evitar el desorden.

    Un ejemplo sería:

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

    Aquí notamos que necesitamos agregar una verificación del usuario que está descargando (cuya identificación sacaremos del contexto de seguridad) con el que guardó.

  • comentario de refuerzo : un comentario que enfatiza la importancia de alguna circunstancia, que a primera vista puede parecer insignificante.

    Como ejemplo, una parte de un método que llena una base de datos de prueba con algunos scripts:

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

  • javaDoc : comentarios que describen la API de determinadas funciones para uso general. Probablemente los comentarios más útiles, ya que es mucho más fácil trabajar con una API documentada, pero también pueden quedar obsoletas, como cualquier otra. Por tanto, no olvides que la principal aportación a la documentación no son los comentarios, sino un buen código.

    Un ejemplo de un método de actualización de usuario completamente normal:

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

Guiones de malos comentarios

Reglas para escribir código: el poder de nombrar correctamente, buenos y malos comentarios - 7
  • comentario murmurado : comentarios que generalmente se escriben apresuradamente, cuyo significado es claro solo para el desarrollador que los escribió, ya que solo él ve la situación con los matices a los que se refiere.

    Considere este ejemplo:

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

    ¿Quién carga estas configuraciones? ¿Se han descargado antes? ¿El método está destinado a interceptar excepciones y llamar a la configuración predeterminada? Surgen demasiadas preguntas cuyas respuestas sólo pueden obtenerse profundizando en el estudio de otras partes del sistema.

  • Un comentario redundante es un comentario que no tiene ninguna carga semántica, ya que ya está claro lo que está sucediendo en una sección determinada del código (no es más fácil de leer que el código).

    Veamos un ejemplo:

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

    ¿De qué sirven esos comentarios si ya vemos todo perfectamente?

  • Comentarios falsos : comentarios que no corresponden a la verdad y solo engañan (desinforman). Como:

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

    ¿Qué hay de malo en este comentario? Y que nos miente un poco, porque la conexión se cierra si isNotUsing = false, pero no al revés, como nos dice la marca.

  • comentarios obligatorios : comentarios que se consideran obligatorios (Javadoc), pero que, de hecho, a veces están innecesariamente desordenados, poco confiables e innecesarios (debe pensar si tales comentarios son necesarios aquí).

    Ejemplo:

    /**
    *  Creación пользователя по переданным параметрам
    * @param firstName Nombre созданного пользователя
    * @param middleName среднее Nombre созданного пользователя
    * @param lastName фамoя созданного пользователя
    * @param age возраст созданного пользователя
    * @param address DIRECCIÓNс созданного пользователя
    * @return пользователь который был создан
    */
    User createNewUser(String firstName, String middleName, String lastName, String age, String address);

    ¿Serías capaz de entender qué hace el método sin estos comentarios? Lo más probable es que sí, por lo que los comentarios en este caso pierden sentido.

  • Los comentarios del diario son comentarios que a veces se agregan al comienzo de un módulo cada vez que se edita (algo así como un registro de los cambios realizados).

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

    Hubo un tiempo en que este pasaje estaba justificado, pero con la llegada de los sistemas de gestión de código fuente (por ejemplo, Git), se convirtió en un desorden y una complicación innecesarias del código.

  • enlaces de comentarios a autores: comentarios cuyo propósito es indicar la persona que escribió el código, para que pueda contactar y discutir cómo, qué y por qué:

    * @author  Bender Benderovich

    Nuevamente, los sistemas de control de versiones recuerdan perfectamente quién agregó este código y cuándo, y este enfoque es innecesario.

  • El código comentado es código que ha sido comentado por una razón u otra. Uno de los peores hábitos, porque lo comentaste y lo olvidaste, y otros desarrolladores simplemente no tienen el coraje de eliminarlo (¿y si es algo valioso?).

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

    Como resultado, se acumula como basura. Bajo ninguna circunstancia se debe dejar dicho código. Si realmente lo necesitas, no te olvides del sistema de control de versiones.

  • Los comentarios no obvios son comentarios que describen algo de una manera innecesariamente compleja.

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

    Un comentario debe explicar el código, no necesitar una explicación en sí. ¿Que hay aquí? ¿Qué son los “bytes de filtro”? ¿Qué tiene que ver +1 con esto? ¿Por qué exactamente 300?

Si decides escribir comentarios, aquí tienes un par de consejos para utilizarlos:
  1. Utilice estilos que sean fáciles de mantener: mantener estilos que sean demasiado elegantes y exóticos puede resultar molesto y llevar mucho tiempo.
  2. No utilice comentarios al final de líneas que se refieran a líneas individuales: esto crea una gran pila de comentarios y es difícil encontrar un comentario expresivo para cada línea.
  3. Al crear un comentario, intente responder la pregunta "por qué" en lugar de "cómo".
  4. Evite las abreviaturas. Como dije anteriormente, no necesitamos una explicación para el comentario: el comentario es la explicación.
  5. Puede utilizar comentarios para marcar las unidades de medida y el rango de valores aceptables.
  6. Coloque comentarios cerca del código que describen.
Por lo tanto, todavía me gustaría recordarles: los mejores comentarios son la ausencia de un comentario y, en su lugar, el nombre correcto en la aplicación. Como regla general, la mayor parte del tiempo ya estaremos trabajando con código listo para usar, manteniéndolo y ampliándolo. Es mucho más conveniente cuando este código es fácil de leer y comprender, porque el código incorrecto se interpone en el camino, obstaculiza las ruedas y la prisa es su fiel compañera. Y cuanto más código incorrecto tengamos, más caerá el rendimiento, por lo que debemos refactorizar de vez en cuando. Pero si desde el principio intentas escribir código para el cual los desarrolladores posteriores no querrán encontrarte y matarte, entonces necesitarás refactorizarlo con menos frecuencia. Pero seguirá siendo necesario, ya que las condiciones y requisitos del producto cambian constantemente, y se complementan con la adición de conexiones adicionales, y no hay forma de evitarlo. Finalmente, les dejaré un par de enlaces interesantes para que se familiaricen con este tema aquí , aquí y aquí Supongo que eso es todo para mí hoy, gracias a todos los que leyeron)) Reglas para escribir código: el poder de nombrar correctamente, buenos y malos comentarios - 8
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION