Я ненавижу даже говорить это, но не совсем сложно понять, как работают правила видимости. Последний размах в победах. Всегда.
Но у людей есть эта проблема, которая в психологии называется теорией куска. Когда вам предоставляют семь вещей, которые вы можете отслеживать в своем уме, один выпадает, потому что ваш мозг имеет около 6 локальных регистров для хранения вещей. Представьте, что здесь появляется простой идентификатор Foo
:
with EXPRESSION1 do begin
with EXPRESSION2 do begin
Foo;
end;
end;
Вышеуказанное для всех намерений идентично with EXPRESSION1, EXPRESSION2 do begin...
.
Итак, давайте посмотрим, как простые правила, такие как область действия, становятся слишком сложными, чтобы им следовать через некоторое время. Давайте представим, что у нас есть следующие уровни области видимости в некотором приложении delphi, в котором мы работаем:
- Область действия каждой единицы, указанной в ваших предложениях
use
.
- Область действия раздела реализации вашего подразделения (Внутренние устройства)
- Область действия класса (идентификаторы внутри вашего текущего класса, если вы пишете метод)
- Локальная область действия процедуры или метода (раздел var в процедуре или функции).
- Первый с утверждением в примере выше.
- Второй с утверждением в примере выше.
Обновление Дэвид указал мне, что я должен упомянуть, что вместо 6 "областей" выше, у нас действительно есть 5 + x областей, где x - длина обоих ваших предложений uses
.
Теперь проблема не в том, что утверждение WITH неясно, а в том, что люди могут легко потеряться, если у вас есть 6 слоев лексической области видимости, как указано выше, и требуют, чтобы вы не только знали обо всех местах, где Foo
определено, потому что если вы думали, что в самом внутреннем операторе With определено что-то с именем Foo
, то это не слишком неприятная и трудная для поиска ошибка в вашем коде. Итак, у нас есть очень умные, очень способные люди, такие как Ник, которые говорят очень разумные вещи, такие как «никогда не используйте с». И я согласен на 99% с Ником.
Я также думаю, что вы могли бы сказать, что врага нет, это склонность разработчиков Delphi просто итеративно наращивать свои приложения в «стиле RAD», пока они не станут чудовищами. Подразделение, которое использует 200 других подразделений, является беспорядком, каждое из которых использует 200 других подразделений, и это вызовет у вас больше горя, чем необузданное злоупотребление выражениями WITH
.
WITH
не вся проблема в плохом коде, это просто самая распространенная пчела в капоте разработчика Delphi. Может быть, это привлекает больше внимания, чем чрезмерно большие предложения использования, но за всю мою карьеру предложения зависимости и адского огромного использования сделали в 100 раз больше, чтобы усложнить жизнь, чем WITH
. Поэтому я думаю, что WITH considered harmful
перевыполнено, а другие вещи, которые следует учитывать больше, рассматриваются.
Разумной альтернативой использованию с является использование однобуквенного имени переменной (я знаю, согласен и не согласен), и избегайте всей двусмысленности:
procedure NoWithPlease;
var
a:TSomething;
begin
a := Some.Long.Expression[x].That.You.Dont.Want.To.Repeat.Six.Times;
a.Foo := 'test';
a.Bar := 'test2'
end;
Это лучше, многие скажут, чем это:
procedure WithPleasure;
begin
with Some.Long.Expression[x].That.You.Dont.Want.To.Repeat.Six.Times do begin
Foo := 'test';
Bar := 'test2'
end;
end;
Теперь я слишком много укушен WITH
, чтобы отстаивать его неограниченное использование. Но я также думаю, что бывают ситуации, когда это лучше, чем делать локальные переменные. Для этого не требуется объявлять локальную переменную или определять тип выражения. Если бы у delphi было type inference
(ключевое слово auto
в C ++), то я бы сказал, что мы могли бы легко обойтись без WITH
полностью, но на самом деле это своего рода способ избежать статического создания зависимости от реализации. типов, а также возможность создавать читаемые подобласти, это может иногда облегчать чтение вашего кода, а иногда и ухудшать его, особенно когда существует более одного уровня операторов WITH
.
Однако мнения по этому вопросу различны, и, как и другие темы программирования, имеют тенденцию превращаться в дискуссию на велосипеде или, что еще хуже, в священную войну.
Мои предложенные правила:
Избегайте WITH
, если это не улучшит ваш код.В большинстве мест, которые, по вашему мнению, вам нужны, вы не используете вместо них локальную переменную.
Всегда избегайте многоуровневых WITH
операторов.