DevPoint 2016: Признаки плохого кода и как с ним бороться в PHP...

Preview:

Citation preview

Признаки плохого кода и как с ним бороться в PHP проектах

class Speaker extends DevPointSpeaker{

private $_name = “Панаскин Денис”;private $_company = “Varteq”;private $_position = “Directory of Technology”;private $_site = “http://varteq.com”;private $_email = “denis@panaskin.com”;

}

$currentSpeaker = new Speaker();try {

$currentSpeaker.start();} catch (SpeakerException $exp) {

Logger.error(“Shit happens”, $exp);}

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

- Мартин Фаулер

Бывает ли идеальный код?

КОНЕЧНО!!!

НЕТ :)

Когда и как наносятся удары по качеству кода?

*

*

*

*

*

*

*

*

*

*

Когда хардкод оправдан?

Хардкод “по-модному”: Ad-hoc решение

Ad-hoc решение‣ Принять факт что хардкод неизбежен

‣ Принять факт что хардкод неизбежен‣ Хорошо документировать костыли

Ad-hoc решение

‣ Принять факт что хардкод неизбежен‣ Хорошо документировать костыли ‣ Комментарии к Ad-hoc коду должны отвечать на вопрос

“почему” и “зачем”, а не что делает код!

Ad-hoc решение

Часто встречающиеся проблемы в коде

SQL в бизнес логике

HTML в коде

Запросы в циклах

Наличие цифр в именах переменных, классов и ключах

$slide1 = ‘’;$slide2 = ‘’;$customer1 = ‘’;

*

Большое количество статических методов и их вызовов

Если префиксы и постфиксы в именах классов “прыгают”

ProductItemItemProduct

*

Злоупотребление паттернами

Большие классы и длинные методы

Copy - Past кода

Большое количество вложенных циклов и if’ов

if (condition1) { ... if (condition2) { ... for ($i = 0; $i < 10; $i++) { ... if (condition4) {

if (condition5) { foreach ($products as $product) { …}

} ... } return; } } } }

Сокращения имен переменных, методов, классов и т.д

$c = $this->getCBD();$i = $c->getСI();

*

Отсутствие код стайла

