Имя пользователя:

Пароль:


Список форумов ПРАКТИЧЕСКИЕ ВОПРОСЫ Работа Программирование и IT Просмотров: 721

Элегантное программирование: Сохраняйте возвращённые значения в переменных


Давим клаву за бабло
  #1
Сообщение 29 Dec 2013, 12:24
Ursego Аватара пользователя
СОЗДАТЕЛЬ ТЕМЫ
Canada, Ontario
Город: Toronto
Стаж: 11 лет 7 месяцев 25 дней
Постов: 10707
Лайкнули: 3448 раз
Карма: 33%
СССР: Днепропетровск
Пол: М
Лучше обращаться на: ты
Заход: 20 Nov 2023, 18:00

Значения, возвращённые подпрограммами и выражениями, не должны передаваться другим подпрограммам и выражениям напрямую. Вместо этого их следует сохранять в переменных, а уже эти переменные использовать дальше в коде (например, в качестве INPUT-а).

Для этого есть по крайней мере две причины:

1. Облегчение отладки - на возвращённые значения можно взглянуть до того, как они будут "похоронены" в сложных структурах данных или вообще исчезнут после сравнение (как в следующем примере: if (myVar == GetSomething())).

2. Если функция должна вызываться внутри сложного выражения, описываемый метод помогает разбить одну сложную строку на несколько простых.

Эти причины заставляют сохранять возвращённое значение всегда - даже если функция вызывается лишь один раз (если больше, тогда тем более нет вопросов). Единственное исключение из правила - логическая функция (т.е. возвращающая Boolean), которая вызывается в методе один раз и используется напрямую в выражении "if": в этом случае мы можем понять что вернулось (true or false) по тому, произошёл ли заход в "if" или программа "перескочила" через него (зайдя в "else" или пойдя дальше). Но в этом случае надо быть уверенным, что функция не вернёт null, который в данной ситуации интерпретируется как false).

Если вызываемая функция - детерминистическая (т.е. возвращает то-же значение в данном контексте) и должна быть вызвана в методе несколько раз, то у помещения возвращённого значения в переменную есть дополнительные преимущества:

1. Улучшение производительности (вызывается лишь раз), особенно если функция не особенно быстрая (например, идёт в базу данных).

2. Читающие код увидят, что функция - детерминистическая (иначе они могут подумать, что она возвращает разные значение при каждом вызове).

Этот совет особенно важен когда результат функции служит условием выхода из цикла Например:

for (i = 1; i++; i < this.FuckingSlowMethod())
{
   ...
}

Если метод возвращает 10000 то это значит, что столько раз он вызывается! Решение вам хорошо известно:

int cnt = this.FuckingSlowMethod();
for (i = 1; i++; i < cnt)
{
   ...
}

Но будьте осторожны - если цикл меняет что-то, что может повлиять на OUTPUT этого метода, он - не детерминистический!

Ещё один пример, показывающий преимущества обсуждаемого подхода (одна сложная строка разбивается на несколько простых - в принципе та-же философия, что и в рефакторинге методов):

*** Не рекомендуется: ***

countryName = this.GetCountryNameByCountryId(this.GetCountryIdByCityId(this.GetCityId(rowNum)));

*** Рекомендуется: ***

cityId = this.GetCityId(rowNum);
countryId = this.GetCountryIdByCityId(cityId);
countryName = this.GetCountryNameByCountryId(countryId);

Как видите, если переменная countryName в результате не была заполнена как ожидалось, то мы можем легко увидеть в дебаггере (без нескольких STEP IN / STEP OUT) какая именно из функций не справилась со своей задачей.

Этот пост лайкнул(и) Cth

Вам есть что сказать по этой теме? Зарегистрируйтесь, и сможете оставлять комментарии
cron