JavaRush /Java Blog /Random-IT /Regole del codice: il potere della denominazione corretta...

Regole del codice: il potere della denominazione corretta, dei commenti positivi e negativi

Pubblicato nel gruppo Random-IT
Regole per scrivere codice: il potere della denominazione corretta, commenti positivi e negativi - 1 Quante volte hai dovuto comprendere il codice di qualcun altro? Quando, invece di un paio d'ore, passi giorni solo per capire la logica di ciò che sta accadendo. La cosa divertente è che per chi ha scritto questo codice tutto è chiaro e molto trasparente. E questo non sorprende: dopotutto, codice perfetto o ideale è un concetto molto vago, perché ogni sviluppatore ha rispettivamente la propria visione del mondo e del codice. Più di una volta mi sono imbattuto in una situazione in cui io e il mio collega guardavamo lo stesso codice e avevamo opinioni diverse sulla sua correttezza e pulizia. Regole per scrivere codice: il potere della denominazione corretta, commenti positivi e negativi - 2È una sensazione familiare, vero? Tuttavia, ci sono alcuni punti consolidati che dovrebbero essere rispettati e che alla fine andranno a nostro vantaggio, perché se lasciassi il tuo codice nello stato in cui vorresti riceverlo, il mondo sarebbe un po' più felice e più pulito. Regole per scrivere codice: il potere della denominazione corretta, commenti positivi e negativi - 3Nel nostro ultimo articolo sulle regole per scrivere codice (o meglio, una piccola guida), abbiamo accennato ai consigli per scrivere il sistema nel suo insieme e i suoi elementi come oggetti, loro interfacce, classi, metodi e variabili. Lì ho accennato brevemente alla corretta denominazione di alcuni elementi. Oggi vorrei parlare proprio di questo, perché i nomi corretti facilitano molto la leggibilità del codice. Chiudiamo l'argomento del codice corretto con l'aiuto di riflessioni e piccoli esempi di commenti nel codice: è buono o non così buono. Quindi iniziamo.

Denominazione corretta

I nomi corretti migliorano la leggibilità del codice, risparmiando di conseguenza tempo nella familiarizzazione, perché è molto più semplice utilizzare un metodo quando il nome ne descrive approssimativamente la funzionalità. Poiché tutto nel codice è costituito da nomi (variabili, metodi, classi, oggetti file, ecc.), questo punto diventa molto importante quando si crea codice corretto e pulito. Sulla base di quanto sopra, il nome dovrebbe trasmettere il significato, ad esempio, del perché esiste una variabile, cosa fa e come viene utilizzata. Noterò ancora e ancora che il miglior commento per descrivere una variabile è il suo nome corretto. Regole per scrivere codice: il potere della denominazione corretta, commenti positivi e negativi - 4

Denominazione delle interfacce

Le interfacce in genere utilizzano nomi che iniziano con una lettera maiuscola e sono scritti in maiuscolo (CamelCase). Era buona pratica quando si scriveva un'interfaccia prefissarla con una I per designarla come interfaccia (ad esempio IUserService), ma questo è piuttosto brutto e distrae. In questi casi, è meglio scrivere senza di esso (UserService) e aggiungere -Impl (UserServiceImpl) alla sua implementazione. Bene, o come ultima risorsa, aggiungi il prefisso C (CUserService) alla sua implementazione.

Nomi delle classi

Proprio come le interfacce, i nomi sono in maiuscolo e utilizzano lo stile cammello (CamelCase). Non importa che tipo di apocalisse sta accadendo, non importa quanto siano veloci le scadenze, ma mai, ricorda, il nome di una classe non dovrebbe mai essere un verbo! I nomi delle classi e degli oggetti devono essere nomi e relative combinazioni (UserController, UserDetails, UserAccount e così via). Non dovresti fornire il nome di ciascuna classe con l'abbreviazione di questa applicazione, poiché ciò aggiungerebbe solo complessità non necessaria (ad esempio, abbiamo un'applicazione di migrazione dei dati utente e aggiungeremo un UDM a ciascuna classe: UDMUserDeatils, UDMUserAccount, UDMUserController ).

Nomi dei metodi

Di solito i nomi dei metodi iniziano con una lettera minuscola, ma usano anche lo stile cammello (CamelCase). Sopra abbiamo parlato del fatto che i nomi delle classi non dovrebbero mai essere verbi. Qui la situazione è diametralmente opposta: i nomi dei metodi devono essere verbi o loro combinazioni con verbi: findUserById, findAllUsers, createUser e così via. Quando si crea un metodo (così come variabili e classi), per evitare confusione, utilizzare un approccio di denominazione. Ad esempio, per trovare un utente, il metodo può essere scritto come getUserById o findUserById. E ancora una cosa: non usare l'umorismo nei nomi dei metodi, perché potrebbero non capire lo scherzo, né cosa fa questo metodo.

