SlideShare a Scribd company logo
1 of 54
Download to read offline
Практические советы
по улучшению
качества кода
О себе
• PHP разработчик более 5 лет
• Работа в компаниях
• Сертификаты
Афанасьев Юрий
oriand@yandex.ru
Почему важна читаемость?
• Чтение кода происходит чаще, нежели чем его
написание
• Чем проще читать код, тем легче его
сопровождать и находить в нём баги
• Эстетическое восприятие влияет на многие
показатели удобства работы с кодом и его
поддержку
3
Что делает этот код?
function calculate() {
return (hours + overtime * rate) * days * gradeRate
}
4
Бывает и хуже…
function result() {
return (hrs + plus_time * rate) * number * level
}
5
Плохо оформленный код
• Неприятно изучать и читать
• В нём сложно найти баги
• Возникают проблемы сопровождения и поддержки
• Его сложно дописывать, исправлять и что-либо с ним
делать
• Происходит постоянное наращивание кома никому
непонятного кода
• В конечном виде код превращается в спагетти-код
6
Стандарты кодирования
• Java: Sun Microsystems
• Python: PEP-8
• PHP: PSR
• JavaScript: JSCS, Google Style Guide
7
Пример
class Booking {
function calculate (Cargo cargo, Voyage voyage) {
float maxBooking = voyage.Capacity() * 1,1
if (voyage.bookedCargoSize() + cargo.size() > maxBooking) {
return false
}
return true
}
}
8
Магические числа
Магические числа
Это числа, такие как 100 или 32767, которые
появляются в программе без объяснений
Строковые значения (например, ’creditcard’) могут
также являться магическими числами
10
Что здесь не так?
class Booking {
function calculate (Cargo cargo, Voyage voyage) {
float maxBooking = voyage.Capacity() * 1,1
if (voyage.bookedCargoSize() + cargo.size() > maxBooking) {
return false
}
return true
}
}
11
float maxBooking = voyage.Capacity() * 1,1
const float OVERBOOKING = 1,1
float maxBooking = voyage.Capacity() * OVERBOOKING
12
В чём удобство констант?
• Улучшает понимание значения числа за счёт
именованной константы
• Проще заменить значения таких чисел во всём
коде
• Код становится легко читаемым и понятным
13
Исключение
Числа исключения - 0 и 1 (если семантически
означают начало отсчёта)
integer maxRange = 10000
for (n = 0; n < maxRange; ++n) {
// ....
}
14
if (codeStatus == 403) {
const integer FORBIDDEN = 403
if (codeStatus == FORBIDDEN) {
15
Методы в классах
Что такое метод?
Метод - это отдельная функция или процедура,
выполняющая одну задачу
17
Что здесь не так?
class Booking {
function calculate (Cargo cargo, Voyage voyage) {
float maxBooking = voyage.Capacity() * 1,1
if (voyage.bookedCargoSize() + cargo.size() > maxBooking) {
return false
}
return true
}
}
18
float maxBooking = voyage.Capacity() * 1,1
if (voyage.bookedCargoSize() + cargo.size() > maxBooking) {
if (
voyage.bookedCargoSize() + cargo.size() > this.getMaxBooking(voyage)
) {
19
Цель метода
Метод должен выполнять лишь одну четко
определенную цель: запись в БД, выполнение
сложных вычислений и т.д.
См. принципы SOLID (принцип одной
ответственности SPR)
20
function calculate (Cargo cargo, Voyage voyage) {
function isFull (Cargo cargo, Voyage voyage) {
21
Именование методов
• Описывайте все действия, происходящие в методе.
Например, sendRequest(), computeRecordDetails()
• Избегайте побочных действий в методах!
• Метод должен выражать действие, поэтому первое
слово всегда глагол. Например, getBankById(Id)
• Избегайте невыразительных имен.
Например, handleOutput(), formatAndPrintOutput()
22
Вложенность кода
Что здесь не так?
if (checkEmpty(message)) {
// … some code
if (maxValue < 100) {
// some code
if (foo->isValid()) {
// … save
} else {
logErrors();
}
}
}
24
Проблема вложенности
• Вложенность более 3-4 уровней сложно понять и
удержать в голове
• Глубокая вложенность говорит о том, что код
нужно рефакторить
25
Как избавиться?
• Переписать условия проверки if-else и циклов.
Например, чаще использовать блок выхода (return)
• Разбить код на небольшие методы
26
Перепишем пример
if ( !checkEmpty(message)) {
return
}
// … some code
if (maxValue > 100) {
return
}
// … some code
if (foo->isValid()) {
// … save
} else {
logErrors();
}
if (checkEmpty(message)) {
// … some code
if (maxValue < 100) {
// some code
if (foo->isValid()) {
// … save
} else {
logErrors();
}
}
}
27
В идеале
Пишите код таким, чтобы он читался словно книга
без постоянного перевода взгляда вверх и вниз
страницы
28
Комментарии
Комментирование кода
/* Убрано до лучших времён, которые вот-вот наступят
if (something) { return false } else { return true } */
GIT/SVN хранят историю изменений. Такие
комментарии сродни мусору в квартире
30
Волшебный TODO
// TODO: упрощённая реализация алгоритма
// Отрефакторить в задаче ETC-1510
• Указывайте все недоработки сразу и заводите на
них задачи
• Каждый такой комментарий указывает на
недоработку (потенциальную уязвимость)
31
Пояснения в начале файла
/* @author Testof Tester Testorovich
@changes 01.01.2016 bug fix
@example new A() */
• В совместном проекте нет единого автора, т.к.
каждый вносит свою лепту
• Историю изменений хранит git
• Пример использования может устареть
32
Описание намерений
// Проверка на загруженность транспортного средства
if (voyage.bookedCargoSize() + cargo.size() > maxBooking) {
• Такой код чаще всего некачественный
• Комментарии часто устаревают
• Между комментарием и кодом может появиться
другой код (!)
33
Как избавиться?
• Куски кода выделяйте в методы или классы
if (voyage.bookedCargoSize() + cargo.size() > this.getMaxBooking(voyage)) {
• Строкам присваивайте пояснительные
переменные или константы
const double OVERBOOKING = 1,1
float maxBooking = voyage.Capacity * OVERBOOKING
34
Принцип DRY
Don’t Repeat Yourself
float maxBooking = voyage.Capacity() * 1,1
if (voyage.bookedCargoSize() + cargo.size() > maxBooking) {
if (
voyage.bookedCargoSize() + cargo.size() > this.getMaxBooking(voyage)
) {
36
Один и только один раз
Повторяющиеся куски кода указывают на
упущенную возможность для абстракции
Дублирующий код чаще выделяют в отдельный
метод, реже - класс
37
Де жа вю?
• Куски кода выделяйте в методы или классы
if (voyage.bookedCargoSize() + cargo.size() > this.getMaxBooking(voyage)) {
38
Польза DRY
• Другие разработчики могут воспользоваться
вашим кодом и не выдумывать его самим
• Выделение абстракций повышает скорость
разработки и уменьшает число ошибок
• Дублирующиеся части могут содержать
различные реализации и разные ошибки
39
Проблема
function findByName(name) {
// …
sql = ‘SELECT * FROM bar WHERE name = ’ . name
// …
}
function findById (id) {
// …
sql = ‘SELECT * FROM bar WHERE id = ’ . id
// …
}
40
Решение
function findByName(name) {
// …
sql = findBy(‘name’, name)
// …
}
function findById (id) {
// …
sql = findBy(‘id’, id)
// …
}
41
Ложка дёгтя
Следование принципу неоправданно, если
• Объединение реализаций плохо связанных
сущностей (отзывы и комментарии)
• Код разных версий api
• В highload проектах (денормализация БД)
• И так далее
Принцип наименьшего
удивления
Что делает этот код?
date.add(5)
44
Помните этот пример?
function result() {
return (hrs + plus_time * rate) * number * level
}
45
Несколько правил
Пишите код так, чтобы он никого не удивлял
• Константы, методы должны располагаться на
своём уровне абстракции
• Название метода должно соответствовать тому,
что оно действительно выполняет
• Избавляйтесь от побочных эффектов в коде
46
Выводы
Код должен выражать намерения разработчика!
Магические числа, длинные и сложные выражения
и т.д. - скрывают намерения автора
И напоследок
• В первую очередь, используйте стандарты,
принятые в вашей компании
• Книги и статьи дают лишь рекомендации. Как
использовать полученные знания решать вам
• Не переусердствуйте в своём желании улучшить
мир кодом. Придерживайтесь золотой середины
49
Книги и ссылки
Совершенный
код
Стив Макконнелл
Чистый код
Роберт Мартин
http://habrahabr.ru/post/266969/
http://geekbrains.ru/events/124
Ссылки
Вопросы?

More Related Content

What's hot

Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Sergey Platonov
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Yandex
 
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Yandex
 
Программирование на языке C Sharp (СИ решетка)
Программирование на языке C Sharp (СИ решетка)Программирование на языке C Sharp (СИ решетка)
Программирование на языке C Sharp (СИ решетка)Alexandr Konfidentsialno
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Yauheni Akhotnikau
 
Dmitrii Dolzhenko «С++ Problems and How Test Frameworks Actually Work»
Dmitrii Dolzhenko «С++ Problems and How Test Frameworks Actually Work» Dmitrii Dolzhenko «С++ Problems and How Test Frameworks Actually Work»
Dmitrii Dolzhenko «С++ Problems and How Test Frameworks Actually Work» LogeekNightUkraine
 
JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.Igor Shkulipa
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаSergey Platonov
 
Никита Цуканов - "Avalonia UI Cross-platform Open Source UI Framework"
Никита Цуканов - "Avalonia UI Cross-platform Open Source UI Framework"Никита Цуканов - "Avalonia UI Cross-platform Open Source UI Framework"
Никита Цуканов - "Avalonia UI Cross-platform Open Source UI Framework"Elias Fofanov
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
хитрости выведения типов
хитрости выведения типовхитрости выведения типов
хитрости выведения типовcorehard_by
 
Программирование на языке C Sharp (СИ решетка) ПРАКТИКУМ
Программирование на языке C Sharp (СИ решетка) ПРАКТИКУМПрограммирование на языке C Sharp (СИ решетка) ПРАКТИКУМ
Программирование на языке C Sharp (СИ решетка) ПРАКТИКУМAlexandr Konfidentsialno
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.Igor Shkulipa
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IPlatonov Sergey
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыPlatonov Sergey
 

What's hot (20)

Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
Александр Тарасенко, Использование python для автоматизации отладки С/C++ код...
 
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
Некоторые паттерны реализации полиморфного поведения в C++ – Дмитрий Леванов,...
 
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
Использование шаблонов и RTTI для конфигурации симулятора флеш-накопителя - Г...
 
Программирование на языке C Sharp (СИ решетка)
Программирование на языке C Sharp (СИ решетка)Программирование на языке C Sharp (СИ решетка)
Программирование на языке C Sharp (СИ решетка)
 
Kranonit s16 (python). dmitry furzenko
Kranonit s16 (python). dmitry furzenkoKranonit s16 (python). dmitry furzenko
Kranonit s16 (python). dmitry furzenko
 
JRebel
JRebelJRebel
JRebel
 
Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?Акторы на C++: стоило ли оно того?
Акторы на C++: стоило ли оно того?
 
Kranonit s16 (python). sergey burma
Kranonit s16 (python). sergey burmaKranonit s16 (python). sergey burma
Kranonit s16 (python). sergey burma
 
Dmitrii Dolzhenko «С++ Problems and How Test Frameworks Actually Work»
Dmitrii Dolzhenko «С++ Problems and How Test Frameworks Actually Work» Dmitrii Dolzhenko «С++ Problems and How Test Frameworks Actually Work»
Dmitrii Dolzhenko «С++ Problems and How Test Frameworks Actually Work»
 
JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.JavaScript Базовый. Занятие 03.
JavaScript Базовый. Занятие 03.
 
Павел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладкаПавел Довгалюк, Обратная отладка
Павел Довгалюк, Обратная отладка
 
Никита Цуканов - "Avalonia UI Cross-platform Open Source UI Framework"
Никита Цуканов - "Avalonia UI Cross-platform Open Source UI Framework"Никита Цуканов - "Avalonia UI Cross-platform Open Source UI Framework"
Никита Цуканов - "Avalonia UI Cross-platform Open Source UI Framework"
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
хитрости выведения типов
хитрости выведения типовхитрости выведения типов
хитрости выведения типов
 
Цена ошибки
Цена ошибкиЦена ошибки
Цена ошибки
 
Программирование на языке C Sharp (СИ решетка) ПРАКТИКУМ
Программирование на языке C Sharp (СИ решетка) ПРАКТИКУМПрограммирование на языке C Sharp (СИ решетка) ПРАКТИКУМ
Программирование на языке C Sharp (СИ решетка) ПРАКТИКУМ
 
C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.C++ Базовый. Занятие 04.
C++ Базовый. Занятие 04.
 
PVS-Studio vs Chromium
PVS-Studio vs ChromiumPVS-Studio vs Chromium
PVS-Studio vs Chromium
 
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках IДмитрий Кашицын, Вывод типов в динамических и не очень языках I
Дмитрий Кашицын, Вывод типов в динамических и не очень языках I
 
DI в C++ тонкости и нюансы
DI в C++ тонкости и нюансыDI в C++ тонкости и нюансы
DI в C++ тонкости и нюансы
 

Similar to практические советы по улучшению качества кода

Теории и практики функционального программирования.
Теории и практики функционального программирования.Теории и практики функционального программирования.
Теории и практики функционального программирования.Dev2Dev
 
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»Yandex
 
Теории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2DТеории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2D0xffAA
 
functional patterns - dotnetconf'11
functional patterns - dotnetconf'11functional patterns - dotnetconf'11
functional patterns - dotnetconf'110xffAA
 
Илья Фофанов "Обработка ошибок в C#"
Илья Фофанов "Обработка ошибок в C#"Илья Фофанов "Обработка ошибок в C#"
Илья Фофанов "Обработка ошибок в C#"Yulia Tsisyk
 
Алексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаАлексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаYandex
 
Цена ошибки
Цена ошибкиЦена ошибки
Цена ошибкиAndrey Karpov
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioAndrey Karpov
 
Эффективный C++
Эффективный C++Эффективный C++
Эффективный C++Andrey Karpov
 
разработка бизнес приложений (8)
разработка бизнес приложений (8)разработка бизнес приложений (8)
разработка бизнес приложений (8)Alexander Gornik
 
Статический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeСтатический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeTatyanazaxarova
 
Программирование как способ выражения мыслей.
Программирование как способ выражения мыслей. Программирование как способ выражения мыслей.
Программирование как способ выражения мыслей. Levon Avakyan
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй этоRoman Dvornov
 
CSSO – история ускорения
CSSO – история ускоренияCSSO – история ускорения
CSSO – история ускоренияRoman Dvornov
 
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...Yandex
 
анализ кода: от проверки стиля до автоматического тестирования
анализ кода: от проверки стиля до автоматического тестированияанализ кода: от проверки стиля до автоматического тестирования
анализ кода: от проверки стиля до автоматического тестированияRuslan Shevchenko
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Platonov Sergey
 
Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальBadoo Development
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановYandex
 

Similar to практические советы по улучшению качества кода (20)

Теории и практики функционального программирования.
Теории и практики функционального программирования.Теории и практики функционального программирования.
Теории и практики функционального программирования.
 
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
FrontTalks: Алексей Андросов (Яндекс), «Ошибки, которые мы любим»
 
Теории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2DТеории и практики фунционального программирования - GDG D2D
Теории и практики фунционального программирования - GDG D2D
 
functional patterns - dotnetconf'11
functional patterns - dotnetconf'11functional patterns - dotnetconf'11
functional patterns - dotnetconf'11
 
Илья Фофанов "Обработка ошибок в C#"
Илья Фофанов "Обработка ошибок в C#"Илья Фофанов "Обработка ошибок в C#"
Илья Фофанов "Обработка ошибок в C#"
 
Алексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кодаАлексей Андросов - Debugger: Отладка кода
Алексей Андросов - Debugger: Отладка кода
 
Цена ошибки
Цена ошибкиЦена ошибки
Цена ошибки
 
Принципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-StudioПринципы работы статического анализатора кода PVS-Studio
Принципы работы статического анализатора кода PVS-Studio
 
Эффективный C++
Эффективный C++Эффективный C++
Эффективный C++
 
разработка бизнес приложений (8)
разработка бизнес приложений (8)разработка бизнес приложений (8)
разработка бизнес приложений (8)
 
Статический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMergeСтатический анализ исходного кода на примере WinMerge
Статический анализ исходного кода на примере WinMerge
 
Программирование как способ выражения мыслей.
Программирование как способ выражения мыслей. Программирование как способ выражения мыслей.
Программирование как способ выражения мыслей.
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй это
 
CSSO – история ускорения
CSSO – история ускоренияCSSO – история ускорения
CSSO – история ускорения
 
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
Филипп Торчинский «Анализ производительности и отладка приложений с помощью D...
 
анализ кода: от проверки стиля до автоматического тестирования
анализ кода: от проверки стиля до автоматического тестированияанализ кода: от проверки стиля до автоматического тестирования
анализ кода: от проверки стиля до автоматического тестирования
 
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
Владислав Шаклеин. Смешивание управляемого и неуправляемого C++ кода в Micros...
 
Как мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон ДовгальКак мы делаем модули PHP в Badoo – Антон Довгаль
Как мы делаем модули PHP в Badoo – Антон Довгаль
 
Coding like a sex
Coding like a sexCoding like a sex
Coding like a sex
 
Статический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий ЛевановСтатический и динамический полиморфизм в C++, Дмитрий Леванов
Статический и динамический полиморфизм в C++, Дмитрий Леванов
 

практические советы по улучшению качества кода

  • 2. О себе • PHP разработчик более 5 лет • Работа в компаниях • Сертификаты Афанасьев Юрий oriand@yandex.ru
  • 3. Почему важна читаемость? • Чтение кода происходит чаще, нежели чем его написание • Чем проще читать код, тем легче его сопровождать и находить в нём баги • Эстетическое восприятие влияет на многие показатели удобства работы с кодом и его поддержку 3
  • 4. Что делает этот код? function calculate() { return (hours + overtime * rate) * days * gradeRate } 4
  • 5. Бывает и хуже… function result() { return (hrs + plus_time * rate) * number * level } 5
  • 6. Плохо оформленный код • Неприятно изучать и читать • В нём сложно найти баги • Возникают проблемы сопровождения и поддержки • Его сложно дописывать, исправлять и что-либо с ним делать • Происходит постоянное наращивание кома никому непонятного кода • В конечном виде код превращается в спагетти-код 6
  • 7. Стандарты кодирования • Java: Sun Microsystems • Python: PEP-8 • PHP: PSR • JavaScript: JSCS, Google Style Guide 7
  • 8. Пример class Booking { function calculate (Cargo cargo, Voyage voyage) { float maxBooking = voyage.Capacity() * 1,1 if (voyage.bookedCargoSize() + cargo.size() > maxBooking) { return false } return true } } 8
  • 10. Магические числа Это числа, такие как 100 или 32767, которые появляются в программе без объяснений Строковые значения (например, ’creditcard’) могут также являться магическими числами 10
  • 11. Что здесь не так? class Booking { function calculate (Cargo cargo, Voyage voyage) { float maxBooking = voyage.Capacity() * 1,1 if (voyage.bookedCargoSize() + cargo.size() > maxBooking) { return false } return true } } 11
  • 12. float maxBooking = voyage.Capacity() * 1,1 const float OVERBOOKING = 1,1 float maxBooking = voyage.Capacity() * OVERBOOKING 12
  • 13. В чём удобство констант? • Улучшает понимание значения числа за счёт именованной константы • Проще заменить значения таких чисел во всём коде • Код становится легко читаемым и понятным 13
  • 14. Исключение Числа исключения - 0 и 1 (если семантически означают начало отсчёта) integer maxRange = 10000 for (n = 0; n < maxRange; ++n) { // .... } 14
  • 15. if (codeStatus == 403) { const integer FORBIDDEN = 403 if (codeStatus == FORBIDDEN) { 15
  • 17. Что такое метод? Метод - это отдельная функция или процедура, выполняющая одну задачу 17
  • 18. Что здесь не так? class Booking { function calculate (Cargo cargo, Voyage voyage) { float maxBooking = voyage.Capacity() * 1,1 if (voyage.bookedCargoSize() + cargo.size() > maxBooking) { return false } return true } } 18
  • 19. float maxBooking = voyage.Capacity() * 1,1 if (voyage.bookedCargoSize() + cargo.size() > maxBooking) { if ( voyage.bookedCargoSize() + cargo.size() > this.getMaxBooking(voyage) ) { 19
  • 20. Цель метода Метод должен выполнять лишь одну четко определенную цель: запись в БД, выполнение сложных вычислений и т.д. См. принципы SOLID (принцип одной ответственности SPR) 20
  • 21. function calculate (Cargo cargo, Voyage voyage) { function isFull (Cargo cargo, Voyage voyage) { 21
  • 22. Именование методов • Описывайте все действия, происходящие в методе. Например, sendRequest(), computeRecordDetails() • Избегайте побочных действий в методах! • Метод должен выражать действие, поэтому первое слово всегда глагол. Например, getBankById(Id) • Избегайте невыразительных имен. Например, handleOutput(), formatAndPrintOutput() 22
  • 24. Что здесь не так? if (checkEmpty(message)) { // … some code if (maxValue < 100) { // some code if (foo->isValid()) { // … save } else { logErrors(); } } } 24
  • 25. Проблема вложенности • Вложенность более 3-4 уровней сложно понять и удержать в голове • Глубокая вложенность говорит о том, что код нужно рефакторить 25
  • 26. Как избавиться? • Переписать условия проверки if-else и циклов. Например, чаще использовать блок выхода (return) • Разбить код на небольшие методы 26
  • 27. Перепишем пример if ( !checkEmpty(message)) { return } // … some code if (maxValue > 100) { return } // … some code if (foo->isValid()) { // … save } else { logErrors(); } if (checkEmpty(message)) { // … some code if (maxValue < 100) { // some code if (foo->isValid()) { // … save } else { logErrors(); } } } 27
  • 28. В идеале Пишите код таким, чтобы он читался словно книга без постоянного перевода взгляда вверх и вниз страницы 28
  • 30. Комментирование кода /* Убрано до лучших времён, которые вот-вот наступят if (something) { return false } else { return true } */ GIT/SVN хранят историю изменений. Такие комментарии сродни мусору в квартире 30
  • 31. Волшебный TODO // TODO: упрощённая реализация алгоритма // Отрефакторить в задаче ETC-1510 • Указывайте все недоработки сразу и заводите на них задачи • Каждый такой комментарий указывает на недоработку (потенциальную уязвимость) 31
  • 32. Пояснения в начале файла /* @author Testof Tester Testorovich @changes 01.01.2016 bug fix @example new A() */ • В совместном проекте нет единого автора, т.к. каждый вносит свою лепту • Историю изменений хранит git • Пример использования может устареть 32
  • 33. Описание намерений // Проверка на загруженность транспортного средства if (voyage.bookedCargoSize() + cargo.size() > maxBooking) { • Такой код чаще всего некачественный • Комментарии часто устаревают • Между комментарием и кодом может появиться другой код (!) 33
  • 34. Как избавиться? • Куски кода выделяйте в методы или классы if (voyage.bookedCargoSize() + cargo.size() > this.getMaxBooking(voyage)) { • Строкам присваивайте пояснительные переменные или константы const double OVERBOOKING = 1,1 float maxBooking = voyage.Capacity * OVERBOOKING 34
  • 36. float maxBooking = voyage.Capacity() * 1,1 if (voyage.bookedCargoSize() + cargo.size() > maxBooking) { if ( voyage.bookedCargoSize() + cargo.size() > this.getMaxBooking(voyage) ) { 36
  • 37. Один и только один раз Повторяющиеся куски кода указывают на упущенную возможность для абстракции Дублирующий код чаще выделяют в отдельный метод, реже - класс 37
  • 38. Де жа вю? • Куски кода выделяйте в методы или классы if (voyage.bookedCargoSize() + cargo.size() > this.getMaxBooking(voyage)) { 38
  • 39. Польза DRY • Другие разработчики могут воспользоваться вашим кодом и не выдумывать его самим • Выделение абстракций повышает скорость разработки и уменьшает число ошибок • Дублирующиеся части могут содержать различные реализации и разные ошибки 39
  • 40. Проблема function findByName(name) { // … sql = ‘SELECT * FROM bar WHERE name = ’ . name // … } function findById (id) { // … sql = ‘SELECT * FROM bar WHERE id = ’ . id // … } 40
  • 41. Решение function findByName(name) { // … sql = findBy(‘name’, name) // … } function findById (id) { // … sql = findBy(‘id’, id) // … } 41
  • 42. Ложка дёгтя Следование принципу неоправданно, если • Объединение реализаций плохо связанных сущностей (отзывы и комментарии) • Код разных версий api • В highload проектах (денормализация БД) • И так далее
  • 44. Что делает этот код? date.add(5) 44
  • 45. Помните этот пример? function result() { return (hrs + plus_time * rate) * number * level } 45
  • 46. Несколько правил Пишите код так, чтобы он никого не удивлял • Константы, методы должны располагаться на своём уровне абстракции • Название метода должно соответствовать тому, что оно действительно выполняет • Избавляйтесь от побочных эффектов в коде 46
  • 48. Код должен выражать намерения разработчика! Магические числа, длинные и сложные выражения и т.д. - скрывают намерения автора
  • 49. И напоследок • В первую очередь, используйте стандарты, принятые в вашей компании • Книги и статьи дают лишь рекомендации. Как использовать полученные знания решать вам • Не переусердствуйте в своём желании улучшить мир кодом. Придерживайтесь золотой середины 49