Является ли Delphi «с» ключевым словом плохая практика?

Я читал плохие вещи о ключевом слове with в delphi, но, на мой взгляд, если вы не используете его. Это может сделать ваш код простым.

Я часто помещал все свои TClientDataSets и TFields в TDataModules. Так что в моих формах у меня был код вроде этого

procedure TMyForm.AddButtonClick(Sender: TObject); begin with LongNameDataModule do begin LongNameTable1.Insert; LongNameTable1_Field1.Value := "some value"; LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value; LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value; LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value; LongNameTable1.Post; end end; 

без ключевого слова я должен написать код, подобный этому

  procedure TMyForm.AddButtonClick(Sender: TObject); begin LongNameDataModule.LongNameTable1.Insert; LongNameDataModule.LongNameTable1_LongNameField1.Value := "some value"; LongNameDataModule.LongNameTable1_LongNameField2.Value := LongNameDataModule.LongNameTable2_LongNameField1.Value; LongNameDataModule.LongNameTable1_LongNameField3.Value := LongNameDataModule.LongNameTable3_LongNameField1.Value; LongNameDataModule.LongNameTable1_LongNameField4.Value := LongNameDataModule.LongNameTable4_LongNameField1.Value; LongNameDataModule.LongNameTable1.Post; end; 

Я думаю, что читать легче с помощью ключевого слова.