Nomi variabili

Nella maggior parte dei casi, i nomi delle variabili iniziano con una lettera minuscola e utilizzano anche Camelcase, tranne nei casi in cui la variabile è una costante globale. In questi casi, tutte le lettere del nome sono scritte in maiuscolo e le parole sono separate da un carattere di sottolineatura - "_". Quando si denominano le variabili, è possibile utilizzare un contesto significativo per comodità. In altre parole, quando c'è una variabile come parte di qualcosa di più grande - ad esempio firstName, lastName, status - in questi casi è possibile aggiungere un prefisso che indica l'oggetto di cui questa variabile fa parte. Ad esempio: userFirstName, userLastName, userStatus. È inoltre necessario evitare nomi simili per le variabili quando hanno significati completamente diversi. Contrari comuni per variabili:
  • inizio/fine
  • primo ultimo
  • bloccato/sbloccato
  • minimo Massimo
  • successivo/precedente
  • vecchio nuovo
  • aperto/chiuso
  • visibile/invisibile
  • fonte/obiettivo
  • cerca la destinazione
  • sottosopra

Nomi di variabili brevi

Quando abbiamo variabili come x o n o qualcosa del genere, non vediamo immediatamente l'intenzione della persona che ha scritto il codice. Non è ovvio cosa faccia il metodo n: richiede una riflessione più ponderata (e questo è tempo, tempo, tempo). Ad esempio, abbiamo un campo: l'ID dell'utente responsabile, e invece di un nome come x o semplicemente id, chiameremo questa variabile responsabileUserId, che aumenta immediatamente la leggibilità e la significatività. Tuttavia, i nomi brevi come n hanno il loro posto come modifiche locali ai piccoli metodi, dove il blocco di codice con quella modifica è solo un paio di righe di codice e il nome del metodo descrive perfettamente cosa succede lì. Uno sviluppatore, vedendo una variabile del genere, ne comprende l'importanza secondaria e la portata molto limitata. Di conseguenza, esiste una certa dipendenza dalla lunghezza del nome della variabile: più lungo è, più globale è la variabile e viceversa. Ad esempio, un metodo per trovare l'ultimo utente salvato per data:
public User findLastUser() {
   return findAllUsers().stream()
           .sorted((x, y) -> -x.getCreatedDate().compareTo(y.getCreatedDate()))
           .findFirst()
           .orElseThrow(() -> new ResourceNotFoundException("Any user doesn't exist "));
}
Qui usiamo i nomi brevi xey per impostare l'ordinamento del flusso e ce ne dimentichiamo.

Lunghezza ottimale

Continuiamo l'argomento della lunghezza del nome. La lunghezza ottimale del nome è compresa tra la lunghezza del nome MaximumNumberOfUsersInTheCurrentGroup e n. Cioè, quelli troppo brevi soffrono di mancanza di significato, e quelli troppo lunghi allungano il programma senza aggiungere leggibilità, e sono semplicemente troppo pigri per scriverli ogni volta. Non tenendo conto del caso precedente, per le variabili con un nome breve come n, è necessario mantenere la lunghezza a circa 8 -16 caratteri. Questa non è una regola ferrea: più che altro una linea guida.

Piccole differenze

Non posso ignorare le sottili differenze nei nomi, perché anche questa è una cattiva pratica, poiché potresti semplicemente confonderti o passare molto tempo extra a notare piccole differenze nei nomi. Ad esempio, la differenza tra InvalidDataAccessApiUsageException e InvalidDataAccessResourceUsageException è difficile da individuare a colpo d'occhio. Inoltre, spesso può verificarsi disinformazione quando si utilizzano L e O minuscole, perché possono essere facilmente confuse con 1 e 0: in alcuni font la differenza è più evidente, in altri meno.

Parte semantica

Dobbiamo inserire la parte semantica nei nomi, ma senza esagerare con i sinonimi, poiché, ad esempio, UserData e UserInfo hanno effettivamente lo stesso significato, e dovremo scavare un po' più a fondo nel codice per capire di quale oggetto specifico abbiamo bisogno . Evita parole non informative, ad esempio firstNameString: perché abbiamo bisogno della parola string? Un nome può essere un oggetto di tipo data? Naturalmente no: quindi, semplicemente - firstName. Ad esempio, vorrei menzionare le variabili booleane, ad esempio flagDelete. La parola bandiera non ha alcun significato semantico. Sarebbe stato più ragionevole chiamarlo isDelete.

Disinformazione

