ЧИСТЫЙ КОД
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