Например, чтобы сохранить процессор в Android, я могу использовать такой код:
PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();
но я думаю локальные переменные powerManager
и wakeLock
могут быть устранены
((PowerManager)getSystemService(POWER_SERVICE))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
.acquire();
похожая сцена появляется в окне предупреждений iOS, например: из
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:@"my title"
message:@"my message"
delegate:nil
cancelButtonTitle:@"ok"
otherButtonTitles:nil];
[alert show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[alertView release];
}
чтобы:
[[[UIAlertView alloc]
initWithTitle:@"my title"
message:@"my message"
delegate:nil
cancelButtonTitle:@"ok"
otherButtonTitles:nil] show];
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[alertView release];
}
Является ли хорошей практикой устранение локальной переменной, если она используется только один раз в области?
Ответы:
Код читается гораздо чаще, чем написано, поэтому вам следует пожалеть бедную душу, которой через шесть месяцев придется читать код (может быть, вы), и стремиться к самому ясному и простому для понимания коду. На мой взгляд, первая форма с локальными переменными гораздо более понятна. Я вижу три действия на трех линиях, а не три действия на одной линии.
И если вы думаете, что оптимизируете что-либо, избавляясь от локальных переменных, это не так. Современный компилятор поместит
powerManager
в регистр 1 , используется ли локальная переменная для вызоваnewWakeLock
метода. То же самое верно дляwakeLock
. Таким образом, в любом случае вы получите один и тот же скомпилированный код.1 Если между объявлением и использованием локальной переменной было много промежуточного кода, он может попасть в стек, но это второстепенная деталь.
источник
В некоторых высоко оцененных комментариях говорится об этом, но ни один из ответов, которые я видел, не сделал, поэтому я добавлю это как ответ. Ваш главный фактор в решении этой проблемы:
Debuggability
Зачастую разработчики тратят гораздо больше времени и усилий на отладку, чем на написание кода.
С локальными переменными вы можете:
Точка останова на линии, где она назначена (со всеми другими украшениями точек останова, такими как условная точка останова и т. Д.)
Изучить / посмотреть / распечатать / изменить значение локальной переменной
Поймать проблемы, которые возникают из-за бросков.
Иметь четкие трассировки стека (строка XYZ имеет одну операцию вместо 10)
Без локальных переменных все вышеперечисленные задачи либо намного сложнее, либо чрезвычайно сложны, либо просто невозможны, в зависимости от вашего отладчика.
Таким образом, следуйте печально известному принципу (напишите код так, как будто бы следующим разработчиком, который будет поддерживать его после себя, является сумасшедшим сумасшедшим, который знает, где вы живете), и допустите ошибку в сторону более легкой отладки , то есть используйте локальные переменные ,
источник
Только если это облегчает понимание кода. В ваших примерах, я думаю, это затрудняет чтение.
Исключение переменных в скомпилированном коде - тривиальная операция для любого респектабельного компилятора. Вы можете проверить вывод самостоятельно, чтобы проверить.
источник
Ваш вопрос "это хорошая практика, чтобы исключить локальную переменную, если она используется только один раз в области?" проверяет неправильные критерии. Утилита локальной переменной зависит не от того, сколько раз она используется, а от того, делает ли код более понятным. Маркировка промежуточных значений значимыми именами может улучшить ясность в ситуациях, подобных той, которую вы представляете, поскольку она разбивает код на более мелкие, более усваиваемые порции.
На мой взгляд, немодифицированный код, который вы представили, более понятен, чем ваш модифицированный код, и поэтому его следует оставить без изменений. На самом деле, я бы хотел вытащить локальную переменную из вашего модифицированного кода, чтобы улучшить ясность.
Я бы не ожидал какого-либо влияния на производительность от локальных переменных, и даже если они есть, они, вероятно, будут слишком малы, чтобы их стоило учитывать, если код не находится в очень узком цикле в критичной для скорости части программы.
источник
Может быть.
Лично я бы не хотел исключать локальные переменные, если задействована типовая трансляция. Я считаю вашу компактную версию менее читабельной, так как количество скобок начинает приближаться к ментальному пределу, который у меня есть. Он даже вводит новый набор скобок, который не был необходим в немного более подробной версии с использованием локальной переменной.
Подсветка синтаксиса, предоставляемая редактором кода, может в некоторой степени смягчить подобные проблемы.
На мой взгляд, это лучший компромисс:
Таким образом, сохраняя одну локальную переменную и исключая другую. В C # я бы использовал ключевое слово var в первой строке, поскольку тип-трансляция уже предоставляет информацию о типе.
источник
Хотя я принимаю обоснованность ответов в пользу локальных переменных, я собираюсь сыграть адвоката дьявола и представить противоположную точку зрения.
Лично я несколько против использования локальных переменных исключительно для целей документации, хотя сама эта причина указывает на то, что практика имеет значение: локальные переменные эффективно псевдодокументируют код.
В вашем случае основной проблемой является отступ, а не отсутствие переменных. Вы можете (и должны) отформатировать код следующим образом:
Сравните это с версией с локальными переменными:
С локальными переменными: имена добавляют некоторую информацию читателю, и типы четко определены, но реальные вызовы методов менее заметны и (на мой взгляд) не читаются так четко.
Без использования локальных переменных: это более кратко и вызовы методов более заметны, но вы можете запросить дополнительную информацию о том, что возвращается. Однако некоторые IDE могут показать вам это.
Еще три комментария:
По моему мнению, добавление кода, который не имеет функционального использования, может иногда сбивать с толку, поскольку читатель должен понимать, что он действительно не имеет функционального использования и просто предназначен для «документации». Например, если бы этот метод был длиной в 100 строк, не было бы очевидно, что локальные переменные (и, следовательно, результат вызова метода) не требовались в какой-то более поздний момент, если вы не прочитали весь метод.
Добавление локальных переменных означает, что вы должны указать их типы, и это приводит к зависимости в коде, которой иначе не было бы. Если тип возвращаемого значения методов изменился тривиально (например, он был переименован), вам пришлось бы обновить свой код, тогда как без локальных переменных вы бы этого не сделали.
Отладка может быть проще с локальными переменными, если ваш отладчик не показывает значения, возвращаемые методами. Но исправление для этого состоит в том, чтобы исправить недостатки в отладчиках, а не изменить код.
источник
with
заявлений. Это были бы нормальные соглашения о форматировании в Java.Здесь есть напряжение мотивации. Введение временных переменных может облегчить чтение кода. Но они также могут предотвратить и затруднить просмотр других возможных рефакторингов, таких как « Извлечь метод» и « Заменить темп на запрос» . Эти последние типы рефакторингов, когда это уместно, часто дают гораздо большие преимущества, чем временная переменная.
О мотивах этих последних рефакторингов Фаулер пишет :
Так что, да, используйте временные файлы, если они делают код более читабельным, особенно если это местная норма для вас и вашей команды. Но имейте в виду, что иногда это может затруднить обнаружение более крупных альтернативных улучшений. Если вы можете развить в себе способность ощущать, когда стоит обойтись без таких темпов, и чувствовать себя более комфортно при этом, то это, вероятно, хорошая вещь.
Я лично избегал читать книгу Фаулера «Рефакторинг» в течение десяти лет, потому что представлял, что по таким относительно простым темам нечего сказать. Я был совершенно неправ. Когда я в конце концов прочитал это, это изменило мою повседневную практику кодирования, к лучшему.
источник
Что ж, это хорошая идея, чтобы исключить локальные переменные, если вы можете сделать код более читабельным. Ваш длинный однострочный текст не читается, но тогда он следует довольно многословному ОО-стилю. Если бы вы могли уменьшить его до чего-то вроде
тогда я бы сказал, что это была бы хорошая идея. Возможно, вы можете ввести вспомогательные методы, чтобы свести это к чему-то похожему; если код, подобный этому, появляется несколько раз, он вполне может быть оправдан.
источник
Давайте рассмотрим закон Деметры здесь. В статье Википедии о LoD говорится следующее:
Одним из последствий следования этому Закону является то, что вам следует избегать вызова методов объектов, возвращаемых другими методами, в длинной пунктирной строке, как показано во втором примере выше:
Действительно трудно понять, что это делает. Чтобы понять это, вы должны понять, что делает каждая процедура, а затем расшифровать, какая функция вызывается для какого объекта. Первый блок кода
ясно показывает, что вы пытаетесь сделать - вы получаете объект PowerManager, получаете объект WakeLock из PowerManager, а затем получаете wakeLock. Вышеизложенное следует правилу № 3 в LoD - вы создаете экземпляры этих объектов в своем коде и, следовательно, можете использовать их, чтобы выполнить то, что вам нужно.
Возможно, еще один способ задуматься - помнить, что при создании программного обеспечения вы должны писать для ясности, а не для краткости. 90% всей разработки программного обеспечения - обслуживание. Никогда не пишите кусок кода, который вы не будете рады поддерживать.
Удачи.
источник
Стоит отметить, что код читается часто, на разных «глубинах». Этот код:
легко "снять". Это 3 заявления. Сначала мы придумали
PowerManager
. Тогда мы придумалиWakeLock
. Тогда мы . Я могу легко это увидеть, просто посмотрев на начало каждой строки; простые присвоения переменных действительно легко частично распознаются как «Type varName = ...» и просто мысленно скользят по «...». Точно так же последнее утверждение, очевидно, не является формой присвоения, но оно включает только два имени, поэтому «основная суть» становится очевидной сразу. Часто это все, что мне нужно знать, если я просто пытаюсь ответить «что делает этот код?» на высоком уровне.acquire
wakeLock
Если я гоняюсь за тонкой ошибкой, которая, как мне кажется, здесь, то, очевидно, мне нужно будет рассмотреть это более подробно и на самом деле будет помнить "...". Но отдельная структура операторов все еще помогает мне делать это по одному утверждению за раз (особенно полезно, если мне нужно глубже погрузиться в реализацию вещей, вызываемых в каждом утверждении; когда я возвращаюсь, я полностью понимаю «одну единицу») и затем можно перейти к следующему утверждению).
Теперь это все одно утверждение. Структура верхнего уровня не так проста для чтения; в исходной версии OP, без разрывов строк и отступов для визуальной передачи любой структуры, мне пришлось бы считать скобки, чтобы декодировать ее в последовательность из 3 шагов. Если некоторые выражения, состоящие из нескольких частей, вложены друг в друга, а не организованы как цепочка вызовов методов, то все равно это может выглядеть примерно так, поэтому я должен быть осторожен с этим, не считая скобок. И если я доверяю отступу и просто проскакиваю вперед до последней вещи как предполагаемой точки всего этого, что
.acquire()
мне скажет само по себе?Однако иногда это может быть тем, что вы хотите. Если я применю ваше преобразование на полпути и написал:
Теперь это говорит о быстром снятии "получить
WakeLock
, тогдаacquire
это". Еще проще, чем в первой версии. Сразу видно, что приобретаемая вещь являетсяWakeLock
. Если получение -PowerManager
это просто деталь, которая довольно незначительна с точки зрения этого кода, ноwakeLock
важна, тогда это может фактически помочь похоронитьPowerManager
материал, поэтому естественно просмотреть его, если вы просто пытаетесь быстро получить Идея того, что делает этот код. И не называя сообщается , что он будет использоваться только один раз, а иногда это что важно (если остальная часть области очень длинная, мне придется прочитать все это, чтобы узнать, будет ли она когда-либо использоваться снова; хотя использование явных вложенных областей может быть другим способом решения этой проблемы, если ваш язык их поддерживает).Что наводит на мысль, что все зависит от контекста и того, что вы хотите общаться. Как и в случае написания прозы на естественном языке, всегда есть много способов написания данного фрагмента кода, которые в основном эквивалентны с точки зрения содержания информации. Как и в случае написания прозы на естественном языке, выбор между ними, как правило, не должен заключаться в применении механистических правил, таких как «исключить любую локальную переменную, которая встречается только один раз». Скорее каквы решите записать свой код, чтобы подчеркнуть некоторые вещи и уменьшить акцент на других. Вы должны стремиться делать этот выбор осознанно (в том числе время от времени писать менее читаемый код по техническим причинам), основываясь на том, что вы действительно хотите подчеркнуть. Особенно подумайте о том, что послужит читателям, которым просто нужно «понять суть» вашего кода (на разных уровнях), поскольку это будет происходить гораздо чаще, чем очень внимательное чтение выражения за выражением.
источник
getSystemService(POWER_SERVICE)
получает менеджер по мощности..newWakeLock
получает замок от пробуждения.acquire
приобретает это. Хорошо, я не знаю всех типов, но я могу узнать это в IDE, если мне нужно.return
как можно быстрее из методов, по той же причине.Это даже антипаттерн с собственным именем: Train Wreck . Уже было указано несколько причин, чтобы избежать замены:
Подумайте, знает ли этот метод слишком много из других объектов. Цепочка методов - это альтернатива, которая может помочь вам уменьшить связь.
Также помните, что ссылки на объекты действительно дешевы.
источник
Поставленный вопрос: «Должны ли мы исключить локальные переменные, если сможем»?
Нет, вы не должны устранять только потому, что вы можете.
Вы должны следовать правилам кодирования в вашем магазине.
По большей части локальные переменные облегчают чтение и отладку кода.
Мне нравится то, что ты сделал с
PowerManager powerManager
. Для меня строчная буква класса означает, что это всего лишь одноразовое использование.Когда вы не должны это делать, если переменная будет содержать дорогостоящие ресурсы. Многие языки имеют синтаксис для локальной переменной, которую необходимо очистить / освободить. В C # это используется.
источник
using(new SQLConnection()) { /* ... */ }
бы не было также законно (будет ли это полезно, другой вопрос :).Один важный аспект не был упомянут в других ответах: всякий раз, когда вы добавляете переменную, вы вводите изменяемое состояние. Обычно это плохо, потому что делает ваш код более сложным и, следовательно, сложным для понимания и тестирования. Конечно, чем меньше область действия переменной, тем меньше проблема.
На самом деле вы хотите не переменную, значение которой можно изменить, а временную константу. Поэтому постарайтесь выразить это в своем коде, если ваш язык позволяет это. В Java вы можете использовать
final
и в C ++ вы можете использоватьconst
. В большинстве функциональных языков это поведение по умолчанию.Это правда, что локальные переменные являются наименее вредным типом изменяемого состояния. Переменные-члены могут вызвать гораздо больше проблем, а статические переменные еще хуже. Тем не менее, я считаю важным выразить в вашем коде как можно точнее то, что он должен делать. И существует огромная разница между переменной, которую можно изменить позже, и простым именем для промежуточного результата. Так что, если ваш язык позволяет вам выразить эту разницу, просто сделайте это.
источник
getFoo()
. Если я избегу локального объявления, я в конечном итогеif(getFoo() > 10) alert(getFoo());
получу, но getFoo () может возвращать разные значения для двух разных вызовов. Я мог бы отправить предупреждение со значением, которое меньше или равно 10, что в лучшем случае сбивает с толку и вернется ко мне как дефект. Такие вещи становятся более важными с параллелизмом. Местное назначение является атомным.PowerManager
экземпляром после вызова этого метода? Позвольте мне проверить остальную часть метода .... ммм хорошо нет. И этаWakeLock
вещь, которую вы получили ... что вы делаете с этим (снова сканируя оставшуюся часть метода) ... ммм снова ничего ... хорошо, так почему они там? О да, это должно быть более читабельным ... но без них я уверен, что вы их больше не используете, поэтому мне не придется читать остальную часть метода.final
в методе необходима локальная переменная, ваш метод слишком длинный.