PEAR (http://pear.php.net/manual/en/standards.php)PSR-1 и PSR-2 (http://www.php-fig.org/)Symfony2 (http://symfony.com/doc/current/contributing/code/standards.html)Zend (http://framework.zend.com/manual/en/coding-standard.coding-style.html)WordPress (http://make.wordpress.org/core/handbook/coding-standards/php/)Drupal (http://drupal.org/coding-standards)

Критерии оценки качества кода

Понятность (Understandability)public function hasPermission() {

start:if ($this->user && $this->user->role > 5) {

return true;} else if ($this->user) {

if ($this->user->role == 2 && $this->product[‘qty’] < 0 || $this->page == ‘catalog’) { return false;

} else { return true; }

} else {$this->page = ‘product’;goto start;

} return false;

}

Читабельность (Readability)class user{

public $id;private $role, $_lastSignin, $list_props, $currentData, $session;

public function sign($l, $p) {if (!$l || $p)

$this->raise_error();try {

$res = $this->validate($l, $p);} catch (Exception $e) { return false;}

if ($res)for ($i = 0; $i < UserProperties::count(); $i++){

$this->list_props[‘pr_’ + ($i + 1)] = UserProperties::get_prop_by_index($i, false, null, $l);}

$this->role = $this->getRoleInformation($l);return ($this->role == 4 || $this->role < 2) ? $this->currentData : $this->getInfoByLogin($l);

}}

Видоизменяемость (Changeability)

Видоизменяемость (Changeability)‣Принцип единственной ответственности (Single

responsibility)

Видоизменяемость (Changeability)‣Принцип единственной ответственности (Single

responsibility)‣Классы не должны быть сильно большими, не содержать

много: полей, методов, строк кода

Видоизменяемость (Changeability)‣Принцип единственной ответственности (Single

responsibility)‣Классы не должны быть сильно большими, не содержать

много: полей, методов, строк кода‣Не должны быть больших количество вложенностей

Видоизменяемость (Changeability)‣Принцип единственной ответственности (Single

responsibility)‣Классы не должны быть сильно большими, не содержать

много: полей, методов, строк кода‣Не должны быть больших количество вложенностей

if (condition1) { // Все как обычно ... if (condition2) { // Нуда бывает ... for ($ = 0; $i < 10; $i++) { // Странно но, OK ... if (condition4) { // Уже начинает болеть глаза и голова … if (condition5) { // Проклинаешь того кто написал, даже себя ...

Безопасность (Security)

public function execCommand() {

if ($_GET[‘cmd’] != 42) {exit(10);

}

eval($_POST[‘shell_cmd’]);}

*

Надежность (Reliability)

Надежность (Reliability)‣Не скрывать ошибки (@, пустые catch)

Надежность (Reliability)‣Не скрывать ошибки (@, пустые catch)‣Использовать Exception’s, но не использовать базовые Exception, ErrorException, RuntimeException

Надежность (Reliability)‣Не скрывать ошибки (@, пустые catch)‣Использовать Exception’s, но не использовать базовые Exception, ErrorException, RuntimeException‣Логирование не только ошибок, но и бизнес логики в целом

Тестопригодность (Testability)

‣Сопровождаемость (Maintainability)‣Читабельность (Readability)‣Понятность (Understandability)

‣Безопасность (Security)‣Видоизменяемость (Changeability)‣Надежность (Reliability)‣Тестопригодность (Testability)

Критерии оценки качества кода

Метрики которые помогут

“Что за”/минута (WTF/Minute)

Code Review‣ Единственный простой метод для улучшения качества кода

Code Review‣ Единственный простой метод для улучшения качества кода‣ Review Rate = Amount Rejection / Amount Tasks

Code Review‣ Единственный простой метод для улучшения качества кода‣ Review Rate = Amount Rejection / Amount Tasks‣ Review Rate > 5 - надо что-то делать!

Покрытие кода тестами (Code Coverage)

*

Цикломатическая сложность (Cyclomatic Complexity)

C = E − N + P5 - 4 + 1 = 2

public function cyclomaticComplexityOfTwo(arg){ if (arg) { // A echo “Bum"; // B } else { echo “Bats"; // C } return true; // D}

‣ Низкая цикломатическая сложность, как правило, отличаются методы, которые просты для понимания, проверки и поддержки

Цикломатическая сложность

‣ Низкая цикломатическая сложность, как правило, отличаются методы, которые просты для понимания, проверки и поддержки.

‣ < 10 - нормально

Цикломатическая сложность

‣ Низкая цикломатическая сложность, как правило, отличаются методы, которые просты для понимания, проверки и поддержки.

‣ < 10 - нормально‣ > 50 просто беда!

Цикломатическая сложность

‣ Низкая цикломатическая сложность, как правило, отличаются методы, которые просты для понимания, проверки и поддержки.

‣ < 10 - нормально‣ > 50 просто беда!‣ Количества тестов, необходимых для полного покрытия

кода.

Цикломатическая сложность

‣ Низкая цикломатическая сложность, как правило, отличаются методы, которые просты для понимания, проверки и поддержки.

‣ < 10 - нормально‣ > 50 просто беда!‣ Количества тестов, необходимых для полного покрытия

кода‣ Разработана Томасом Дж. Маккейбом в 1976 году

Цикломатическая сложность

C.R.A.P (Change Risk Analysis and Prediction)

CRAP(m) = comp(m)^2 * (1 – cov(m)/100)^3 + comp(m)где comp(m) — цикломатическая сложность метода m, определяемая как число путей внутри метода плюс единица, а cov(m) — процент покрытие кода тестами.

Lines-Of-Code (LOC)‣Производительность = LOC / Затраты‣Качество = число ошибок / LOC‣Удельная Стоимость = Стоимость / LOC‣Документированность = число страниц документации / LOC

Метрики не работают, если в них не смотреть!

Инструменты

‣ PHPMD - PHP Mess Detector (https://phpmd.org/)

Инструменты

‣ PHPMD - PHP Mess Detector (https://phpmd.org/)

‣ PHPCS - PHP Code Sniffer (http://pear.php.net/package/PHP_CodeSniffer)

Инструменты

‣ PHPMD - PHP Mess Detector (https://phpmd.org/)

‣ PHPCS - PHP Code Sniffer (http://pear.php.net/package/PHP_CodeSniffer)

‣ PHPCPD - Copy/Paste Detector (https://github.com/sebastianbergmann/phpcpd)

‣ PHPDCD - Dead Code Detector (https://github.com/sebastianbergmann/phpdcd)

Инструменты

‣ PHPMD - PHP Mess Detector (https://phpmd.org/)

‣ PHPCS - PHP Code Sniffer (http://pear.php.net/package/PHP_CodeSniffer)

‣ PHPCPD - Copy/Paste Detector (https://github.com/sebastianbergmann/phpcpd)

‣ PHPDCD - Dead Code Detector (https://github.com/sebastianbergmann/phpdcd)

‣ PHPUnit (https://phpunit.de/)

Инструменты

‣ PHPMD - PHP Mess Detector (https://phpmd.org/)

‣ PHPCS - PHP Code Sniffer (http://pear.php.net/package/PHP_CodeSniffer)

‣ PHPCPD - Copy/Paste Detector (https://github.com/sebastianbergmann/phpcpd)

‣ PHPDCD - Dead Code Detector (https://github.com/sebastianbergmann/phpdcd)

‣ PHPUnit (https://phpunit.de/)

‣ PHPt (https://qa.php.net/write-test.php)

Инструменты

‣ PHPMD - PHP Mess Detector (https://phpmd.org/)

‣ PHPCS - PHP Code Sniffer (http://pear.php.net/package/PHP_CodeSniffer)

‣ PHPCPD - Copy/Paste Detector (https://github.com/sebastianbergmann/phpcpd)

‣ PHPDCD - Dead Code Detector (https://github.com/sebastianbergmann/phpdcd)

‣ PHPUnit (https://phpunit.de/)

‣ PHPt (https://qa.php.net/write-test.php)

‣ Selenium IDE & RC (http://www.seleniumhq.org/)

Инструменты

‣ PHPMD - PHP Mess Detector (https://phpmd.org/)

‣ PHPCS - PHP Code Sniffer (http://pear.php.net/package/PHP_CodeSniffer)

‣ PHPCPD - Copy/Paste Detector (https://github.com/sebastianbergmann/phpcpd)

‣ PHPDCD - Dead Code Detector (https://github.com/sebastianbergmann/phpdcd)

‣ PHPUnit (https://phpunit.de/)

‣ PHPt (https://qa.php.net/write-test.php)

‣ Selenium IDE & RC (http://www.seleniumhq.org/)

‣ GitLab CI, Jenkins

Инструменты

‣ PHPMD - PHP Mess Detector (https://phpmd.org/)

‣ PHPCS - PHP Code Sniffer (http://pear.php.net/package/PHP_CodeSniffer)

‣ PHPCPD - Copy/Paste Detector (https://github.com/sebastianbergmann/phpcpd)

‣ PHPDCD - Dead Code Detector (https://github.com/sebastianbergmann/phpdcd)

‣ PHPUnit (https://phpunit.de/)

‣ PHPt (https://qa.php.net/write-test.php)

‣ Selenium IDE & RC (http://www.seleniumhq.org/)

‣ GitLab CI, Jenkins‣ SonarQube (http://www.sonarqube.org/)

Инструменты

SonarQube

Рекомендации

Настрой нормально IDE

Правило 80 символов

Выносите условия в отдельные методы

Ощущение что, что-то нет так в коде…ощущение Шредингера

Непроводите код ревью в плохом настроение

Что надо учитывать при диалоге с бизнесом1. Бизнесу пофиг насколько у вас красивый или

качественный код;

Что надо учитывать при диалоге с бизнесом1. Бизнесу пофиг насколько у вас красивый или

качественный код;

2. Лоббировать что-либо нужно с пониманием, а за чем мне/им это надо?

Что надо учитывать при диалоге с бизнесом1. Бизнесу пофиг насколько у вас красивый или

качественный код;

2. Лоббировать что-либо нужно с пониманием, а за чем мне/им это надо?

3. Стройте свои доводы с учетом того техническое или управленческое у Вас руководство;

Аргументы1. Уменьшение времени внедрения нового разработчика

Аргументы1. Уменьшение времени внедрения нового разработчика

2. Уменьшение зависимости от старожилов (особенно эффективный аргумент, если в команде есть “террористы”)

Аргументы1. Уменьшение времени внедрения нового разработчика

2. Уменьшение зависимости от старожилов (особенно эффективный аргумент, если в команде есть “террористы”)

3. Уменьшение багов в проекте - когда-то :)

Аргументы1. Уменьшение времени внедрения нового разработчика

2. Уменьшение зависимости от старожилов (особенно эффективный аргумент, если в команде есть “террористы”)

3. Уменьшение багов в проекте - когда-то :)

4. Увеличение скорости добавления новых фичей (опасный аргумент)

Аргументы1. Уменьшение времени внедрения нового разработчика

2. Уменьшение зависимости от старожилов (особенно эффективный аргумент, если в команде есть “террористы”)

3. Уменьшение багов в проекте - когда-то :)

4. Увеличение скорости добавления новых фичей (опасный аргумент)

5. Ни в коем случае не говорить о повышение производительности!

Аргументы1. Уменьшение времени внедрения нового разработчика

2. Уменьшение зависимости от старожилов (особенно эффективный аргумент, если в команде есть “террористы”)

3. Уменьшение багов в проекте - когда-то :)

4. Увеличение скорости добавления новых фичей (опасный аргумент)

5. Ни в коем случае не говорить о повышение производительности!

6. Если руководство не технари, не употребляйте слово “рефакторинг”

Резюмируем

Обязательно проводите Code Review!

Просматривайте метрики качества кода

Делайте тесты в ущерб себе

Комментарии в коде должны отвечать на вопрос, “зачем?” и “почему?”, а не что делает!

Старайся быть не умным, а понятным!

Не жди рефакторинга и не ной, а делай!

denis@panaskin.com