Не следует ли использовать ключевое слово?

    14 Solutions collect form web for “Является ли Delphi «с» ключевым словом плохая практика?”

    Самая большая опасность, связанная с такими патологическими состояниями, как «с A, B, C, D», заключается в том, что ваш код может молча изменить смысл без вашего уведомления. Рассмотрим этот пример:

     with TFoo.Create try Bar := Baz; DoSomething(); finally Free; end; 

    Вы пишете этот код, зная, что Bar является свойством TFoo, а Baz является свойством типа, содержащего метод, который имеет этот код.

    Теперь, через два года, появился какой-то доброжелательный разработчик, добавляющий свойство Baz в TFoo. Ваш код молча изменил значение. Компилятор не будет жаловаться, но код теперь сломан.

    Ключевое слово « с ключевым словом» – это отличная возможность сделать ваш код более удобочитаемым, но есть некоторые подводные камни.

    Отладка:

    При использовании кода:

     with TMyClass.Create do try Add('foo'); finally Free; end; 

    Невозможно проверить свойства этого classа, поэтому всегда объявляйте переменную и используйте ключевое слово с этим.

    Интерфейсы:

    При создании интерфейса в разделе with он живет до конца вашего метода:

     procedure MemoryHog; begin with GetInterfaceThatTakes50MBOfMemory do Whatever; ShowMessage('I''m still using 50MB of memory!'); end; 

    ясность

    При использовании classа в предложении с именами свойств или методов, которые уже существуют в пределах области действия, он может легко обмануть вас.

     with TMyForm.Create do Width := Width + 2; //which width in this with is width? 

    Конечно, если у вас есть повторяющиеся имена, вы используете свойства и методы classа, объявленного в своем заявлении (TMyForm).

    Заявление имеет свое место, но я должен согласиться с тем, что чрезмерное использование может привести к двусмысленному коду. Хорошее эмпирическое правило состоит в том, чтобы убедиться, что код «более» доступен для чтения и поддержки после добавления оператора with. Если вы чувствуете, что вам нужно добавить комментарии, чтобы объяснить код после добавления инструкции, это, вероятно, плохая идея. Если код более читабельен, как в вашем примере, используйте его.

    Кстати: это всегда был один из моих любимых шаблонов в Delphi для показа модального windows

     with TForm.Create(nil) do try ShowModal; finally Free; end 

    Я склоняюсь к тому, чтобы полностью запретить все заявления. Как было сказано ранее, это может усложнить ситуацию, и мой опыт в том, что так будет. Много раз отладчик хочет оценивать значения из-за с, и все, что часто я нахожу вложенными, что приводит к тому, что код трудно читать.

    Код Брайана кажется читабельным и приятным, но код будет короче, если вы просто указали непосредственно отправителю, и вы устраните все сомнения по поводу того компонента, который вы включили:

     TAction(Sender).Enabled := Something; 

    Если вы беспокоитесь о том, чтобы много писать, я предпочитаю временно ссылаться на объект с длинными именами:

     var t: TTable; begin t := theLongNamedDataModule.WithItsLongNamedTable; t.FieldByName(' '); end; 

    Я не могу сказать, почему печатание должно вас беспокоить. Во-первых, во-первых, программисты , а также завершение кода, копирование и запись ключей могут помочь вам стать более эффективной машинистом.

    update: просто наткнулся на длинную статью с небольшим разделением на заявления: он с ключевым словом. Самая отвратительная, опасная, ударная сила вашего языка на языке. 🙂

    Когда я впервые начал программировать на паскале (с TurboPascal!) И узнал, как я пошел, WITH казался замечательным. Как вы говорите, ответ на утомительную типизацию и идеально подходит для этих длинных записей. Поскольку Delphi прибыл, я удалял его и поощрял других отказаться от него – аккуратно подвел Verity в реестре. Помимо сокращения читаемости, есть две основные причины, по которым я бы избегал этого:

    1. Если вы используете class, тогда вам это не понадобится – только записи «кажутся» полезными.
    2. Использование отладчика для выполнения кода с объявлением с помощью Ctrl-Enter не работает.

    Тем не менее, для удобства чтения я все еще использую синтаксис:

     procedure ActionOnUpdate( Sender : TObject ) begin With Sender as TAction do Enabled := Something end; 

    Я не видел лучшей конструкции.

    Ваш пример доступа к данным по шаблону нажатием кнопки – это, на мой взгляд, плохо надуманный пример. Вся потребность в WITH уходит, если вы переместите этот код в модуль данных, где он должен быть. Затем OnClick просто вызывает LongNameDataModule.InsertStuff и нет необходимости.

    С плохое устройство, и вы должны посмотреть на свой код, чтобы понять, зачем вам это нужно. Вы, вероятно, сделали что-то не так, или могли бы сделать это лучше.

    Как упоминал Vegar, это так же аккуратно и намного читаемо, проще отлаживать и менее подвержено проблемам скрытности, чтобы использовать временную ссылку.

    До сих пор я никогда не нашел нужды в использовании. Раньше я был амбивалентен, пока не взял на себя проект, который часто использовал ум, сгибающийся дважды . Вопрос о том, должен ли первоначальный разработчик ссылаться на элементы в первом или втором, если эта двусмысленная ссылка была с недопустимым или неуклюжим кодом, мукой попытки отладки ее и ударом по эффектам расширения или модификации classов, которые используют эти мерзости просто не стоит времени.

    Явный код просто читаем. Таким образом, вы можете получить свой торт и наслаждаться едой.

     procedure TMyForm.AddButtonClick(Sender: TObject); var dm: TLongNameDataModuleType begin dm:=LongNameDataModule; dm.LongNameTable1.Insert; dm.LongNameTable1_Field1.Value := "some value"; dm.LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value; dm.LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value; dm.LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value; dm.LongNameTable1.Post; end; 

    Я твердо убежден в том, что удаляю поддержку WITH в Delphi. Ваш пример использования использования datamodule с именованными полями – это единственный экземпляр, который я мог видеть, что он работает. В противном случае лучшим аргументом против него был Крейг Стунц, который я проголосовал.

    Я просто хотел бы отметить, что со временем вы можете в конечном итоге (должны) переписать все кодировки в событиях OnClick, и ваш код также в конечном итоге переместится от именованных полей в datamodules в classы, которые обертывают эти данные, и причина использования WITH исчезнет ,

    Основная проблема с «с» заключается в том, что вы не знаете, где заканчивается ее область действия, и вы можете иметь несколько совпадений с операторами.

    Я не думаю, что вам следует избегать его использования, если ваш код доступен для чтения.

    Одно из предложений сделать его более читаемым (и менее запутанным в более длинном коде) было, если codegear добавила возможность разрешить псевдонимы с помощью, и, вероятно, разрешить несколько сеансов в одном:

     procedure TMyForm.AddButtonClick(Sender: TObject); begin with LongNameDataModule as dm, dm.LongNameTable1 as t1, dm.LongNameTable2 as t2 do begin t1.Insert; t1.FieldByName('Field1').AsString := 'some value'; t1.FieldByName('Field2').AsString := t2.FieldByName('Field2').AsString; t1.Post; dm.Connection.Commit; end end; 

    Насколько мне известно, With вполне приемлемо в случае, если вы даете. Это, безусловно, улучшает ясность кода.

    Настоящее зло – это когда у вас сразу несколько открытий.

    Кроме того, мое мнение состоит в том, что то, что вы используете с помощью on, имеет большое значение. Если это действительно другой объект, то с, вероятно, плохая идея. Тем не менее, мне не нравится иметь много переменных на одном уровне, даже если это имеет смысл – как правило, объекты данных, которые содержат весь очень сложный элемент данных, – это, как правило, весь fragment работы, для которой программа предназначена для работы. (Я не думаю, что этот случай произошел бы в приложении, у которого не было такого элемента.) Чтобы сделать мир более ясным, я часто использую записи для группировки связанных элементов. Я считаю, что почти все, с которыми я пользуюсь, предназначены для доступа к таким подгруппам.

    Ваш вопрос – отличный пример того, что «молот – это не всегда решение».

    В этом случае «с» не является вашим решением: вы должны перенести эту бизнес-логику из своей формы в свой datamodule. Не делает этого нарушает Закон Деметры, как mghie (Michael Hieke) уже прокомментировал.

    Возможно, ваш пример был просто иллюстративным, но если вы действительно используете такой код в своих проектах, это то, что вы должны сделать вместо этого:

     procedure TLongNameDataModule.AddToLongNameTable1(const NewField1Value: string); begin LongNameTable1.Insert; LongNameTable1_Field1.Value := NewField1Value; LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value; LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value; LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value; LongNameTable1.Post; end; 

    И затем назовите его из вашей формы следующим образом:

     procedure TMyForm.AddButtonClick(Sender: TObject); begin LongNameDataModule.AddToLongNameTable1('some value'); end; 

    Это эффективно избавляет вас от вашего заявления и делает ваш код более удобным для обслуживания одновременно.

    Конечно, окружающие строки Delphi с одинарными кавычками помогут скомпилировать его 😉

    Есть много превосходных ответов здесь о том, почему заявление с плохой, поэтому я постараюсь не повторять их. Я много лет использую эту инструкцию, и я очень сильно уклоняюсь от нее. Это частично из-за того, что это может быть сложно разобраться в объеме, но в последнее время я начинаю заниматься рефакторингом, и ни один из автоматических рефакторингов не работает с заявлением – и автоматическое рефакторинг является удивительным.

    Также некоторое время назад я сделал видеоролик о том, почему с заявлением плохо, это не одна из моих лучших работ, но здесь

    Используйте только временно (точно так же, как вы прокомментируете временно).

    Это помогает вам писать эскизы кода, чтобы получить что-то скомпилированное и быстро выполняемое. Если вы консолидируете решение, очистите его! Удалите, когда вы переместите код в нужное место.

    Текущая с заявлением «опасна», но ее можно существенно улучшить:

      With TForm1.Create (Nil) Do // New TForm1 instance Try LogForm ("); // That same instance as parameter to an outer method "ShowModal; // Instance.ShowModal Finally "Free; // Instance.Free End; 

    Мое предложение:

    1. Не более одного объекта / записи в заголовке.
    2. Вложенные не разрешены.
    3. Использование «для указания объекта / записи (двойные кавычки похожи на метку ditto: http://en.wikipedia.org/wiki/Ditto_mark ).
    Interesting Posts

    Разрешения IIS_IUSRS и IUSR в IIS8

    Возможно ли установить ОС на жесткий диск, который не находится на каком-либо устройстве, а затем установить его в devica и загрузиться / работать нормально?

    Java: как преобразовать HashMap в массив

    Bluetooth и WIFI для Android

    Как открыть файл EPS в GIMP 2? «Не удалось интерпретировать файл PostScript»

    Выбор строки серии pandas / dataframe по целочисленному индексу

    Может ли zipping файл сломать его?

    Методы определения местоположения для IP-адресов

    Windows 7 аудио случайно останавливается

    Как сопоставить динамический url / prj / noticeOpen / 2 в Spring MVC-controllerе

    Эквивалент chmod для изменения прав доступа к файлам в Windows

    Вывести переменную среды ENDLOCAL

    Как реализовать правильную обработку ошибок HTTP в .NET MVC 2?

    Создайте новый экземпляр classа с зависимостями, не понимая поставщика фабрики

    Имеются ли выражения Thread.sleep (0) и Thread.yield ()?

    Давайте будем гением компьютера.