ЧИСТЫЙ КОД

Software Design Meetup

Философия создания и развития ПО

РЕФАКТОРИНГ

"Speed depends on stability" - Martin Fowler

Vladimir Minkin (vk.com/vladimir.minkin)

Код это требования

Software Design Meetup

Когда требования определяются настолько подробно, чтобы они могли бы быть выполнены компьютером, 
это и есть программирование.

“The code itself, no matter how ideal it is, is not worth a penny. What matters is the business functionality that this code implements.” - Nikolay Ashanin

Логика должна быть достаточно прямолинейной,
чтобы ошибкам было трудно спрятаться

Бьёрн Страуступ

Software Design Meetup

Software Design Meetup

В автостроении основная часть работы связано не с производством, в с сопровождением продуктов.

Необходимо знать
что где находится

"The code does not “care” about how cohesive or decoupled it is; people do." - Tago Fabic

Software Design Meetup

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

Потом === никогда

Software Design Meetup

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

"Fools ignore complexity. Pragmatists suffer it.
Some can avoid it. Geniuses remove it." -
Alan Perlis

(Le Blanc's law)

Software Design Meetup

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

3 стадии кода

Software Design Meetup

Make it work
Make it right
Make it fast

(Kent Beck)

"Any fool can write code that a computer can understand.
Good programmers write code that humans can understand."

- Martin Fowler

Software Design Meetup

Чистый код должен читаться как хорошо написанная проза, слова словно изчезают, заменяясь зрительными образами! Так чтобы читатель воскликнул:

«Ага! Ну конечно!»

Devil is in details

Software Design Meetup

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

"After you finish the first 90% of a project,
you have to finish the other 90%."
- Michael Abrash

Software Design Meetup

Мы способны отличить хорошую картину от плохой, но это ещё не значит что мы умеем рисовать.

«Чувство кода»

Software Design Meetup

Бесполезно пытаться написать чистый код, 
если вы не знаете что это такое!

"Good programming is good writing."
- John Shore

Software Design Meetup

Допускать высказывания типа
"тестирование - это не мое дело"
нельзя.

J. Hank Rainwater

Тесты - Holy Grail

Software Design Meetup

Код без тестов не может быть назван чистым!

Работа программиста не заканчивается написанием кода - он должен доказать что код работает правильно.

"Tests are the Programmer's stone, transmuting fear into boredom." - Kent Beck

Software Design Meetup

Если у вас есть тесты, вы не боитесь вносить изменения в код! Именно тесты делают наш код гибким, пригодным для сопровождения и повторного использования.
Без тестов каждое изменение — возможная ошибка.

1. Имена

Software Design Meetup

- должны передавать намерение
- удобные для поиска (не однобуквенные*)
- одно слово для каждой концепции
- классы - существительные, методы - глаголы
- из пространства решений (структур)

"A sentence should be enough to get the idea across." - 37Signals

Software Design Meetup

Software Design Meetup

Не язык делает программы простыми.
Программа выглядит простой благодаря
работе программиста!

Software Design Meetup

Prefix / Suffix

is
on

can

dom

when

VO

DTO

DAO

View

Service

"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
- Martin Golding

Software Design Meetup

Длинные имена и параметры

глагол
+ существительное
+ прилагательное

Software Design Meetup

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

Software Design Meetup

Из пространства решений

2. Функции

Software Design Meetup

- Первое правило: функции должны быть компактными.
- Второе правило: функции должны быть еще компактнее.
- Желательно чтобы длина функции не превышала 20 строк.
- Максимальный уровень отступов не превышает одного-двух.
- Не должны содержать вложенный структур (*).

"Functions should do one thing. They should do it well. They should do it only." - Robert C. Martin

Software Design Meetup

Software Design Meetup

Функции пишутся прежде всего для разложения более крупной концепции.

Software Design Meetup

Software Design Meetup

Функция должна что-то делать или отвечать на какой то вопрос, но не одновременно.

Либо функция изменяет состояние объекта,
либо возвращает информацию

Software Design Meetup

Пример
рефакторинг

Слишком много действий, сложно понять что и как она делает.

Software Design Meetup

В общей сумме получили 10 + 6 строчек кода

Результат

Software Design Meetup

Обработка ошибок - это одна операция.
Значит, функция, обрабатывающая ошибки,
ничего другого делать не должна!

Software Design Meetup

Уровни ошибок

Service

View

Software Design Meetup

Искусство программирования является искусством языкового проектирования.

Software Design Meetup

Опытные программисты рассматривают систему как историю, которую они должны рассказать.

Software Design Meetup

Ваша цель - "рассказать историю" системы, а написанные вами функции должны четко складываться в понятный и точный язык, который поможет вам в этом.

Software Design Meetup

Функциональное

Software Design Meetup

- Абстракции над абстракциями - функции в функциях
- Алгебраические структуры: "monoids", "semigroups", "functors", "monads"
- "Чистые" (Pure) функции

"Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function." - John Carmack

(link)

Software Design Meetup

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


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

3. Комментарии

Software Design Meetup

- Комментарии в лучшем случае являются неизбежным злом.
- Неточные комментарии гораздо вреднее, чем отсутствие.
- Предупреждение о последствиях.
- Заметки на будующее - комментарий TODO: (билет).
- Комментарии к API общего пользования

"Don't comment bad code - rewrite it."
- Brian W. Kernighan & P. J. Plaugher

Software Design Meetup

Wire API

Software Design Meetup

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

Software Design Meetup

GIT
COMMITS
HISTORY

4. Тесты

Software Design Meetup

- Тесты и код продукта пишутся вместе.
- Тестовый код не менее важен, чем код продукта. 
- Тесты как средство обеспечения изменений.
- Если не поддерживать чистоту тестов, то вы их лишитесь.
- Без тестов любое изменение становится потенциальной ошибкой!

"A clever person solves a problem.
A wise person avoids it."
— Albert Einstein

Тестируйте
граничные
условия

Software Design Meetup

Software Design Meetup

Cypress
E2E

Software Design Meetup

Unit
Tests

Software Design Meetup

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

5. Классы

Software Design Meetup

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

"90% of the functionality delivered now is better than 100% delivered never." - Brian W. Kernighan

Software Design Meetup

TodoModel

Инкапсулирует
абстракцию IDatabaseService

Dependencies Inversion

Software Design Meetup

Гибридные структуры - наполовину объекты, наполовину структуры данных; они усложняют как добаление новых функций, так и новых структур данных (*).

Функции или типы

Software Design Meetup

Струтура данных VO -
Value Object

Не обладает поведением (может отражать структуру базы данных)

Software Design Meetup

Классы должны иметь небольшое количество переменных. Каждый метод класса должен оперировать с одной или несколькими из этих переменных.

Закон Деметры (*)

Software Design Meetup

Модуль не должен знать устройство тех объектов, 
с которыми он работает.

Метод не должен вызывать методы объектов, 
возвращаемых любым их разрещенных функций.

Trainwreck:  b.getC().getD().getE().doThing();

?

Software Design Meetup

Код должен выражать намерение автора.

Классы - SOLID

Software Design Meetup

S: Single Responsibility
O: Open — Closed
L: Liskov Substitution
I: Interface Segregation
D: Dependency Inversion

"Theory and practice sometimes clash. And when that happens, theory loses. Every single time." - Linus Torvalds

(link)

Software Design Meetup

Single Responsibility

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

Software Design Meetup

- Структура системы должна быть такой, чтобы обновление (добавление или изменения) создавало как можно меньше проблем!

- В идеале новая функциональность должна реализовываться расширением системы, а не внесением изменений в существующий код.

Open — Closed

Software Design Meetup

Open
Closed

Software Design Meetup

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

Liskov Substitution

Software Design Meetup

- По мере роста вашего приложения у вас возникает соблазн добавить метод к существующему интерфейсу. 

- Если метод не связан с интерфейсом, лучше выделить этот новый метод в отдельный интерфейс.

Interface Segregation

 (sub-interfaces)

Software Design Meetup

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

- Отсутствие жестких привязок означает, что элементы системы лучше изолируются друг от друга и от изменений.

Dependency Inversion

Software Design Meetup

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

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

- Если классы утрачивают связанность, разбейти их!

Связанность

6. Системы

Software Design Meetup

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

В чистой системе классы организованы таким образом, чтобы риск от изменений был сведен к минимуму.

Software Design Meetup

Возможность построить
"правильную систему с первого раза" -
миф.

Software Design Meetup

- Конструирование и использование системы - два совершенно разных процесса.
- Фаза инициализации присутствует в каждом приложении.
- Перемещение всех аспектов конструирования в main.
- Приложение ничего не знает о процессе конструирования.

Отделение конструирования системы от ее использования

"Anything that can possibly go wrong, will go wrong."
- Murphy's Law

Software Design Meetup

Asynchronious

Dependency
Injection

Software Design Meetup

Код должен легко читаться,
даже если это затрудняет его написание.

Software Design Meetup

- Механизм отделения конструирования от использования.
- Практическое применение обращения контроля (IoC) - SRP.
- Объект не должен брать на себя ответственность за создание экземпляров зависимостей.
- Объекты могут быть с отложенной инициализацией.

Внедрение зависимостей (DI)

"One man's crappy software is another man's full time job."
- Jessica Gaston

Software Design Meetup

Dependency Injection

Software Design Meetup

Asynchronious

Software Design Meetup

Software Design Meetup

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

Software Design Meetup

В некоторых ситуациях, момент создания объекта должен определяется приложением.

Фабрики (Abstract Factory)

Software Design Meetup

Дублирование - главный враг
хорошо спроектированной системы.
DRY

Software Design Meetup

Сегодня мы реализуем текущие потребности, а завтра перерабатываем и расширяем систему для реализации новых потребностей.

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

Суть итеративной, пошаговой гибкой разработки

Software Design Meetup

Модульность и разделение ответсвенности позволяют децентрилизовать управление и принятие решений.

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

Оптимизация принятия решений

"Machines should work. People should think."
- IBM Pollyanna Principle

Software Design Meetup

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

"The longer it takes for a bug to surface, the harder it is to find."
- Roedy Green

Сопровождение

Software Design Meetup

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

"At some point software design becomes less about what and more about when." - Kent Beck

Выразительность - экономия ресурсов

Software Design Meetup

- Обеспечение прохождения всех тестов
- Не содержит дублирующего кода
- Выражает намерение программиста
- Использует минимальное количество классов и методов

"Architecture is not about making decisions earlier,
but making decisions
late." - Robert C. Martin

4 правила простой архитектуры

Software Design Meetup

Большинство систем работают лучше всего, если они остаются простыми, а не усложняются. 

Из всех возможных вариантов выбирайте наиболее простой!

“Big fish in a small pond”
- Malcolm Gladwell​ (link)

KISS

7. Рефакторинг

Software Design Meetup

- Устранение дубликатов
- Устранение жестких привязок
- Повышение связяности
- Разделение ответственности
- Изоляция системных областей (plugins)
- Сокращение объема функций и классов
- Выбор более содержательных имен

Software Design Meetup

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

Software Design Meetup

С1: Неуместная информация
С2: Устаревший комментарий
С3: Избыточный комментарий
С4: Плохо написанный комментарий
С5: Закомментированный код

Комментарии

"When you feel the need to write a comment, first try to refactor the code so that any comment becomes superflous." - Martin Fowler

Software Design Meetup

F1: Слишком много аргументов
F2: Выходные аргументы
F3: Флаги в аргументах
F4: Мертвые функции

Функции

"A design is a plan or specification for the construction of
an object or system."
- Wikipedia

G1: Несколько языков в одном исходном файле
G2: Очевидное поведение не реализовано
G3: Некорректное граничное поведение
G4: Отключенные средства безопасности
G5: Дублирование
G6: Код на неверном уровне абстракции
G7: Базовые классы, зависящие от производных
G8: Слишком много информации

Разное 1

Software Design Meetup

G9: Мертвый код
G10: Вертикальное разделение
G11: Непоследовательность
G12: Балласт
G13: Искусственные привязки
G14: Функциональная зависть
G15: Аргументы селекторы
G16: Непонятные намерения

Разное 2

Software Design Meetup

G17: Неверное размещение
G18: Неуместные статические методы
G19: Используйте пояснительные переменные
G20: Имена функций должны описывать выполняемую операцию
G21: Понимание алгоритма
G22: Пребразование логических зависимостей в физические
G23: Полиморфизм вместо if/else или switch/case
G24: Соблюдайте стандартные конвенции

Разное 3

Software Design Meetup

G25: Заменяйте "волшебные числа" именованными константами
G26: Будьте точны
G27: Структура важнее конвенций
G28: Инкапсулируйте условные конструкции
G29: Избегайте отрицательный условий
G30: Функции должны выполнять одну операцию
G31: Скрытые временные привязки
G32: Структура кода должна быть обоснована

Разное 4

Software Design Meetup

G33: Инкапсулируйте граничные условия
G34: Функции должны быть написаны на одном уровне абстракции
G35: Храните конфигурационные данные на высоких уровнях
G36: Избегайте транзитивных обращений ("закон Деметры")

Разное 5

"These days, the problem isn't how to innovate; it's how to get society to adopt the good ideas that already exist." - Douglas Engelbart

Software Design Meetup

N1: Используйте содержательные имена
N2: Выбирайте имена на подходящем уровне абстракции
N3: По возможности используйте стандартную номенклатуру
N4: Недвусмысленные имена
N5: Используйте длинные имена для длинных областей видимости
N6: Избегайте кодирования
N7: Имена должны описывать побочные эффекты

Имена

Software Design Meetup

T1: Нехватка тестов
T2: Используйте средства анализа покрытия кода
T3: Не пропускайте тривиальные тесты
T4: Отключенный тест как вопрос
T5: Тестируйте граничные условия
T6: Тщательное тестируйте код рядом с ошибками
T7: Закономерности сбоев часто несут полезную информацию

Тесты

Software Design Meetup

СПАСИБО

Software Design Meetup

Github: Code

"The only way to go fast, is to go well."
- Robert C. Martin

Чистый код, рефакторинг, философия создания и развития ПО

By Vladimir Cores Minkin

Чистый код, рефакторинг, философия создания и развития ПО

  • 441