Vorrei anche spendere alcune parole sulla denominazione errata. Diciamo che abbiamo il nome userActivityList e che l'oggetto così denominato non è del tipo List, ma qualche altro contenitore o oggetto personalizzato per l'archiviazione. Questo può confondere il programmatore medio: sarebbe meglio chiamarlo qualcosa come userActivityGroup o userActivities.

Ricerca

Uno degli svantaggi dei nomi brevi e semplici è che sono difficili da trovare in una grande quantità di codice, perché cosa sarebbe più facile da trovare: una variabile chiamata nome o NAME_FOR_DEFAULT_USER? Naturalmente, la seconda opzione. È necessario evitare parole (lettere) ricorrenti nei nomi, poiché ciò non farebbe altro che aumentare il numero di file trovati durante la ricerca, il che non va bene. Ci teniamo a ricordarti che i programmatori passano più tempo a leggere il codice che a scriverlo, quindi fai attenzione ai nomi degli elementi della tua applicazione. Ma cosa succede se non riesci a dargli un nome con successo? Cosa succede se il nome di un metodo non descrive bene la sua funzionalità? È qui che entra in gioco, il nostro prossimo punto sono i commenti.

Commenti

Regole per scrivere codice: il potere della denominazione corretta, commenti positivi e negativi - 5Non c'è niente come un commento rilevante, ma niente ingombra un modulo come commenti senza significato, obsoleti o fuorvianti. È un'arma a doppio taglio, non è vero? Tuttavia, non dovresti considerare i commenti come un bene inequivocabile: piuttosto, come un male minore. Dopotutto, un commento, nella sua essenza, è un risarcimento per un pensiero espresso senza successo nel codice. Ad esempio, li usiamo per trasmettere in qualche modo l'essenza del metodo se risulta essere troppo confuso. In una situazione del genere, è meglio rifattorizzare correttamente il codice piuttosto che scrivere note descrittive. Più il commento è vecchio, peggio è, perché il codice tende a crescere ed evolversi, ma il commento può rimanere lo stesso, e più si va avanti, più queste note diventano dubbie. I commenti imprecisi sono molto peggio di nessun commento, perché confondono e ingannano, dando false aspettative. E anche se abbiamo un codice molto complicato, vale comunque la pena non commentarlo, ma riscriverlo.

