Предыдущая глава: Функции

Наша цель использования комментариев заключается в том, что мы не можем достаточно выразить себя с помощью кода. Но комментарии всегда неудачны. Потому что мы не знаем, как выразить себя без них.

Итак, если вы оказались в ситуации, когда вам нужно написать комментарий, вернитесь к коду и попытайтесь выразить себя в коде.

Код меняется и развивается. Куски его перемещаются отсюда туда. Но комментарии не всегда могут следовать за ними. И комментарии отделяются от кода, который они описывают. Например:

MockRequest request;
private final String HTTP_DATE_REGEXP = 
 "[SMTWF][a-z]{2}\\,\\s[0-9]{2}\\s[JFMASOND][a-z]{2}\\s"+
 "[0-9]{4}\\s[0-9]{2}\\:[0-9]{2}\\:[0-9]{2}\\sGMT";
private Response response;
private FitNesseContext context;
private FileResponder responder;
private Locale saveLocale;
// Example: "Tue, 02 Apr 2003 22:18:49 GMT"

Обычно комментарий описывает константу HTTP_DATE_REGEXP. Но добавлены другие переменные экземпляра. И комментарий не обновился.

Одной из наиболее распространенных причин написания комментариев является плохой код. Мы знаем, что код беспорядок. И мы хотим добавить комментарии, чтобы описать себя. Но это не очень хороший способ. Четкий и выразительный код с небольшим количеством комментариев лучше, чем сложный код с большим количеством комментариев.

Конечно, кода всегда недостаточно для объяснения самих себя. Но есть способ. Посмотрите на эти два кода ниже, что бы вы хотели увидеть?:

// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) && 
  (employee.age > 65)) 

or

if (employee.isEligibleForFullBenefits())

Хорошие комментарии

Некоторые комментарии необходимы и полезны.

Например, заявления об авторских правах и авторстве необходимы и разумны для размещения в комментарии в начале каждого исходного файла:

// Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the GNU General Public License version 2 or later.

Иногда мы добавляем комментарии //TODO для заметок:

//TODO-MdM these are not needed
// We expect this to go away when we do the checkout model
protected VersionInfo makeVersion() throws Exception {
    return null;
}

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

Если вы пишете общедоступный API, вам следует написать для него хорошую документацию по Java. Но Javadocs может вводить в заблуждение и быть нечестным, как и любой другой вид комментариев.

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

Если вы решили написать комментарий, то потратьте свое время и напишите лучший комментарий. Посмотрите на этот пример, автор не уделил особого внимания своему бормотанию:

public void loadProperties() {
    try {
        String propertiesPath = propertiesLocation + "/" + PROPERTIES_FILE;
        FileInputStream propertiesStream = new FileInputStream(propertiesPath);
        loadedProperties.load(propertiesStream);
    } catch (IOException e) {
        // No properties files means all defaults are loaded
    }
}

Что означает этот комментарий? Вероятно, если мы получим IOException, то файлов свойств не было и загружаются все значения по умолчанию. Но как ? Были ли они загружены до вызова loadProperties.load? Или loadProperties.load перехватил исключение, загрузил значения по умолчанию, а затем передал исключение, чтобы мы его игнорировали? Или loadProperties.load загрузил все значения по умолчанию, прежде чем пытаться загрузить файл? Или — это самый страшный сценарий — он написал этот комментарий, а он вернулся и загрузил настройки по умолчанию.

См. следующий пример кода, чтение — пустая трата времени:

// Utility method that returns when this.closed is true. Throws an exception
// if the timeout is reached.
public synchronized void waitForClose(final long timeoutMillis)
        throws Exception {
    if (!closed) {
        wait(timeoutMillis);
        if (!closed)
            throw new Exception("MockResponseSender could not be closed");
    }
}

Код достаточно информативен. Комментарии не требуются.

Как насчет следующих комментариев Javadoc? Они ничего не объясняют.

/** The name. */
private String name;
/** The version. */
private String version;
/** The licenceName. */
private String licenceName;
/** The version. */
private String info;

Смотри внимательно. Вы распознаете ошибку копирования-вставки? Если авторы не обращают внимания на то, когда пишутся (или вставляются) комментарии, почему читатели должны получать от них выгоду?

Посмотрите на следующий код. Возможно, автор сначала написал комментарий, а затем код:

// does the module from the global list <mod> depend on the
// subsystem we are part of?
if (smodule.getDependSubsystems().contains(subSysMod.getSubSystem()))

Автор должен был провести рефакторинг кода, чтобы комментарий можно было удалить.

ArrayList moduleDependees = smodule.getDependSubsystems();
String ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.contains(ourSubSystem))

Иногда программисты пишут комментарии к закрывающим фигурным скобкам. Это может иметь смысл, если ваш код слишком длинный. Но вместо этого попытайтесь сократить свою функцию.

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
}

Не делайте закомментированный код.

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()));

Когда вы видите этот закомментированный код, что вы думаете? Есть ли у вас мужество, чтобы удалить его? Вы подумаете, что это важно для удаления. В старые времена код с комментариями был полезен. Но теперь у нас есть хорошие системы управления исходным кодом. Эти системы запомнят код для нас. Просто удалите его.

«Не комментируйте плохой код — перепишите его»
Брайан В. Керниган