Главная страница
Навигация по странице:

  • Комментарии за закрывающей фигурной скобкой

  • Создание, анализ ирефакторинг


    Скачать 3.16 Mb.
    НазваниеСоздание, анализ ирефакторинг
    Дата29.09.2022
    Размер3.16 Mb.
    Формат файлаpdf
    Имя файлаChistyj_kod_-_Sozdanie_analiz_i_refaktoring_(2013).pdf
    ТипКнига
    #706087
    страница12 из 49
    1   ...   8   9   10   11   12   13   14   15   ...   49
    листинг 4 .3 .
    /**
    *
    * @param title Название диска
    * @param author Автор диска
    * @param tracks Количество дорожек на диске
    * @param durationInMinutes Продолжительность воспроизведения в минутах
    */
    public void addCD(String title, String author, int tracks, int durationInMinutes) {
    CD cd = new CD();
    cd.title = title;
    cd.author = author;
    cd.tracks = tracks;
    cd.duration = duration;
    cdList.add(cd);
    }
    журнальные комментарии
    Некоторые программисты добавляют комментарий в начало модуля при каждом его редактировании . Такие комментарии накапливаются, образуя своего рода журнал всех вносимых изменений . Я видел модули, в которых эти журнальные записи растягивались на десятки страниц .
    * Изменения (начиная с 11 октября 2001)
    * --------------------------
    * 11.10.2001 : Реорганизация класса и его перемещение в новый пакет
    * com.jrefinery.date (DG);
    * 05.11.2001 : Добавление метода getDescription(), устранение класса
    * NotableDate (DG);
    * 12.11.2001 : С устранением класса NotableDate IBD требует включения
    * метода setDescription() (DG); исправление ошибок
    * в методах getPreviousDayOfWeek(), getFollowingDayOfWeek()
    * и getNearestDayOfWeek() (DG);
    * 05.12.2001 : Исправление ошибки в классе SpreadsheetDate (DG);
    90

    Плохие комментарии
    91
    * 29.05.2002 : Перемещение констант месяцев в отдельный интерфейс
    * (MonthConstants) (DG);
    * 27.08.2002 : Исправление ошибки в методе addMonths() с подачи N???levka Petr
    (DG);
    * 03.10.2002 : Исправление ошибок по сообщениям Checkstyle (DG);
    * 13.03.2003 : Реализация Serializable (DG);
    * 29.05.2003 : Исправление ошибки в методе addMonths (DG);
    * 04.09.2003 : Реализация Comparable. Обновление isInRange javadocs (DG);
    * 05.01.2005 : Исправление ошибки в методе addYears() (1096282) (DG);
    Когда-то создание и сопровождение журнальных записей в начале каждого мо- дуля было оправдано . У нас еще не было систем управления исходным кодом, которые делали это за нас . В наши дни длинные журналы только загромождают и усложняют код . Их следует полностью удалить из ваших программ .
    шум
    Также в программах нередко встречаются комментарии, не содержащие ничего, кроме «шума» . Они лишь утверждают очевидное, не предоставляя никакой новой информации .
    /**
    * Конструктор по умолчанию.
    */
    protected AnnualDateRule() {
    }
    Да неужели? А как насчет этого:
    /** День месяца. */
    private int dayOfMonth;
    И наконец, апофеоз избыточности:
    /**
    * Возвращает день месяца.
    *
    * @return день месяца.
    */
    public int getDayOfMonth() {
    return dayOfMonth;
    }
    Эти комментарии настолько бесполезны, что мы учимся не обращать на них вни- мания . В процессе чтения кода наш взгляд просто скользит мимо них . Рано или поздно код вокруг таких комментариев изменяется, и они начинают лгать .
    Первый комментарий в листинге 4 .4 кажется уместным . Он объясняет, почему блок catch игнорируется . Но второй комментарий не несет полезной информации .
    Видимо, программист настолько вышел из себя при написании этих блоков try
    /
    catch в этой функции, что ему понадобилось «выпустить пар» .
    91

    92
    Глава 4 . Комментарии
    листинг 4 .4 . startSending private void startSending()
    {
    try
    {
    doSending();
    }
    catch(SocketException e)
    {
    // Нормально. Кто-то прервал запрос.
    }
    catch(Exception e)
    {
    try
    {
    response.add(ErrorResponder.makeExceptionString(e));
    response.closeAll();
    }
    catch(Exception e1)
    {
    // Ну хватит уже!
    }
    }
    }
    Вместо того чтобы давать выход чувствам в бесполезном комментарии, про- граммисту следовало понять, что раздражение можно было снять улучшением структуры кода . Ему стоило направить свою энергию на выделение последнего блока try
    /
    catch в отдельную функцию, как показано в листинге 4 .5 .
    листинг 4 .5 . startSending (переработанная версия)
    private void startSending()
    {
    try
    {
    doSending();
    }
    catch(SocketException e)
    {
    // Нормально. Кто-то прервал запрос.
    }
    catch(Exception e)
    {
    addExceptionAndCloseResponse(e);
    }
    }
    private void addExceptionAndCloseResponse(Exception e)
    {
    try
    92

    Плохие комментарии
    93
    {
    response.add(ErrorResponder.makeExceptionString(e));
    response.closeAll();
    }
    catch(Exception e1)
    {
    }
    }
    Искушение создать очередной «шумовой комментарий» следует заменить ре- шимостью очистить код . Вы сами увидите, что это сделает вашу работу более приятной и эффективной .
    Опасный шум
    Комментарии Javadoc тоже бывают «шумовыми» . Какую пользу приносят следу- ющие комментарии (из хорошо известной библиотеки, распространяемой с от- крытым кодом)? Ответ: никакой . Это избыточные шумовые комментарии, вы- званные неуместным желанием как-то документировать свои действия .
    /** Имя. */
    private String name;
    /** Версия. */
    private String version;
    /** Название лицензии. */
    private String licenceName;
    /** Версия. */
    private String info;
    Прочитайте эти комментарии повнимательнее . Заметили ошибку копирования/
    вставки? Если авторы не следят за ними в момент написания (или вставки), то как можно ожидать, что эти комментарии принесут пользу читателю?
    не используйте комментарии там, где можно
    использовать функцию или переменную
    Возьмем следующий фрагмент кода:
    // Зависит ли модуль из глобального списка от подсистемы,
    // частью которой является наш код?
    if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem()))
    Его можно было бы перефразировать без комментария в следующем виде:
    ArrayList moduleDependees = smodule.getDependSubsystems();
    String ourSubSystem = subSysMod.getSubSystem();
    if (moduleDependees.contains(ourSubSystem))
    Возможно (хотя и маловероятно), автор исходного кода сначала написал ком- ментарий, а затем — соответствующий ему код . Но после этого автор должен был переработать свой код, как это сделал я, чтобы комментарий можно было удалить .
    93

    94
    Глава 4 . Комментарии
    Позиционные маркеры
    Некоторые программисты любят отмечать определенные позиции в исходных файлах . Например, недавно я обнаружил в одной из просматриваемых программ следующую строку:
    // Действия //////////////////////////////////
    В отдельных случаях объединение функций под такими заголовками имеет смысл . Но в общем случае они составляют балласт, от которого следует изба- виться — особенно от назойливой серии косых черт в конце .
    Взгляните на дело под таким углом: заголовки привлекают внимание только в том случае, если они встречаются не слишком часто . Используйте их умеренно и только тогда, когда они приносят ощутимую пользу . При слишком частом упо- треблении заголовков читатель воспринимает их как фоновый шум и перестает обращать на них внимание .
    Комментарии за закрывающей фигурной скобкой
    Иногда программисты размещают специальные комментарии за закрывающи- ми фигурными скобками, как в листинге 4 .6 . Применение таких комментариев оправдано в длинных функциях с многоуровневой вложенностью, но они только загромождают компактные специализированные функции, которым мы отдает предпочтение . Итак, если у вас возникает желание прокомментировать закры- вающие фигурные скобки, лучше постарайтесь укоротить свои функции .
    листинг 4 .6 . wc.java public class wc {
    public static void main(String[] args) {
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    String line;
    int lineCount = 0;
    int charCount = 0;
    int wordCount = 0;
    try {
    while ((line = in.readLine()) != null) {
    lineCount++;
    charCount += line.length();
    String words[] = line.split("\\W");
    wordCount += words.length;
    } //
    while
    System.out.println("wordCount = " + wordCount);
    System.out.println("lineCount = " + lineCount);
    System.out.println("charCount = " + charCount);
    } //
    try
    catch (IOException e) {
    System.err.println("Error:" + e.getMessage());
    } //catch
    } //
    main
    }
    94

    Плохие комментарии
    95
    Ссылки на авторов
    /* Добавлено Риком */
    Системы контроля исходного кода отлично запоминают, кто и когда внес то или иное исправление . Нет необходимости загрязнять код подобными ссылками .
    Может показаться, что такие комментарии помогают другим определить, с кем следует обсуждать данный фрагмент кода . Однако в действительности эти ком- ментарии остаются в коде на долгие годы и со временем становятся все менее точными и актуальными .
    И снова лучшим источником подобной информации является система контроля исходного кода .
    Закомментированный код
    В программировании редко встречаются привычки более отвратительные, чем закрытие комментариями неиспользуемого кода . Никогда не делайте этого!
    InputStreamResponse response = new InputStreamResponse();
    response.setBody(formatter.getResultStream(), formatter.getByteCount());
    // InputStream resultsStream = formatter.getResultStream();
    // StreamReader reader = new StreamReader(resultsStream);
    // response.setContent(reader.read(formatter.getByteCount()));
    У других программистов, видящих закомментированный код, не хватает хра- брости удалить его . Они полагают, что код оставлен не зря и слишком важен для удаления . В итоге закомментированный код скапливается, словно осадок на дне бутылки плохого вина .
    Следующий код взят из общих модулей Apache:
    this.bytePos = writeBytes(pngIdBytes, 0);
    //
    hdrPos = bytePos;
    writeHeader();
    writeResolution();
    //
    dataPos = bytePos;
    if (writeImageData()) {
    writeEnd();
    this.pngBytes = resizeByteArray(this.pngBytes, this.maxPos);
    }
    else {
    this.pngBytes = null;
    }
    return this.pngBytes;
    Почему эти две строки кода закомментированы? Они важны? Их оставили как напоминание о будущих изменениях? Или это «хлам», который кто-то закоммен- тировал сто лет назад и не удосужился убрать из программы?
    В 60-е годы закомментированный код мог быть действительно полезен . Но с тех пор у нас давно появились хорошие системы контроля исходного кода . Эти систе- мы запоминают изменения в коде за нас . Нам уже не нужно закрывать их коммен- тариями . Просто удалите ненужный код . Он никуда не исчезнет . Честное слово .
    95

    96
    Глава 4 . Комментарии
    Комментарии hTmL
    Как видно из следующего фрагмента, HTML в комментариях к исходному коду выглядит отвратительно . Он затрудняет чтение комментариев именно там, где они должны легко читаться — в редакторе/IDE . Если комментарии должны извлекаться внешним инструментом (например, Javadoc) для отображения в веб- странице, то за украшение комментариев соответствующим кодом HTML должен отвечать этот инструмент, а не программист .
    /**
    * Задача для запуска тестов.
    * Задача запускает тесты fitnesse и публикует результаты.
    *
    *
    * Usage:
    * <taskdef name="execute-fitnesse-tests"
    * classname="fitnesse.ant.ExecuteFitnesseTestsTask"
    * classpathref="classpath" />
    * OR
    * <taskdef classpathref="classpath"
    * resource="tasks.properties" />
    *
    * <execute-fitnesse-tests
    * suitepage="FitNesse.SuiteAcceptanceTests"
    * fitnesseport="8082"
    * resultsdir="${results.dir}"
    * resultshtmlpage="fit-results.html"
    * classpathref="classpath" />
    *
    */
    нелокальная информация
    Если вы должны написать комментарий, проследите за тем, чтобы он описывал находящийся поблизости код . Не излагайте информацию системного уровня в контексте локального комментария . Примером служит приведенный ниже комментарий Javadoc . Не считая того факта, что комментарий ужасающе из- быточен, в него также включена информация о порте по умолчанию, притом что функция никоим образом не может управлять этим значением . И конечно, ничто не гарантирует, что комментарий будет изменен при изменении кода, в котором это значение определяется .
    /**
    * Порт, на котором будет работать fitnesse. По умолчанию 8082.
    *
    * @param fitnessePort
    */
    public void setFitnessePort(int fitnessePort)
    {
    this.fitnessePort = fitnessePort;
    }
    96

    Плохие комментарии
    97
    Слишком много информации
    Не включайте в комментарии интересные исторические дискуссии или опи- сания подробностей, не относящиеся к делу . Следующий комментарий был извлечен из модуля, который должен был проверять, что функция кодирует и декодирует данные в формате base64 . Читателю кода совершенно не нужна заумная информация, содержащаяся в этом комментарии, — вполне достаточно номера RFC .
    /*
    RFC 2045 - Multipurpose Internet Mail Extensions (MIME)
    Часть 1: Формат тел сообщений раздел 6.8. Кодирование данных Base64
    В процессе кодирования 24-разрядные группы входных битов представляются в виде выходных строк из 4 закодированных символов. Слева направо 24-разрядная входная группа образуется посредством конкатенации 38-разрядных входных групп.
    Далее эти 24 бита интерпретируются как 4 конкатенированных 6-разрядных группы,
    каждая из которых преобразуется в одну цифру алфавита base64. При кодировании потока битов в кодировке base64 предполагается, что битовый поток упорядочивается от старшего значащего бита. Иначе говоря, первым битом потока будет старший бит первого 8-битового байта, а восьмым - младший бит первого 8-битого байта и т. д.
    */
    неочевидные комментарии
    Связь между комментарием и кодом, который он описывает, должна быть оче- видной . Если уж вы берете на себя хлопоты, связанные с написанием коммента- рия, то по крайней мере читатель должен посмотреть на комментарий и на код и понять, о чем говорится в комментарии . Для примера возьмем следующий комментарий из общих модулей Apache:
    /*
    * Начать с массива, размер которого достаточен для хранения
    * всех пикселов (плюс байты фильтра), плюс еще 200 байт
    * для данных заголовка
    */
    this.pngBytes = new byte[((this.width + 1) * this.height * 3) + 200];
    Что такое «байты фильтра»? Они как-то связаны с +1? Или с *3? И с тем и с дру- гим? Один пиксел соответствует одному байту? И почему 200? Цель коммента- рия — объяснить код, который не объясняет сам себя . Плохо, когда сам коммен- тарий нуждается в объяснениях .
    Заголовки функций
    Короткие функции не нуждаются в долгих описаниях . Хорошо выбранное имя компактной функции, которая выполняет одну операцию, обычно лучше заго- ловка с комментарием .
    97

    98
    Глава 4 . Комментарии
    Заголовки Javadoc во внутреннем коде
    При всей полезности комментариев Javadoc для API общего пользования не применяйте их в коде, не предназначенном для общего потребления . Генериро- вание страниц Javadoc для внутренних классов и функций системы обычно не приносит реальной пользы, а формализм комментариев Javadoc только отвлекает читателя .
    Пример
    Модуль в листинге 4 .7 был написан для первого учебного курса «XP Immersion» .
    Предполагалось, что он является примером плохого кодирования и стиля ком- ментирования . Кент Бек переработал этот код в куда более приятную форму перед несколькими десятками увлеченных слушателей . Позднее я приспособил этот пример для своей книги «Agile Software Development, Principles, Patterns, and
    Practices» и статьи в журнале «Software Development» . Любопытно, что в то время многие из нас считали этот модуль «хорошо документированным» . Теперь мы видим, что он представляет собой ералаш . Посмотрим, сколько разных ошибок комментирования вам удастся найти .
    листинг 4 .7 . GeneratePrimes.java
    /**
    * Класс генерирует простые числа в диапазоне до максимального значения,
    * заданного пользователем, по алгоритму "Решета Эратосфена".
    *
    * Эратосфен Киренский, 276 год до н.э., Ливия -- * 194 год до н.э., Александрия.
    * Первый ученый, вычисливший длину земного меридиана. Известен своими работами
    * о календарях с високосным годом, заведовал Александрийской библиотекой.
    *
    * Алгоритм весьма прост. Берем массив целых чисел, начиная с 2, и вычеркиваем
    * из него все числа, кратные 2. Находим следующее невычеркнутое число
    * и вычеркиваем все его кратные. Повторяем до тех пор, пока не дойдем
    * до квадратного корня верхней границы диапазона.
    *
    * @author Альфонс
    * @version 13 февраля 2002 u
    */
    import java.util.*;
    public class GeneratePrimes
    {
    /**
    * @param maxValue - верхняя граница диапазона.
    */
    public static int[] generatePrimes(int maxValue)
    {
    if (maxValue >= 2) // Единственно допустимый случай
    98

    Плохие комментарии
    99
    {
    // Объявления int s = maxValue + 1; // Размер массива boolean[] f = new boolean[s];
    int i;
    // Инициализировать массив значениями true.
    for (i = 0; i < s; i++)
    f[i] = true;
    // Удалить числа, заведомо не являющиеся простыми.
    f[0] = f[1] = false;
    // Отсев int j;
    for (i = 2; i < Math.sqrt(s) + 1; i++)
    {
    if (f[i]) // Если элемент i не вычеркнут, вычеркнуть кратные ему.
    {
    for (j = 2 * i; j < s; j += i)
    f[j] = false; // Кратные числа не являются простыми.
    }
    }
    // Сколько простых чисел осталось?
    int count = 0;
    for (i = 0; i < s; i++)
    {
    if (f[i])
    count++; // Приращение счетчика
    }
    int[] primes = new int[count];
    // Переместить простые числа в результат for (i = 0, j = 0; i < s; i++)
    {
    if (f[i]) // Если простое primes[j++] = i;
    }
    return primes; // Вернуть простые числа
    }
    else // maxValue < 2
    return new int[0]; // Вернуть пустой массив при недопустимых входных данных.
    }
    }
    В листинге 4 .8 приведена переработанная версия того же модуля . Обратите вни- мание: применение комментариев стало намного более ограниченным . Во всем модуле осталось всего два комментария пояснительного характера .
    99

    1   ...   8   9   10   11   12   13   14   15   ...   49


    написать администратору сайта