Tipi di commenti

  • i commenti legali sono commenti lasciati all'inizio di ciascun file di codice sorgente per motivi legali, come ad esempio:

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

  • I commenti informativi sono commenti che forniscono una spiegazione del codice (fornendo informazioni aggiuntive o l'intento di una determinata parte di codice.

    Come esempio:

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

    In questo caso si può fare a meno dei commenti, poiché il nome del metodo e i suoi argomenti, insieme alla funzionalità molto trasparente, si descrivono abbastanza bene.

  • commento di avviso - un commento il cui scopo è avvisare gli altri sviluppatori sulle conseguenze indesiderate di alcune azioni (ad esempio, perché il test è stato contrassegnato come @Ignore):

    // Слишком долго отрабатывает
    // Не запускайте, если не располагаете избытком времени
    @Ignore
    @Test
    public void someIntegrationTest() {
           ……
           }
  • TODO - commenti che sono appunti per il futuro che dovranno essere fatti, ma per qualche motivo non possono essere fatti ora. Questa è una buona pratica, ma è comunque necessario rivederli regolarmente per rimuovere quelli irrilevanti ed evitare confusione.

    Un esempio potrebbe essere:

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

    Qui notiamo che dobbiamo aggiungere un controllo dell'utente che sta scaricando (il cui ID estrarremo dal contesto di sicurezza) con quello che ha salvato.

  • commento di rinforzo - un commento che sottolinea l'importanza di alcune circostanze, che a prima vista possono sembrare insignificanti.

    Ad esempio, una parte di un metodo che riempie un database di test con alcuni script:

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

  • javaDoc : commenti che descrivono l'API di determinate funzionalità per uso generale. Probabilmente i commenti più utili, poiché è molto più facile lavorare con un'API documentata, ma possono anche diventare obsolete, come tutte le altre. Pertanto, non dimenticare che il contributo principale alla documentazione non sono i commenti, ma un buon codice.

    Un esempio di un metodo di aggiornamento utente del tutto normale:

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

Script di commenti errati

Regole per scrivere codice: il potere della denominazione corretta, commenti positivi e negativi - 7
  • commento borbottante - commenti che di solito vengono scritti in fretta, il cui significato è chiaro solo allo sviluppatore che li ha scritti, poiché solo lui vede la situazione con le sfumature a cui si riferisce.

    Considera questo esempio:

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

    Chi carica queste impostazioni? Sono stati scaricati prima? Il metodo è destinato a intercettare le eccezioni e richiamare le impostazioni predefinite? Sorgono troppe domande, le cui risposte possono essere ottenute solo approfondendo lo studio di altre parti del sistema.

  • un commento ridondante è un commento che non porta alcun carico semantico, poiché è già chiaro cosa sta succedendo in una determinata sezione di codice (non è più facile da leggere del codice).

    Diamo un'occhiata ad un esempio:

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

    Che senso hanno tali commenti se vediamo già tutto perfettamente

  • commenti falsi - commenti che non corrispondono alla verità e sono solo fuorvianti (disinformazione). Ad esempio:

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

    Cosa c'è di sbagliato in questo commento? E il fatto che ci sta mentendo un po', perché la connessione è chiusa se isNotUsing = false, ma non viceversa, come ci dice mark.

  • commenti obbligatori - commenti considerati obbligatori (Javadoc), ma che in realtà a volte sono inutilmente confusi, inaffidabili e non necessari (è necessario pensare se tali commenti siano necessari qui).

    Esempio:

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

    Saresti in grado di capire cosa fa il metodo senza questi commenti? Molto probabilmente sì, quindi i commenti in questo caso diventano privi di significato.

  • i commenti del journal sono commenti che a volte vengono aggiunti all'inizio di un modulo ogni volta che viene modificato (qualcosa come un registro delle modifiche apportate).

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

    Un tempo questo passaggio era giustificato, ma con l'avvento dei sistemi di gestione del codice sorgente (ad esempio Git), questo è diventato un inutile disordine e complicazione del codice.

  • commenti link agli autori - commenti il ​​cui scopo è indicare la persona che ha scritto il codice, in modo da poter contattare e discutere come, cosa e perché:

    * @author  Bender Benderovich

    Ancora una volta, i sistemi di controllo della versione ricordano perfettamente chi ha aggiunto questo codice e quando, e questo approccio non è necessario.

  • il codice commentato è il codice che è stato commentato per un motivo o per l'altro. Una delle peggiori abitudini, perché l'hai commentata e dimenticata, e altri sviluppatori semplicemente non hanno il coraggio di eliminarla (e se fosse qualcosa di prezioso).

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

    Di conseguenza, si accumula come spazzatura. In nessun caso tale codice dovrà essere lasciato. Se ne hai davvero bisogno, non dimenticare il sistema di controllo della versione.

  • i commenti non ovvi sono commenti che descrivono qualcosa in modo inutilmente complesso.

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

    Un commento dovrebbe spiegare il codice, non necessitare di una spiegazione stessa. Cosa c'è qui? Cosa sono i “byte filtro”? Cosa c'entra +1 con questo? Perché esattamente 300?

Se decidi di scrivere commenti, ecco un paio di suggerimenti su come utilizzarli:
  1. Usa stili facili da mantenere: mantenere stili troppo fantasiosi ed esotici può essere fastidioso e richiedere molto tempo.
  2. Non utilizzare commenti alla fine delle righe che si riferiscono a singole righe: questo crea una grande pila di commenti ed è difficile trovare un commento espressivo per ogni riga.
  3. Quando crei un commento, prova a rispondere alla domanda “perché” anziché “come”.
  4. Evita le scorciatoie. Come ho detto sopra, non abbiamo bisogno di una spiegazione per il commento: il commento è la spiegazione.
  5. È possibile utilizzare i commenti per contrassegnare le unità di misura e l'intervallo di valori accettabili.
  6. Inserisci i commenti vicino al codice che descrivono.
Di conseguenza, vorrei comunque ricordarvi: i migliori commenti sono l'assenza di un commento e, al suo posto, la corretta denominazione nell'applicazione. Di norma, la maggior parte delle volte lavoreremo già con codice già pronto, mantenendolo ed espandendolo. È molto più conveniente quando questo codice è facile da leggere e capire, perché il codice cattivo si intromette, mette i bastoni tra le ruote e la fretta è la sua fedele compagna. E più codice errato abbiamo, più cali di prestazioni, quindi dobbiamo eseguire il refactoring di tanto in tanto. Ma se fin dall'inizio provi a scrivere codice per il quale gli sviluppatori successivi non vorranno trovarti e ucciderti, dovrai rifattorizzarlo meno spesso. Ma sarà comunque necessario, poiché le condizioni e i requisiti del prodotto cambiano costantemente, integrati dall'aggiunta di ulteriori connessioni, e non c'è scampo da questo. Infine, lascerò un paio di link interessanti per farti conoscere questo argomento qui , qui e qui immagino che sia tutto per me oggi, grazie a tutti quelli che hanno letto)) Regole per scrivere codice: il potere della denominazione corretta, commenti positivi e negativi - 8
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION