Что такое чистый код?
Мне нравится, когда мой код элегантен и эффективен. Логика должна быть простой, чтобы было трудно скрывать ошибки, зависимости должны быть минимальными для облегчения обслуживания, обработка ошибок должна выполняться в соответствии с четко сформулированной стратегией, а производительность должна быть близкой к оптимальной, чтобы не соблазнять людей запутывать код беспринципными оптимизациями. Чистый код хорошо справляется с одной задачей.
Бьерн Страуструп, изобретатель C++ и автор книги "Язык программирования C++".
Код чистый, если его легко понять всем в команде. С понятностью приходит читабельность, изменчивость, расширяемость и ремонтопригодность. Все, что необходимо для поддержания проекта в течение длительного времени без накопления большого количества технического долга.
Ниже приведены несколько советов по написанию чистого кода.
И. Используйте осмысленные имена
Имя переменной, функции или класса должно отвечать на все важные вопросы. Он должен рассказать вам, почему он существует, что он делает и как он используется. Если имя требует комментария, то имя не раскрывает своего намерения.
int a; // work day per week
Имя a ничего не раскрывает. Не вызывает ощущения рабочий день в неделю. Мы должны выбрать имя, которое указывает, что измеряется, и единицу измерения:
int workDayPerWeek; int dayOfTheWeek;
Кроме того, используйте произносимые имена и выдуманные слова вместо правильных английских терминов.
Сравнивать
class DtaCR { private String fn; private String ln; private Date co ; /* ... */ };
To
class Customer { private String firstName; private String lastName; private Date createdOn ; /* ... */ };
Вы можете знать, какой класс легко понять.
II. Функция должна быть маленькой и делать только одну вещь
Первое правило функций состоит в том, что они должны быть маленькими. Второе правило функций состоит в том, что они должны быть меньше этого размера. Строки не должны быть длиннее 150 символов. Функции не должны состоять из 100 строк. Функции вряд ли когда-либо должны быть длиной в 20 строк.
Сравнивать
HtmlUtil.java (рефакторинг)
public static String renderPageWithSetupsAndTeardowns (PageData pageData, boolean isSuite ) throws Exception { boolean isTestPage = pageData.hasAttribute("Test"); if (isTestPage) { WikiPage testPage = pageData.getWikiPage(); StringBuffer newPageContent = new StringBuffer(); includeSetupPages(testPage, newPageContent, isSuite); newPageContent.append(pageData.getContent()); includeTeardownPages(testPage, newPageContent, isSuite); pageData.setContent(newPageContent.toString()); } return pageData.getHtml(); }
To
public static String renderPageWithSetupsAndTeardowns( PageData pageData, boolean isSuite) throws Exception { if (isTestPage(pageData)) includeSetupAndTeardownPages(pageData, isSuite); return pageData.getHtml(); }
Должно быть совершенно ясно, что первая функция делает больше, чем одну вещь. Среди прочего, это создание буферов, страниц настройки, создание нового содержимого страницы, включая настройки и удаление страниц, а также генерация HTML. С другой стороны, вторая функция делает одну простую вещь. Это включает в себя настройки и разборки на тестовых страницах. Функции должны делать одну вещь. Они должны делать это хорошо.
III. Объект и структура данных
Есть причина, по которой мы держим наши переменные в секрете. Мы не хотим, чтобы кто-то еще зависел от них. Мы хотим сохранить свободу изменять их тип или реализацию по прихоти или импульсу.
Сравнивать
public class Point { public double x; public double y; }
To
public interface Point { double getX(); double getY(); void setCartesian(double x, double y); double getR(); double getTheta(); void setPolar(double r, double theta); }
Прелесть листинга второго класса заключается в том, что вы никак не можете сказать, в каких координатах реализована реализация: в прямоугольных или в полярных. Может быть ни то, ни другое! И все же интерфейс безошибочно представляет собой структуру данных. Но он представляет собой нечто большее, чем просто структуру данных. Методы применяют политику доступа. Вы можете прочитать отдельные координаты независимо, но вы должны установить координаты вместе как атомарную операцию.
С другой стороны, первый класс очень четко реализован в прямоугольных координатах и заставляет нас независимо манипулировать этими координатами. Это раскрывает реализацию. В самом деле, реализация была бы раскрыта, даже если бы переменные были частными, а мы использовали геттеры и сеттеры одной переменной. Скрыть реализацию — это не просто поместить слой функций между переменными. Сокрытие реализации связано с абстракциями! Класс не просто выталкивает свои переменные через геттеры и сеттеры. Скорее он предоставляет абстрактные интерфейсы, которые позволяют пользователям манипулировать сущностью данных, не зная их реализации.
Объекты раскрывают поведение и скрывают данные. Это упрощает добавление новых типов объектов без изменения существующего поведения. Это также затрудняет добавление новых вариантов поведения к существующим объектам. Структуры данных раскрывают данные и не имеют существенного поведения. Это упрощает добавление новых поведений к существующим структурам данных, но затрудняет добавление новых структур данных к существующим функциям.
Библиография
Чистый код: руководство по гибкому программному обеспечению — Роберт Сесил Мартин