Роберт Мартин - Чистый код. Создание, анализ и рефакторинг
- Название:Чистый код. Создание, анализ и рефакторинг
- Автор:
- Жанр:
- Издательство:Питер
- Год:2019
- Город:СПб.
- ISBN:978-5-4461-0960-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Роберт Мартин - Чистый код. Создание, анализ и рефакторинг краткое содержание
Эта книга посвящена хорошему программированию. Она полна реальных примеров кода. Мы будем рассматривать код с различных направлений: сверху вниз, снизу вверх и даже изнутри. Прочитав книгу, вы узнаете много нового о коде. Более того, вы научитесь отличать хороший код от плохого. Вы узнаете, как писать хороший код и как преобразовать плохой код в хороший.
Книга состоит из трех частей. В первой части излагаются принципы, паттерны и приемы написания чистого кода; приводится большой объем примеров кода. Вторая часть состоит из практических сценариев нарастающей сложности. Каждый сценарий представляет собой упражнение по чистке кода или преобразованию проблемного кода в код с меньшим количеством проблем. Третья часть книги – концентрированное выражение ее сути. Она состоит из одной главы с перечнем эвристических правил и «запахов кода», собранных во время анализа. Эта часть представляет собой базу знаний, описывающую наш путь мышления в процессе чтения, написания и чистки кода.
Примечание верстальщика:
Чистый код. Создание, анализ и рефакторинг - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
}
}
Что означает комментарий в блоке catch? Очевидно, он что-то означал для автора, но для читателя этот смысл не доходит. Видимо, если мы получаем IOException, это означает, что файл свойств отсутствует; в этом случае должны загружаться все настройки по умолчанию. Но кто загружает эти настройки? Были ли они загружены перед вызовом loadProperties.load? Или вызов loadProperties.load перехватывает исключение, загружает настройки по умолчанию, а затем передает исключение нам, чтобы мы могли его проигнорировать? Или loadProperties.load загружает настройки по умолчанию до того, как вы попытались загрузить файл? Автор пытался успокоить себя относительно того факта, что он оставил блок catch пустым? Или — и это самая пугающая возможность — автор хотел напомнить себе, что позднее нужно вернуться и написать код загрузки настроек по умолчанию?
Чтобы разобраться в происходящем, нам остается только изучить код других частей системы. Любой комментарий, смысл которого приходится искать в других модулях, не несет полезной информации и не стоит битов, затраченных на его написание.
Избыточные комментарии
В листинге 4.1 приведена простая функция с совершенно лишним заголовочным комментарием. Вероятно, чтение комментария займет больше времени, чем чтение самого кода.
// Вспомогательный метод; возвращает управление, когда значение this.closed истинно.
// Инициирует исключение при достижении тайм-аута.
public synchronized void waitForClose(final long timeoutMillis)
throws Exception
{
if(!closed)
{
wait(timeoutMillis);
if(!closed)
throw new Exception("MockResponseSender could not be closed");
}
}
Какой цели достигает этот комментарий? Конечно, он несет не больше информации, чем программный код. Он не объясняет код, не предоставляет обоснований и не раскрывает намерений. Он читается не проще, чем сам код. Более того, комментарий уступает коду в точности и навязывает читателю эту неточность взамен истинного понимания. Он напоминает жуликоватого торговца подержанными машинами, уверяющего, что вам незачем заглядывать под капот.
А теперь рассмотрим легион бесполезных, избыточных комментариев Javadoc из листинга 4.2, позаимствованных из Tomcat. Эти комментарии только загромождают код и скрывают его смысл. Никакой пользы для документирования от них нет. Что еще хуже, я привел только несколько начальных комментариев — в этом модуле их намного больше.
public abstract class ContainerBase
implements Container, Lifecycle, Pipeline,
MBeanRegistration, Serializable {
/**
* Задержка процессора для этого компонента.
*/
protected int backgroundProcessorDelay = -1;
/**
* Поддержка событий жизненного цикла для этого компонента.
*/
protected LifecycleSupport lifecycle =
new LifecycleSupport(this);
/**
* Слушатели контейнерных событий для этого контейнера.
*/
protected ArrayList listeners = new ArrayList();
/**
* Реализация загрузчика, связанная с контейнером.
*/
protected Loader loader = null;
/**
* Реализация журнального компонента, связанная с контейнером.
*/
protected Log logger = null;
/**
* Имя журнального компонента.
*/
protected String logName = null;
/**
* Реализация менеджера, связанная с контейнером.
*/
protected Manager manager = null;
/**
* Кластер, связанный с контейнером.
*/
protected Cluster cluster = null;
/**
* Удобочитаемое имя контейнера.
*/
protected String name = null;
/**
* Родительский контейнер, по отношению к которому
* данный контейнер является дочерним.
*/
protected Container parent = null;
/**
* Загрузчик родительского класса, задаваемый при назначении загрузчика.
*/
protected ClassLoader parentClassLoader = null;
/**
* Объект Pipeline, связанный с данным контейнером.
*/
protected Pipeline pipeline = new StandardPipeline(this);
/**
* Объект Realm, связанный с контейнером.
*/
protected Realm realm = null;
/**
* Объект ресурсов DirContext, связанный с контейнером
*/
protected DirContext resources = null;
Недостоверные комментарии
Иногда с самыми лучшими намерениями программист делает в комментариях заявления, неточные и не соответствующие истине. Еще раз взгляните на совершенно лишний, но при этом слегка вводящий в заблуждение комментарий из листинга 4.1.
А вы нашли, в чем этот комментарий обманывает читателя? Метод не возвращает управление, когда значение this.closed становится истинным. Он возвращает управление, если значение this.closed истинно; в противном случае метод ожидает истечения тайм-аута, а затем инициирует исключение, если значение this.closed так и не стало истинным.
Эта крошечная дезинформация в комментарии, который читается хуже, чем сам код, может заставить другого программиста вызвать функцию в предположении, что она вернет управление сразу же, как только значение this.closed станет истинным. После этого бедный программист будет долго отлаживать программу, пытаясь понять, почему его код выполняется так медленно.
Обязательные комментарии
Правила, говорящие, что каждая функция должна иметь комментарий Javadoc или что каждая переменная должна быть помечена комментарием, — обычная глупость. Такие комментарии только загромождают код, распространяют недостоверную информацию и вызывают общую путаницу и дезориентацию.
Например, требование обязательного комментария Javadoc для каждой функции приводит к появлению монстров вроде листинга 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)
Интервал:
Закладка: