Giter VIP home page Giter VIP logo

clean-code's Introduction

Краткий, вольный пересказ книги чистый код

Глава 1. Что такое чистый код?

Глава 2. Содержательные имена.

Глава 3. Функции.

Глава 4. Коммнтарии.

Глава 5. Форматирование.

Глава 6. Объекты и структуры данных.

Глава 7. Обработка ошибок.

Глава 8. Границы.

Глава 9. Модульные тесты.

Глава 1. Что такое чистый код?

Код никогда не исчезет, потому что код представляет подробности тербований!

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

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

Уметь отличать чистый код от грязного != уметь писать чистый код.

Что такое "чистый код"?:

  1. логика прямолинейна, каждая функция делает то, что вы ожидали
  2. зависимости минимальны и явно определены, чтобы упростить сопровождение
  3. читается, как хорошо написанная проза
  4. используются содержательные имена
  5. покрыт тестами и проходит все эти тесты
  6. не содержит дубликатов
  7. содержит минимальное кол-во сущностей: классов, методов, функций и т.д.

При написании кода пользуйтесь правилом бойскаутов - "оставляй место стоянки чище, чем оно было до твоего прихода". (Чистка не обязательно должна быть глобальной, можно присвоить более понятное имя переменной или разбить слишком большую функцию и т.д.)

Ничто не обладает абсолютной истиной, в том числе все советы описанные в этой книге

Глава 2. Содержательные имена.

Имена должны передавать намерения программиста

Имя переменной, ф-ии или класса должно отвечать на вопросы: почему эта переменная (и т.д.) существует, что она делает и как используется.

public List<int[]> getItem() {
  List<int[]> list1 = new ArrayList<int[]>();
  for (int[] x : theList)
    if (x[0] == 4)
      list1.add(x);
  return list1;
}

Какие данные храняться в theList? Чем так важен элемент с нулевым индексом? Что такое 4? Как будет использоваться возвращаемый список? Чтобы отвитить, не хватает контекста. Допустим, это игра "Сапер". Стоит написать более осмысленные имена переменных, избавится от магических чисел и описать массив int. В результате получим:

public List<Cell> getFlaggedCells() {
  List<Cell> flaggedCells = new ArrayList<Cell>();
  for (Cell cell : gameBoard)
    if (cell[0] == 4)
      flaggedCells.add(cell);
  return flaggedCells;
}

Избегайте дезинформации

  • Не обозначайте группу учетных записей accountList, если только она действительно не храниться в списке (лучше подойдут accountGroup, bunchOfAccounts или просто accounts).
  • Остерегайтесь малозаметных различий в именах.

Используйте осмысленные различия

Допустим, есть класс Product. Создав другой класс ProductInfo или ProductData, вы создаете разные имена, которые по сути обозначают одно и тоже. Нужно записывать различающиеся имена так, чтобы было понятно, какой смысл заложен в этих различиях. Слово variable не должно встречаться в именах переменных, а table не должно встречаться в именах таблиц.

Используйте удобнопроизносимые имена

Имена должны нормально произноситься!

Неудачный выбор:

private Date genymdhms;
private Date modymdhms;

Так лучше:

private Date generationTimestamp;
private Date modificationTimestamp;

Используйте удобные для поиска имена

Однобуквенные имена могут использоваться ТОЛЬКО для локальных переменных в коротких методах. Длинна имени должна соответствовать размеру его области видимости. Если переменная или константа может использоваться в нескольких местах кодового блока, важно присвоить ей имя удобное для поиска (спойлер: в ней будет больше одной или пары букв).

Венгерская запись

Это запись при которой в первая буква в имени переменной означала код типа. Так было в досторические имена, сейчас все это не нужно, потому что компиляторы, редакторы и языки стали более продвинутыми.

Интерфейсы и реализации

Например, вы строите абстрактную фабрику для создания геометрических фигур. Фабрика это интерфейс, который реализуется конкретным классом. Как их назвать? IShapeFactory и ShapeFactory? Автор считает, что лучше без префикса, потому что это устарело и передает лишнюю информацию. Пользователям не нужно знать, что они имеют дело с интерфейсом, им достаточно знать, что это ShapeFactory. И если есть необходимось закодировать в имени либо интерфейс либо реализацию, то лучше выбрать реализацию.

Имена классов

Имена классов и объектов - это существительные и их комбинации: Customer, WikiPage, Account. Лучше не использовать такие слова, как Manager, Processor, Data или Info. Имя класса не должно быть глаголом.

Имена методов

Имена методов - глаголы и глагольные словосочетания: postPayment, deletePage, save. К методам чтения/записи добавляется префикс set, get, is. При перезагрузке конструкторов используются статические методы-фабрики с именами, описывающими аргументы. Например, запись Complex fulcrumPoint = Complex.FormRealNumber(23.0); обычно лучше записи Complex fulcrumPoint = Complex(23.0);.

Избегайте остроумия

Никаких тут LOL в именах переменных. А abort() лучше, чем eatMyShorts() :).

Выберите одно слово для каждой концепции

Например, существование в разных классах эквивалентных методов get, retrieve, get неизбежно создаст путаницу. Как запомнить к какому классу относится то или иное имя метода? Аналогично, использование терминов controller, manager, driver в одной кодовой базе вызывает путаницу. Например, чем DeviceManager отличается от ProtocolController? Почему не использовать одинаковые термины? Такие имена создают впечатление, что два объекта обладают разными типами и относятся к разным классам.

Воздержитесь от каламбуров

Старайтесь не использовать одно слово в двух смыслах. Например, прграмма содержит много классов с методами add, которые складывают два значения. Вы пишете новый класс с медотом, помещающим один элемент в коллекцию. Стоит ли дать этому методу имя add? На первый взгляд это последовательно, но метод содержит другую семантику, поэтому лучше присвоить имя insert или append.

Используйте имена из пространства решения

Т.к. код будут читать программисты, то можно использовать термины из области информатики, названия алгоритмов, паттернов, мат. термины. Например JobQueue.

Добавьте содержательный контекст

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

Не добавляйте избыточный контекст

Короткие имена лучше длинных, если их смысл понятен читателю. Имена accountAddress и customerAddress подходят для экземпляров класса Address, но для класса такой выбор неудачен. Address - хорошее имя для класса.

Глава 3. Функции.

Компактность

Первое правило: фун-ии должны быть компактными. Второе правило: фун-ии должны быть ещё компактнее. Желательно чтобы длина функции не превышала 20 строк.

Блоки и отступы

Блоки в командах if, else, while должны состоять из одной строки, в которой обычно содержится вызов фун-ии. Это не только делает вмещающуюю фун-ии более компактной, но и способствует документированию кода.

Правило одной операции

Функция должна выполнять только одну операцию. Она должна выполнять её хорошо и ничего другого она делать не должна. Если ф-ия выполняет только те действия, которые находятся на одном уровне под объявленным именем ф-ии, то эта ф-ия выполняет одну операцию.

Используйте содеражательные имена

Чем меньше и специализированнее ф-ия, тем проще выбрать для нее содержательное имя. Длинное содержательное имя, лучше короткого невразумительного.

Используйте исклочения вместо кодов ошибок

Изолируйте блоки try/catch

Блоки try/catch выглядят уродливо, запутывают структуру кода и смешивают обработку ошибок с нормальной обработкой, поэтому лучше выносить эти блоки в отдельные ф-ии, например:

