Как найти вонючие части вашего кода [Часть XIV]
24 февраля 2022 г.Бесконечный код пахнет!
Мы видим несколько симптомов и ситуаций, которые заставляют усомниться в качестве нашего развития.
Давайте рассмотрим некоторые возможные решения.
Большинство этих запахов — просто намеки на то, что что-то может быть не так. Это не жесткие правила.
Предыдущие части
[Часть I] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-i-xqz3evd)
[Часть II] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-ii-o96s3wl4)
[Часть III] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-iii-t7h3zkv)
[Часть IV] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-iv-7sc3w8n)
[Часть V] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-v-evj3zs9)
[Часть VI] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-vi-cmj31om)
[Часть VII] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-vii-8dk31x0)
[Часть VIII] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-viii-8mn3352)
[Часть IX] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-ix-7rr33ol)
[Часть X] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-x-i7r34uj)
[Часть XI] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xi-sit35t1)
[Часть XII] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xii)
[Часть XIII] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xiii)
Давай продолжим...
Code Smell 66 - Хирургия дробовиком
Скажи это только один раз
Проблемы
- Плохие обязанности
- Дублирование кода
- Ремонтопригодность
- [Единая ответственность] (https://en.wikipedia.org/wiki/Единая ответственность_принцип) Нарушение.
- Скопированный код.
Решения
- Рефакторинг
Образец кода
Неправильно
```php
конечный класс Социальная сеть {
функция postStatus (строка $ newStatus) {
если (!$user->isLogged()) {
выдать новое исключение («Пользователь не зарегистрирован»);
функция uploadProfilePicture (изображение $ newPicture) {
если (!$user->isLogged()) {
выдать новое исключение («Пользователь не зарегистрирован»);
функция sendMessage(Пользователь $recipient, Сообщение $messageSend) {
если (!$user->isLogged()) {
выдать новое исключение («Пользователь не зарегистрирован»);
Верно
```php
конечный класс Социальная сеть {
функция postStatus (строка $ newStatus) {
$this->assertUserIsLogged();
функция uploadProfilePicture (изображение $ newPicture) {
$this->assertUserIsLogged();
функция sendMessage(Пользователь $recipient, Сообщение $messageSend) {
$this->assertUserIsLogged();
функция assertUserIsLogged() {
если (!$this->user->isLogged()) {
выдать новое исключение («Пользователь не зарегистрирован»);
//Это просто упрощение, чтобы показать запах кода
//Операции должны быть определены как объекты с предусловиями и т.д.
Обнаружение
Некоторые современные линтеры могут обнаруживать повторяющиеся шаблоны (а не только повторяющийся код), а также при выполнении проверки кода мы можем легко обнаружить эту проблему и запросить рефакторинг.
Теги
- Дублирование кода
Заключение
Добавление новой функции должно быть простым, если наша модель соответствует 1:1 реальному миру, а наши обязанности находятся в правильных местах.
Мы должны быть готовы к небольшим изменениям, затрагивающим несколько классов.
Больше информации
[Блог NDpend] (https://blog.ndepend.com/shotgun-surgery)
[Дзона] (https://dzone.com/articles/code-smell-shot-surgery)
Кредиты
Фото Уильям Истед на Unsplash
Дублирование — главный враг хорошо спроектированной системы.
Роберт Мартин
Код Запах 67 - Посредник
Давайте нарушим Закон Деметры.
Проблемы
- Ненужная косвенность
- Пустые классы
- Читабельность
Решения
- Удалите посредника.
Образец кода
Неправильно
```java
клиент открытого класса {
Адресный адрес;
общедоступный почтовый индекс zipCode () {
обратный адрес.zipCode();
Адрес публичного класса {
частный почтовый индекс zipCode;
общедоступный почтовый индекс zipCode () {
вернуть новый ZipCode('CA90210');
Приложение открытого класса {
ZipCode zipCode = client.zipCode();
Верно
```java
клиент открытого класса {
Адресный адрес;
// теперь клиент должен указать свой адрес
публичный адресс() {
обратный адрес;
Адрес публичного класса {
частный почтовый индекс zipCode;
общедоступный почтовый индекс zipCode () {
вернуть новый ZipCode('CA90210');
Приложение открытого класса {
ZipCode zipCode = client.address().zipCode();
Обнаружение
То же, что и его [противоположный запах] (https://maximilianocontieri.com/code-smell-08-long-chains-of-collaborations). Мы можем обнаружить это маленькое с помощью разбора деревьев.
Теги
- Связь
- Декларативный
- Читабельность
Заключение
Это прямо противоположно [цепочке сообщений] (https://maximilianocontieri.com/code-smell-08-long-chains-of-collaborations). Мы делаем явной цепочку сообщений.
Связи
[Code Smell 08 — Длинные цепочки сотрудничества] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-ii-o96s3wl4)
[Код Запах 114 - Пустой класс] (https://maximilianocontieri.com/code-smell-114-empty-class)
Больше информации
[Гуру рефакторинга] (https://refactoring.guru/smells/middle-man)
[Refactoring.com] (https://refactoring.com/catalog/removeMiddleMan.html)
[Вики C2] (https://wiki.c2.com/?MiddleMan)
[Википедия] (https://en.wikipedia.org/wiki/Law_of_Demeter)
Кредиты
Фото Дэн Коунселл на Unsplash
Всякий раз, когда мне нужно подумать, чтобы понять, что делает код, я спрашиваю себя, могу ли я реорганизовать код, чтобы сделать это понимание более очевидным.
Мартин Фаулер
Код Запах 68 - Добытчики
- Получение вещей широко распространено и безопасно. Но это очень плохая практика.*
Проблемы
- Именование
- Сокрытие информации
- Связь
- Нарушение инкапсуляции
- Изменчивость
- Анемичные модели
Решения
- Избегайте добытчиков
- Вместо этого используйте доменные имена
- Защитите свои решения по внедрению.
Образец кода
Неправильно
```php
<?php
конечное окно класса {
публичная ширина $;
публичная высота $;
общественные $дети;
публичная функция getWidth() {
вернуть $this->width;
публичная функция getArea() {
вернуть $this->width * $this->height;
публичная функция getChildren() {
вернуть $this->children;
Верно
```php
<?php
конечное окно класса {
частная $ ширина;
частная высота $;
частные $дети;
ширина публичной функции () {
вернуть $this->width;
область общественных функций () {
вернуть $this->height * $this->width;
общедоступная функция addChildren ($ aChild) {
// не раскрывать внутренние атрибуты
вернуть $this->children[] = $aChild;
Обнаружение
Добытчики совпадают в определенных сценариях с истинной ответственностью. Для окна будет разумно вернуть свой цвет, и оно может случайно сохранить его как цвет. поэтому метод color(), возвращающий цвет атрибута, может быть хорошим решением.
getColor() нарушает биекцию, поскольку она реализуема и не имеет реального аналога в наших сопоставителях.
Большинство линтеров могут предупредить нас, если обнаружат анемичные модели с геттерами и сеттерами.
Теги
- Сокрытие информации
Заключение
Геттеры и сеттеры - плохая устоявшаяся практика. Вместо того, чтобы сосредоточиться на поведении объекта (важно), мы отчаянно пытаемся узнать сущность объекта (случайно) и нарушаем его реализацию.
Связи
[Код Запах 28 - Сеттеры] (https://maximilianocontieri.com/code-smell-28-setters)
[Код Запах 01 - Модели с анемией] (https://maximilianocontieri.com/code-smell-01-anemic-models)
[Код Запах 64 - Неуместная близость] (https://hackernoon.com/nude-models-part-ii-getters-sjo3ua2)
Больше информации
Обнаженные модели - Часть II Геттеры
Кредиты
Фото Видар Нордли-Матисен на Unsplash
Ценность прототипа заключается в обучении, которое он дает, а не в самом коде.
Алан Купер
Code Smell 69 - Большой взрыв (JavaScript Ridiculous Castings)
Этот удобный оператор создает проблемы.
TL;DR: не смешивайте логические значения с небулевыми.
Проблемы
- Не декларативный код
- Трудно отлаживать
- Магические отливки
- Случайная сложность
Решения
- Будьте откровенны
- Не смешивайте булевы значения с небулевыми.
- [Fail Fast] (https://maximilianocontieri.com/fail-fast)
- Будьте умнее своего компилятора.
- Оставайтесь верны биекции.
[Единственный принцип проектирования программного обеспечения] (https://hackernoon.com/the-one-and-only-software-design-principle-1x983ylp)
Образец кода
Неправильно
```javascript
!true // возвращает ложь
!false // возвращает истину
Актив = Истина
!isActive // возвращает ложь
возраст = 54
!age // возвращает ложь
массив = []
!массив // возвращает ложь
obj = новый объект;
!obj // возвращает ложь
!!true // возвращает истину
!!false // возвращает ложь
!!isActive // возвращает истину
!!возраст // возвращает истину
!!массив // возвращает истину
!!obj // возвращает истину
Верно
```javascript
!true // возвращает ложь
!false // возвращает истину
Актив = Истина
!isActive // возвращает ложь
возраст = 54
!age // должно возвращать несоответствие типов (или факториал 54!)
массив = []
!array // должен возвращать несоответствие типов
obj = новый объект;
!obj // должен возвращать несоответствие типов (что означает отрицание объекта в реальном домене?)
!!true // возвращает true - это идемпотент
!!false // возвращает false - это идемпотент
!!isActive // возвращает true - это идемпотент
!!возраст // вздор
!!массив // бессмыслица
!!obj // бред
Обнаружение
Поскольку это «функция» в некоторых языках, ее будет трудно протестировать. Мы можем установить политики программирования или выбрать больше [строгих языков] (https://dev.to/tmaximini/typescript-bang-operator-considered-harmful-3hhi).
Мы должны обнаруживать использование ! !! в небулевых объектах и предупреждать наших программистов.
Теги
- Кастинг
- Принуждение
- Джаваскрипт
Заключение
Такие языки, как JavaScript, делят всю свою вселенную на значения true или false. Это решение скрывает ошибки при работе с небулевыми значениями.
Мы должны быть очень строгими и держать логические значения (и их поведение) подальше от небулевых значений.
Связи
[Code Smell 24 — Boolean Coercions] (https://maximilianocontieri.com/code-smell-24-boolean-coercions)
[Code Smell 06 — Too Clever Programmer] (https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-ii-o96s3wl4)
Больше информации
[Bennadel.com] (https://www.bennadel.com/blog/3858-the-double-bang-operator-and-a-misunderstanding-of-how-javascript-handles-truthy-falsy-values.htm)
[Mozilla] (https://developer.mozilla.org/en-US/docs/Glossary/Truthy)
Кредиты
Фото Грега Ракози на Unsplash
Легче написать неправильную программу, чем понять правильную.
Алан Джей Перлис
Code Smell 70 - Анемичные генераторы моделей
TL;DR: не создавайте анемичных объектов. Гораздо меньше с автоматическими инструментами.
Проблемы
- Анемичные объекты
- Связь с реализацией
- Сложнее отлаживать
Решения
- Создайте свои объекты вручную.
- Сосредоточьтесь на важном поведении вместо случайного хранения данных.
Образец кода
Неправильно
```php
AnemicClassCreator::create(
'Работник',
новый AutoGeneratedField('id', '$validators->getIntegerValidator()'),
новый AutoGeneratedField('имя', '$validators->getStringValidator()'),
новое AutoGeneratedField('currentlyWorking', '$validators->getBooleanValidator()')
класс Сотрудник расширяет AutoGeneratedObjectEmployee {
// У нас есть магические сеттеры и геттеры
//getId(), setId(), getName()
//Проверка не является неявной
//Класс загружается через автозагрузчик
$john = новый сотрудник;
$джон->setId(1);
$john->setName('Джон');
$john->setCurrentlyWorking(true);
$john->getName(); //возвращает 'Джон'
Верно
```php
последний класс Сотрудник {
личное $имя;
частный $рабочийстатус;
общедоступная функция __construct (строка $ имя, рабочее состояние $ рабочее состояние) {
имя публичной функции(): строка {
вернуть $это->имя;
// Это не геттер. Сотрудник обязан сообщить нам свое имя.
//У нас нет магических сеттеров и геттеров
//все методы настоящие и могут быть отлажены
//Проверки неявные
$john = новый сотрудник('Джон', новый HiredWorkingStatus());
$джон->имя(); //возвращает 'Джон'
Обнаружение
Часто анемичные модели создаются с помощью [метапрограммирования] (https://maximilianocontieri.com/laziness-i-meta-programming).
Нам нужно отслеживать эти волшебные [генераторы кода] (https://maximilianocontieri.com/lazyness-ii-code-wizards).
Теги
- Анемичный
Заключение
Мастера кода, метапрограммирование и анемичные модели — все это запахи кода.
Нам нужно избегать этих темных методов.
Необходимость писать явно код заставляет нас размышлять над каждым фрагментом данных, который мы инкапсулируем.
Связи
[Код Запах 01 - Модели с анемией] (https://maximilianocontieri.com/code-smell-01-anemic-models)
Больше информации
[Лень I — Метапрограммирование] (https://hackernoon.com/laziness-chapter-i-meta-programming-6s4l300e)
[Лень II - Мастера кода] (https://hackernoon.com/lazyness-chapter-ii-code-wizards-3i9x3xtr)
Кредиты
Фото Ленни Куне на Unsplash
Лучшие запахи легко заметить, и в большинстве случаев они приводят к действительно интересным проблемам. Классы данных (классы со всеми данными и без поведения) являются хорошими примерами этого. Вы смотрите на них и спрашиваете себя, какое поведение должно быть в этом классе.
Мартин Фаулер
И это пока все…
Следующая статья объяснит еще 5 запахов кода!
Оригинал