Как найти вонючие части вашего кода [Часть XXVI]
21 ноября 2022 г.Запахи кода — это классика.
Это пахнет, потому что, вероятно, есть много случаев, когда его можно отредактировать или улучшить.
n Большинство этих запахов являются лишь намеками на то, что что-то может быть не так. Следовательно, их не обязательно исправлять как таковые… (Тем не менее, вы должны изучить это.)
Пахнет предыдущим кодом
- Часть I< /а>
- Часть II< /а>
- Часть III< /а>
- Часть IV< /а>
- Часть V< /а>
- Часть VI< /а>
- Часть VII< /а>
- Часть VIII< /а>
- Часть IX< /а>
- Часть X< /а>
- Часть XI< /а>
- Часть XII
- Часть XIII
- Часть XIV
- Часть XV
- Часть XVI
- Часть XVII
- Часть XVIII
- Часть XIX
- Часть XX
- Часть XXI
- Часть XXII
- Часть XXIII
- Часть XXIV
- Часть XXV
Продолжим...
Code Smell 126 — Поддельный нулевой объект
Нулевые объекты — отличная альтернатива "Ошибке на миллиард долларов". Иногда они нам не нужны
<цитата>
TL;DR: не злоупотребляйте шаблонами. Даже NullObject.
.Проблемы
- Пустые классы
- Загрязнение пространства имен
- Повторяющееся поведение
Решения
- Создайте пустые объекты, создающие экземпляры классов реальных объектов.
Контекст
Шаблон Null Object — отличная альтернатива NULL. и IF (оба кодовые запахи).
Структура шаблона говорит нам о необходимости создания иерархии.
Это не обязательно; нам нужно, чтобы естественные объекты были полиморфны нулевым объектам.
Наследование — неправильный способ достижения полиморфизма.
Простым решением является создание реального объекта, который ведет себя как нулевой.
Например: "0" – это нулевой объект чисел.
“(или "") – это пустой объект String
Пустая коллекция — это нулевой объект коллекции.
Пример кода
Неверно
abstract class Address {
public abstract String getCity();
public abstract String getState();
public abstract String getZipCode();
}
// Using inheritance for null objects is a mistake
// We should use interfaces (when available)
public class NullAddress extends Address {
public NullAddress() { }
public String getCity() {
return Constants.EMPTY_STRING;
}
public String getState() {
return Constants.EMPTY_STRING;
}
public String getZipCode() {
return Constants.EMPTY_STRING;
}
}
public class RealAddress extends Address {
private String zipCode;
private String city;
private String state;
public RealAddress(String city, String state, String zipCode) {
this.city = city;
this.state = state;
this.zipCode = zipCode;
}
public String getZipCode() {
return zipCode;
}
public String getCity() {
return city;
}
public String getState() {
return state;
}
}
Правильно
// There are just "addresses"
public class Address {
private String zipCode;
private String city;
private String state;
public Address(String city, String state, String zipCode) {
// Looks anemic :(
this.city = city;
this.state = state;
this.zipCode = zipCode;
}
public String zipCode() {
return zipCode;
}
public String city() {
return city;
}
public String state() {
return state;
}
}
Address nullAddress = new Address(Constants.EMPTY_STRING, Constants.EMPTY_STRING, Constants.EMPTY_STRING);
// we have our null object
// we should NOT assign it to a singleton, static or global
// It behaves like a null object. That's enough
// No premature optimizations
Обнаружение
- [x] Руководство
Это семантический запах.
Теги
- Нет
Заключение
Создание классов Null Object иногда является чрезмерным.
Нам нужно создать настоящий объект.
Этот реальный объект никогда не должен быть глобальным< /a>, одиночка или < a href="https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-iv-7sc3w8n">static.
Слишком много запахов, которых нужно избегать.
Отношения
Code Smell 114 — Пустой класс< /p>
Code Smell 18 — Статические функции
Code Smell 17 — Глобальные функции
Подробнее
Кредиты
Фото Хуана Давилы на Unsplash
Спасибо Эрнану Уилкинсону за идею курса Diseño a la Gorra (на испанском языке)
<цитата>
Все модели ошибочны, но некоторые модели полезны
Джордж Бокс
Великие цитаты о разработке программного обеспечения
Code Smell 127 — Изменяемые константы
Вы объявляете что-то константой. Но вы можете изменить его.
<цитата>TL;DR: используйте неизменяемые константы
Проблемы
- Изменяемость ли>
- Нарушение принципа наименьшего удивления
- Связь
Решения
- Применить изменяемость< /li>
- Избегайте констант. Их трудно имитировать в тестах.
Контекст
Мы научились объявлять константы на первом курсе компьютерного программирования.
Как всегда, неважно, постоянно ли что-то.
Важно, чтобы он не мутировал.
Пример кода
Неверно
const DISCOUNT_PLATINUM = 0.1;
const DISCOUNT_GOLD = 0.05;
const DISCOUNT_SILVER = 0.02;
// Since variables are constants we cannot reassign them
const DISCOUNT_PLATINUM = 0.05; // Error
// We can group them
const ALL_CONSTANTS = {
DISCOUNT: {
PLATINUM = 0.1;
GOLD = 0.04;
SILVER = 0.02;
},
};
const ALL_CONSTANTS = 3.14; // Error
ALL_CONSTANTS.DISCOUNT.PLATINUM = 0.08; // NOT AN ERROR. WTF!
const ALL_CONSTANTS = Object.freeze({
DISCOUNT:
PLATINUM = 0.1;
GOLD = 0.05;
SILVER = 0.02;
});
const ALL_CONSTANTS = 3.14; // Error
ALL_CONSTANTS.DISCOUNT.PLATINUM = 0.12; // NOT AN ERROR. WTF!
Правильно
export const ALL_CONSTANTS = Object.freeze({
DISCOUNT: Object.freeze({
PLATINUM = 0.1;
GOLD = 0.05;
SILVER = 0.02;
}),
});
const ALL_CONSTANTS = 3.14; // Error
ALL_CONSTANTS.DISCOUNT.PLATINUM = 0.12; // ERROR
// Code works, but it is coupled and we cannot test it
Class TaxesProvider {
applyPlatinum(product);
}
// Now we can couple to a interface (the protocol of taxes provider)
// Since class has no setters it is constant an immutable
// And we can replace it on tests
Обнаружение
- [x] Полуавтоматический
Мы можем выполнить мутационное тестирование, чтобы найти измененные значения.
Теги
- Константы
Заключение
Важна изменчивость.
Нам нужно обеспечить его соблюдение с помощью правильных инструментов.
Отношения
Code Smell 86 — Изменяемые массивы констант
Code Smell 107 — Повторное использование переменных< /p>
Code Smell 02 — Константы и магические числа< /а>
Подробнее
Кредиты
На создание этого запаха вдохновил это
Фото Сангхарша Лохакаре на Unsplash
<цитата>
Вы начинаете копаться в коде. Чем больше копаешь, тем больше вещей находишь. В конце концов, вы закопаетесь в яму, из которой не сможете выбраться. Чтобы не копать себе могилу, рефакторинг нужно проводить систематически.
Эрик Гамма
Великие цитаты о разработке программного обеспечения
Code Smell 128 – кодирование не на английском языке
Использование вашего местного языка — отличная идея, потому что это упрощает присвоение доменных имен. Нет
<цитата>TL;DR: придерживайтесь английского языка. Всегда.
Проблемы
- Полиморфизм
- Разрыв в культуре
- Смешанный код
- Синтаксические ошибки
Решения
- Писать на английском
- Переименовать понятия домена на английском языке
Контекст
Все языки программирования написаны на английском языке.
Если не считать нескольких неудачных экспериментов в 90-х годах, все современные языки используют английский для своих примитивов и фреймворков.
Если вы хотели читать или писать в средневековой Европе, вам нужно было одновременно выучить новый язык. Письмо означало латынь.
Это справедливо для современных языков программирования.
Я не являюсь носителем английского языка.
Мой код (кажется) на английском.
Пример кода
Неверно
const elements = new Set();
elements.add(1);
elements.add(1);
echo elements.size() yields 1
// This is the standard set
var moreElements = new MultiConjunto();
// We defined a multiset in Spanish
// because we are extending the domain
moreElements.agregar('hello');
moreElements.agregar('hello');
// 'agregar' is the Spanish word for 'add'
echo moreElements.size() yields 2 // Since it is a multiset
// elements and moreElements are NOT polymorphic
// I cannot exchange their implementation
Правильно
const elements = new Set();
elements.add(1);
elements.add(1);
echo elements.size() yields 1
// This is the standard set
var moreElements = new MultiSet();
// We defined a multiset in English
moreElements.add('hello');
moreElements.add('hello');
echo moreElements.size() yields 2 // Since it is a multiset
// elements and moreElements are polymorphic
// I can exchange their implementation anytime
Обнаружение
- [x] Автоматически
Большинство IDE и линтеров имеют тезаурус.
Мы можем искать иностранные слова.
Теги
- Читаемость
Заключение
Не смешивайте неанглийские доменные слова с английскими примитивами.
Даже при сопоставлении ваших реальных объектов используйте простой английский язык.
Подробнее
Кредиты
Фото Анны Вандер Стел на Скрыть
<цитата>
Язык программирования — это инструмент, оказывающий глубокое влияние на наши мыслительные привычки.
Эдсгер Дейкстра
Великие цитаты о разработке программного обеспечения
Code Smell 129 — Структурная оптимизация
Мы любим улучшать сложность времени и пространства, угадывая нереальные сценарии
<цитата>TL;DR: ничего не оптимизируйте, пока у вас не будет тестового сценария реального использования.
Проблемы
Решения
- Покройте свои сценарии тестами.
- Создайте читаемый (и, возможно, неэффективный) код.
- Проведите реальный тест с реальными пользовательскими данными. (Нет, итерация кода 100 000 раз может оказаться нереальным вариантом использования).
- Если у вас есть убедительные данные, вам нужно улучшить обнаруженные узкие места с помощью сравнительного анализа, используя принцип Парето.
- Атакуйте 20 % самых серьезных проблем, вызывающих 80 % низкой производительности.
Контекст
В университете и на онлайн-курсах мы изучаем алгоритмы, структуры данных и сложность вычислений, прежде чем создавать хорошие правила проектирования.
Мы склонны переоценивать (возможные) проблемы с производительностью и недооценивать удобочитаемость кода и срок службы программного обеспечения.
Преждевременная оптимизация часто не приводит к решению реальных проблем.
Нам нужно хирургически улучшить наш код, когда факты говорят нам, что у нас есть реальная проблема.
Пример кода
Неверно
for (k = 0; k < 3 * 3; ++k) {
i = Math.floor(k / 3);
j = k % 3;
console.log(i + ' ' + j);
}
// This cryptic piece of code iterates a
// two dimensional array
// We don't have proofs this will be useful
// In real contexts
Правильно
for (innerIterator = 0; innerIterator < 3; innerIterator++) {
for (outerIterator = 0; outerIterator < 3; outerIterator++) {
console.log(innerIterator + ' ' + outerIterator);
}
}
// This is a readable double for-loop
// 3 is a small number
// No performance issues (by now)
// We will wait for real evidence
Обнаружение
- [x] Руководство
Это семантический запах.
Нам может показаться, что код труднее читать.
Теги
- Преждевременная оптимизация
Заключение
Нам нужно прекратить оптимизацию для машин и начать оптимизировать для людей, читающих код и сопровождающих код.
Нам нужно избегать языков программирования, предназначенных для преждевременной оптимизации, и отдавать предпочтение надежным.
Отношения
Code Smell 06 — Слишком умный программист а>
Code Smell 20 — Преждевременная оптимизация
Подробнее
Кредиты
Фото Присциллы Дю Приз на Скрыть
<цитата>
Оптимизм — это профессиональный риск программирования: обратная связь — это лечение.
Кент Бек
Великие цитаты о разработке программного обеспечения
Code Smell 130 — AddressImpl
Приятно видеть класс, реализующий интерфейсы. Лучше понимать, что он делает
<цитата>TL;DR: называйте свои классы именами реальных концепций.
Проблемы
- Биекция Ошибка
- Плохие имена
Решения
- Найдите правильное имя с помощью MAPPER
Контекст
Некоторые языки содержат идиомы и общеупотребительные выражения, мешающие правильному наименованию моделей.
Нам следует тщательно выбирать имена.
Пример кода
Неверно
public interface Address extends ChangeAware, Serializable {
/**
* Gets the street name.
*
* @return the street name
*/
String getStreet();
// ...
}
// Wrong Name - There is no concept 'AddressImpl' in real world
public class AddressImpl implements Address {
private String street;
private String houseNumber;
private City city;
// ..
}
Правильно
// Simple
public class Address {
private String street;
private String houseNumber;
private City city;
// ..
}
// OR
// Both are real-world names
public class Address implements ContactLocation {
private String street;
private String houseNumber;
private City city;
// ..
}
Обнаружение
- [x] Автоматически
Поскольку это запах именования.
Мы можем искать с помощью регулярных выражений и переименовывать эти понятия.
Теги
- Именование
Заключение
Нам следует выбирать имена классов в соответствии с существенной биекцией, а не следовать случайной реализации.
Не называйте «I» в своих интерфейсах.
Отношения
Code Smell 65 — Переменные, названные в честь типов
Code Smell 38 — Абстрактные имена
Подробнее
Кредиты
<цитата>
Закодированные имена редко произносятся и их легко пропустить.
Роберт С. Мартин
Великие цитаты о разработке программного обеспечения
И это пока все…
В следующей статье мы расскажем еще о пяти запахах кода!
Оригинал