try {
  deletePageAndReferences(page);
} catch (e) {
  logError(e) {
}

Глава 4. Коммнтарии.

Грамотное применние комментариев должно компенсировать нашу неудачу в выражении своих мыслей в коде. Комментарий - всегда признак неудачи. Чем древнее комментарий, чем дальше он расположен от описываемого им кода, тем больше вероятность, что он неверен.

Примеры хороших комментариев:

  1. Юридические: копирайт, лицензия.
  2. Информативные: пояснения для регулярок, поиска, формата даты/времени.
  3. Представление намерений: нетривиальные решения требующие пояснения.
  4. Прояснение: комментарии для возвращающих значений, являющихся частью библиотеки.
  5. Предупреждения о последствиях: предупреждения о нежелательных или опасных действиях.
  6. Комментарии TODO.
  7. Услиление: если нужно подчеркнуть важность чего-то, что на первый взгляд кажется несущественным.

Всё остальное плохие комметарии, но если вы их всё таки решили написать, постарайтесь чтобы они были, краткими, содержатльными, достоверными. Позиционные маркеры, ссылки на авторов, закомментированный код, HTML-комментарии, неочевидные комментарии - плохо. Но не стоит использовать комментарий там, где можно использовать. фу-ю или переменную.

Глава 5. Форматирование.

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

Вертикальное разделение концепций

Каждая строка это выражение или условие, а каждая группа строк представляет собой законченную мысль. Каждая такая мысль должна отделятся пустой строкой. Концепции тесно связанные друг с другом должны находится поблизости друг от друга по вертикали и не должны находится в разных файлах. Переменные нужно объявлять как можно ближе к месту использования, а переменные экземпляров класса, напротив, должны объявлятся в начале класса. Если одна фу-я вызывает другую, то они должны находится вблизи друг друга и вызывающая фу-я должна находится над вызываемой (по возможности).

Горизонтальное форматирование

Оптимальная длинна строки 100-120 символов. Горизонтальное выравнивание, в большенстве случаев, приносит неудобства, потому что выделяет совсем не то, что требуется и отвлекает читателя.

Глава 6. Объекты и структуры данных.

Если в некоторой системе нас интересует гибкость в добавлении новых типов данных, то в этой части системы предпочтение отдается объектной реализации. Если нам нужна гибкость расширения поведения, то лучше выбирать процедуры.

Глава 7. Обработка ошибок.

При обнаружении ошибок лучше инициировать исключение. Код вызова становится более понятным, а его логика не скрывается за кодом обработки ошибок. Используйте try-catch-finaly.

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

Создавайте содержательные сообщения об ошибках и передавайте их своим исключениям. Каждое исключение должно содержать достаточно информации для определения источника ошибки.

Не возвращайте null при обработке ошибок. Никогда! Это создает дополнительную работу и есть вероятность, что ваше приложение однажды "уйдет в штопор". Вместо это верните исключение или если ваш код вызывает стороннее api, способный вернуть null, создайте для него обертку в виде метода, который инициирует исключение или возвращает объект особого случая (см. паттерн особый случай).

Возвращать null из методов плохо, но передавать null при вызове ещё хуже. Можно создать новый тип сключения и инициировать его в методе.

Глава 8. Границы.

Если в продукте есть код вне вашего контроля, примите особые меры по его защите, чтобы будущие изменения не обходились слишком дорого. Можно воспользоваться обертками или использовать паттерн "Адаптер".

Глава 9. Модульные тесты.

Три закона TDD

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

Тесты и код пишутся вместе, а тесты немного опережают код.

Тесты "на скорую руку" равносильны отсутствию тестов или даже хуже отсутствия.

Тесты должны менятся по мере развития продукта.

Хороший тест - удобочитаемый тест.

В каждой тестовой фу-ии должна тестироваться только одна концепция.

F.I.R.S.T.

Чистые тесты должны обладать 5-ю характеристиками:

Быстрота (Fast) Тесты должны выполнятся быстро.

Независимость (Independent) Тесты не должны зависеть друг от друга. Один тест не должен создавать условия для выполнения следующего теста.

Повторяемость (Repeatable) Тесты должны довать повторяемые результаты в любой среде.

Очевидность (Self-Validating) Результат выполнения теста должен быть логический. Тест либо пройден, либо нет. Чтобы узнать результат, пользователь не должен лезть в логи.

Своевременность (Timely) Тесты должны писать своевременно, непосредственно перед написанием кода продукта.

Глава 10. Классы.

clean-code's People

Contributors

petryaeva avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

Forkers

rickrotor

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.