Как найти вонючие части вашего кода [Часть XXVIII]
19 декабря 2022 г.Запахи кода — это классика.
Это пахнет, потому что, вероятно, есть много случаев, когда его можно отредактировать или улучшить.
n Большинство этих запахов являются лишь намеками на то, что что-то может быть не так. Следовательно, их не обязательно исправлять как таковые… (Тем не менее, вы должны изучить это.)
Пахнет предыдущим кодом
Вы можете найти все предыдущие запахи кода (Часть I - XXVii) здесь.
Продолжим...
Code Smell 136 — Классы только с одним подклассом
- Обобщать и предвидеть будущее – это хорошо (опять же).
TL;DR: не обобщайте слишком много
# проблем * Спекулятивный дизайн * Сложность * Чрезмерная разработка
# решения
- Удаляйте абстрактный класс, пока не получите больше примеров.
# Контекст
В прошлом программисты просили нас проектировать с учетом изменений.
Сегодня мы продолжаем следовать научному методу.
Всякий раз, когда мы находим дублирование, мы удаляем его.
Не раньше.
Не с интерфейсами, не с классами.
# Пример кода
## Неправильно
```питон Босс класса(объект): def инициализация(я, имя): self.name = имя
класс GoodBoss(Босс): def инициализация(я, имя): super().инициализация(имя)
# На самом деле это очень классный пример # Боссы должны быть неизменны, но могут менять свое настроение # с конструктивным отзывом ```
## справа
```питон Босс класса(объект): def инициализация(я, имя): self.name = имя
# Боссы конкретны и могут менять настроение ```
# Обнаружение - [x] Автоматически
Это очень просто для наших линтеров, поскольку они могут отследить эту ошибку во время компиляции.
# исключений
Некоторые фреймворки создают абстрактный класс в качестве заполнителя для построения наших моделей на их основе.
Субклассификация никогда не должна быть нашим первым вариантом.
Более элегантным решением было бы объявить интерфейс< /a> так как он менее связан.
# тегов * Над дизайном
# отношения
Code Smell 114 — Пустой класс< /p>
Code Smell 11 — Подклассификация повторного использования кода< /а>
Code Smell 43 — Подклассы бетонных классов а>
Code Smell 92 — Имена изолированных подклассов
Code Smell 135 — Интерфейсы всего с одной реализацией а>
# Заключение
Нужно ждать абстракций, а не быть творческими и спекулятивными.
# кредитов
Фото Бенджамина Дэвиса на Unsplash р>
<цитата>
Написание класса без его контракта было бы похоже на создание инженерного компонента (электрическая схема, микросхема СБИС (очень большая интеграция), мост, двигатель...) без спецификации. Ни один профессиональный инженер даже не подумал бы об этой идее.
Бертран Мейер
Великие цитаты о разработке программного обеспечения
Code Smell 137 — Слишком глубокое дерево наследования
Еще один симптом повторного использования плохого кода
<цитата>TL;DR: предпочитайте композицию наследованию
Проблемы
- Соединение
- Повторное использование подклассов
- Плохая согласованность
- Хрупкие базовые классы
- Переопределение метода
- Замена Лисков
Решения
- Разбивайте предложения и составляйте их.
Контекст
В старых документах рекомендовалось использовать классы в качестве специализации для повторного использования кода.
Мы узнали, что композиция — это более эффективный и расширяемый способ поделиться поведением.
Пример кода
Неверно
classdef Animalia
end
classdef Chordata < Animalia
end
classdef Mammalia < Chordata
end
classdef Perissodactyla < Mammalia
end
classdef Equidae < Perissodactyla
end
classdef Equus < Equidae
//Equus behaviour
end
classdef EFerus < Equus
//EFerus behaviour
end
classdef EFCaballus < EFerus
//EFCaballus behaviour
end
Правильно
classdef Horse
methods
// Horse behavior
end
end
Обнаружение
- [x] Автоматически
Многие линтеры сообщают об глубине дерева наследования (DIT).
Теги
- Иерархии
Заключение
Заботьтесь о своих иерархиях и часто нарушайте их.
Отношения
Code Smell 11 — Подклассификация повторного использования кода< /а>
Code Smell 43 — Подклассы бетонных классов а>
Code Smell 58 — Проблема йо-йо
Code Smell 37 — Защищенные атрибуты
Code Smell 125 — Отношения IS-A< /а>
Code Smell 58 — Проблема йо-йо
Подробнее
Соединение: единственная проблема
<цитата>
Программные объекты (классы, модули, функции и т. д.) должны быть открыты для расширения, но закрыты для модификации.
Бертран Мейер
Великие цитаты о разработке программного обеспечения
Code Smell 138 — Зависимость пакетов
Существует отраслевая тенденция максимально избегать написания кода. Но это не бесплатно
<цитата>TL;DR: напишите свой код, если вам не нужно существующее сложное решение
Проблемы
- Соединение
- Проблемы безопасности а>
- Архитектурная сложность
- Повреждение пакетов а>
Решения
- Импортировать и внедрять простые решения
- Использовать внешние и проверенные зависимости
Контекст
В последнее время появилась тенденция полагаться на трудно отслеживаемые зависимости.
Это привносит связь в наши проекты и архитектурные решения.
Пример кода
Неверно
$ npm install --save is-odd
// https://www.npmjs.com/package/is-odd
// This package has about 500k weekly downloads
// https://github.com/i-voted-for-trump/is-odd/blob/master/index.js
module.exports = function isOdd(value) {
const n = Math.abs(value);
return (n % 2) === 1;
};
Правильно
function isOdd(value) {
const n = Math.abs(value);
return (n % 2) === 1;
};
// Just solve it inline
Обнаружение
- [x] Автоматически
Мы можем проверить наши внешние зависимости и придерживаться минимума.
Мы также можем полагаться на определенную конкретную версию, чтобы избежать взлома.
Теги
- Безопасность
Заключение
Ленивые программисты доводят повторное использование до абсурдных пределов.
Нам нужен хороший баланс между дублированием кода и сумасшедшим повторным использованием.
Как всегда, есть эмпирические правила, но нет жестких правил.
Отношения
Code Smell 94 — Слишком много импорта
Подробнее
Кредиты
Фото olieman.eth на Скрыть
Спасибо Рамиро Рела за этот запах
<цитата>
Сложность убивает. Это высасывает жизнь из разработчиков, затрудняет планирование, создание и тестирование продуктов, создает проблемы с безопасностью и вызывает разочарование у конечных пользователей и администраторов.
Рэй Оззи
Великие цитаты о разработке программного обеспечения
Code Smell 139 — Деловой код в пользовательском интерфейсе
Проверки должны быть в интерфейсе или нет?
<цитата>TL;DR: Всегда создавайте правильные объекты в своих бэкендах. Интерфейсы случайны.
Проблемы
- Проблемы безопасности
- Дублирование кода
- Тестируемость
- Расширение до API, микросервисов и т. д.
- Анемичный и изменчивый объекты
- Нарушение биекции
Решения
- Перенесите проверку на серверную часть.
Контекст
Дублирование кода является предупреждением о преждевременной оптимизации.
Создание системы с проверкой пользовательского интерфейса может привести к использованию API или внешних компонентов.
Нам нужно проверять объекты на серверной части и отправлять правильные ошибки проверки клиентским компонентам.
Пример кода
Неверно
<script type="text/javascript">
function checkForm(form)
{
if(form.username.value == "") {
alert("Error: Username cannot be blank!");
form.username.focus();
return false;
}
re = /^w+$/;
if(!re.test(form.username.value)) {
alert("Error: Username must contain only letters, numbers and underscores!");
form.username.focus();
return false;
}
if(form.pwd1.value != "" && form.pwd1.value == form.pwd2.value) {
if(form.pwd1.value.length < 8) {
alert("Error: Password must contain at least eight characters!");
form.pwd1.focus();
return false;
}
if(form.pwd1.value == form.username.value) {
alert("Error: Password must be different from Username!");
form.pwd1.focus();
return false;
}
re = /[0-9]/;
if(!re.test(form.pwd1.value)) {
alert("Error: password must contain at least one number (0-9)!");
form.pwd1.focus();
return false;
}
re = /[a-z]/;
if(!re.test(form.pwd1.value)) {
alert("Error: password must contain at least one lowercase letter (a-z)!");
form.pwd1.focus();
return false;
}
re = /[A-Z]/;
if(!re.test(form.pwd1.value)) {
alert("Error: password must contain at least one uppercase letter (A-Z)!");
form.pwd1.focus();
return false;
}
} else {
alert("Error: Please check that you've entered and confirmed your password!");
form.pwd1.focus();
return false;
}
alert("You entered a valid password: " + form.pwd1.value);
return true;
}
</script>
<form ... onsubmit="return checkForm(this);">
<p>Username: <input type="text" name="username"></p>
<p>Password: <input type="password" name="pwd1"></p>
<p>Confirm Password: <input type="password" name="pwd2"></p>
<p><input type="submit"></p>
</form>
Правильно
<script type="text/javascript">
// send a post to a backend
// backend has domain rules
// backend has test coverage and richmodels
// it is more difficult to inject code in a backend
// Validations will evolve on our backend
// Business rules and validations are shared with every consumer
// UI / REST / Tests / Microservices ... etc. etc.
// No duplicated code
function checkForm(form)
{
const url = "https://<hostname/login";
const data = {
};
const other_params = {
headers : { "content-type" : "application/json; charset=UTF-8" },
body : data,
method : "POST",
mode : "cors"
};
fetch(url, other_params)
.then(function(response) {
if (response.ok) {
return response.json();
} else {
throw new Error("Could not reach the API: " + response.statusText);
}
}).then(function(data) {
document.getElementById("message").innerHTML = data.encoded;
}).catch(function(error) {
document.getElementById("message").innerHTML = error.message;
});
return true;
}
</script>
Обнаружение
- [x] Полуавтоматический
Мы можем обнаружить некоторые шаблоны поведения в коде пользовательского интерфейса
Исключения
Если у вас есть веские доказательства серьезных узких мест в производительности, вам необходимо автоматически дублировать бизнес-логику во внешнем интерфейсе.
Вы не можете просто пропустить внутреннюю часть.
Вы не должны делать это вручную, потому что вы забудете это сделать.
Теги
- Изменчивость
Заключение
Используйте TDD.
Вы поместите всю свою бизнес-логику в объекты домена.
Отношения
Запах кода 97 - Сообщения об ошибках без сочувствия
Code Smell 01 — Анемичные модели
Code Smell 90 – Реализация событий обратного вызова
Code Smell 78 — Callback Hell< /p>
Подробнее
Кредиты
Фото Ленин Эстрада на Unsplash
<цитата>
Я думаю, что еще одним хорошим принципом является отделение представления или пользовательского интерфейса (UI) от реальной сущности вашего приложения. Следуя этому принципу, мне снова и снова везло с изменениями. Так что я думаю, что это хороший принцип для подражания.
Мартин Фаулер
Великие цитаты о разработке программного обеспечения
Код Запах 140 — Оценка короткого замыкания
Мы изучаем короткие схемы на наших первых курсах программирования. Нам нужно помнить, почему.
<цитата>TL;DR: будьте ленивы при оценке логических условий
Проблемы
- Побочные эффекты
- Биекция Ошибка
- Проблемы с производительностью
Решения
- Используйте короткое замыкание вместо полной оценки.
Контекст
Мы изучаем логические операции на наших 101 компьютерных курсах.
Булевы таблицы истинности отлично подходят для математики, но мы должны быть более умными в разработке программного обеспечения.
Оценка короткого замыкания помогает нам быть ленивыми и даже создавать недействительные полные оценки.
Пример кода
Неверно
<?
if (isOpen(file) & size(contents(file)) > 0)
// Full evaluation
// Will fail since we cannot retrieve contents
// from not open file
Правильно
<?
if (isOpen(file) && size(contents(file)) > 0)
// Short circuit evaluation
// If file is not open it will not get the contents
Обнаружение
- [x] Автоматически
Мы можем предупредить наших разработчиков, когда они используют полную оценку.
Исключения
Не используйте короткое замыкание в качестве альтернативы IF.
если операнды имеют побочные эффекты, это еще один запах кода.
Теги
- логическое значение
Заключение
Большинство языков программирования поддерживают короткие замыкания.
У многих из них это единственный вариант.
Мы должны поощрять подобные выражения.
Отношения
Code Smell 101 — Сравнение с логическими значениями
Code Smell 69 – Big Bang (Нелепые кастинги JavaScript)
Подробнее
<цитата>
Написание класса без его контракта было бы похоже на создание инженерного компонента (электрическая схема, микросхема СБИС (очень большая интеграция), мост, двигатель...) без спецификации. Ни один профессиональный инженер даже не подумал бы об этой идее.
Бертран Мейер
Великие цитаты о разработке программного обеспечения
Следующая статья, код 5 пахнет сильнее
п
Оригинал