Извлечение переменной
Проблема
У вас есть сложное для понимания выражение.
Решение
Поместите результат выражения или его части в отдельные переменные, поясняющие суть выражения.
void renderBanner() {
if ((platform.toUpperCase().indexOf("MAC") > -1) &&
(browser.toUpperCase().indexOf("IE") > -1) &&
wasInitialized() && resize > 0 )
{
// do something
}
}
void renderBanner() {
final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
final boolean isIE = browser.toUpperCase().indexOf("IE") > -1;
final boolean wasResized = resize > 0;
if (isMacOs && isIE && wasInitialized() && wasResized) {
// do something
}
}
void RenderBanner()
{
if ((platform.ToUpper().IndexOf("MAC") > -1) &&
(browser.ToUpper().IndexOf("IE") > -1) &&
wasInitialized() && resize > 0 )
{
// do something
}
}
void RenderBanner()
{
readonly bool isMacOs = platform.ToUpper().IndexOf("MAC") > -1;
readonly bool isIE = browser.ToUpper().IndexOf("IE") > -1;
readonly bool wasResized = resize > 0;
if (isMacOs && isIE && wasInitialized() && wasResized)
{
// do something
}
}
if (($platform->toUpperCase()->indexOf("MAC") > -1) &&
($browser->toUpperCase()->indexOf("IE") > -1) &&
$this->wasInitialized() && $this->resize > 0)
{
// do something
}
$isMacOs = $platform->toUpperCase()->indexOf("MAC") > -1;
$isIE = $browser->toUpperCase()->indexOf("IE") > -1;
$wasResized = $this->resize > 0;
if ($isMacOs && $isIE && $this->wasInitialized() && $wasResized) {
// do something
}
def renderBanner(self):
if (self.platform.toUpperCase().indexOf("MAC") > -1) and \
(self.browser.toUpperCase().indexOf("IE") > -1) and \
self.wasInitialized() and (self.resize > 0):
# do something
def renderBanner(self):
isMacOs = self.platform.toUpperCase().indexOf("MAC") > -1
isIE = self.browser.toUpperCase().indexOf("IE") > -1
wasResized = self.resize > 0
if isMacOs and isIE and self.wasInitialized() and wasResized:
# do something
renderBanner(): void {
if ((platform.toUpperCase().indexOf("MAC") > -1) &&
(browser.toUpperCase().indexOf("IE") > -1) &&
wasInitialized() && resize > 0 )
{
// do something
}
}
renderBanner(): void {
const isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
const isIE = browser.toUpperCase().indexOf("IE") > -1;
const wasResized = resize > 0;
if (isMacOs && isIE && wasInitialized() && wasResized) {
// do something
}
}
Причины рефакторинга
Главная мотивация этого рефакторинга — сделать более понятным сложное выражение, разбив его на промежуточные части. Это может быть:
-
Условие оператора
if()
или части оператора?:
в C-подобных языках. -
Длинное арифметическое выражение без промежуточных результатов.
-
Длинное склеивание строк.
Выделение переменной может стать первым шагом к последующему извлечению метода, если вы увидите, что выделенное выражение используется и в других местах кода.
Достоинства
- Улучшает читабельность кода. Постарайтесь дать выделенным переменным хорошие названия, которые будут отражать точно суть выражения. Так вы сделаете код читабельным и сумеете избавиться от лишних комментариев. Например,
customerTaxValue
,cityUnemploymentRate
,clientSalutationString
и т. д.
Недостатки
-
Появляются дополнительные переменные. Но этот минус компенсируется простотой чтения кода.
-
При рефакторинге выражений условных операторов помните о том, что программа обычно оптимизирует выполнение условных выражений и не выполняет дальнейшие проверки, если уже понятен финальный результат выражения. Например, если в выражении
if (a() || b()) ...
методa
вернетtrue
, то программа не станет выполнятьb
— что бы он ни вернул, результирующее выражение всё равно будет истинным.Однако, после извлечения частей этого выражения в переменные, оба метода будут вызываться постоянно, что может негативно сказаться на производительности, особенно если эти методы выполняют какую-то ресурсоёмкую работу.
Порядок рефакторинга
-
Вставьте новую строку перед интересующим вас выражением и объявите там новую переменную. Присвойте этой переменной часть сложного выражения.
-
Замените часть вынесенного выражения новой переменной.
-
Повторите это для всех сложных частей выражения.