пятница, 12 сентября 2014 г.

Коротко. О "шаманстве" и инициализации переменных

Я сегодня "не в духе".

Поэтому - напишу ЖЁСТКО.

Люди когда же МЫ ВСЕ начнём читать исходники, а не полагать на "эти парни в Embarcadero что-то понаделали".

Вот пример про FMX.

Вот некоторые жалуются, что вот так работает:

procedure SomeLocalProcedure;
var
 l_Form : TSomeForm;
begin
 l_Form := TSomeForm.Create(nil);
 l_Form.SomeProperty := SomeData;
end;

А вот так не работает:

procedure SomeLocalProcedure;
var
 l_Form : TSomeForm;
begin
 Application.CreateForm(TSomeForm, l_Form);
 l_Form.SomeProperty := SomeData; // - тут получаем AV
end;

Заглянем в исходники FMX.

Там конечно - "трансректально":

procedure TApplication.CreateForm(const InstanceClass: TComponentClass; var Reference);
var
  Instance: TComponent;
  RegistryItems : TFormRegistryItems;
  RegItem : TFormRegistryItem;
begin
  if FRealCreateFormsCalled then
  begin
    Instance := TComponent(InstanceClass.NewInstance);
    TComponent(Reference) := Instance;
    try
      Instance.Create(Self);
      for RegItem in FCreateForms do
        if RegItem.InstanceClass = InstanceClass then
        begin
          RegItem.Instance := Instance;
          RegItem.Reference := @Reference;
        end;
    except
      TComponent(Reference) := nil;
      raise;
    end;
  end
  else
  begin
    SetLength(FCreateForms, Length(FCreateForms) + 1);
    FCreateForms[High(FCreateForms)] := TFormRegistryItem.Create;
    FCreateForms[High(FCreateForms)].InstanceClass := InstanceClass;
    FCreateForms[High(FCreateForms)].Reference := @Reference;

    // Add the form to form registry in case RegisterFormFamily will not be called
    if FFormRegistry.ContainsKey(EmptyStr) then
    begin
      RegistryItems := FFormRegistry[EmptyStr];
    end
    else begin
      RegistryItems := TFormRegistryItems.Create;
      FFormRegistry.Add(EmptyStr, RegistryItems);
    end;

    RegistryItems.Add(FCreateForms[High(FCreateForms)]);
  end;
end;

Я бы своего коллегу, за подобное - УБИЛ бы на месте.

Хотя у меня есть "пара коллег", которые такой "трансректальный" код пишут, но зато считают в шестнадцатиричной системе в УМЕ и склеивают бинарники неизвестного формата. Они - ГЕНИИ. Но их - ЕДИНИЦЫ.

На них - "не надо равняться".

Видим, что Reference - в "ветке else" - нигде не инициализируется. Что уже вызывает ВОЗГЛАС - "дебилы".

Как я это понял? Банально - "Ctrl-F".

Ну и ещё вот эта строчка:

FCreateForms[High(FCreateForms)].Reference := @Reference;

Это же - 3.14-ц... Простите за грубость...

А если Reference - это локальная переменная? Которая на СТЕКЕ!

Простите - это - 3.14-ц...

Я бы на месте Embarcadero положил бы туда Proxy, который бы делал форму при ПЕРВОМ же обращении.

Или хотя бы "кидало вменяемое исключение".

Как? Это - "тема отдельного поста".

В общем - "ребятам из Embarcadero" - двойка. С ДВУМЯ жирными минусами.

Или я - чего-то не понимаю.

Но я не об этом.

Но!

Люди "почему-то" начинают лезть "в кишки" вместо того, чтобы сделать вот что:

procedure SomeLocalProcedure;
var
 l_Form : TSomeForm;
begin
 l_Form := nil; // - ДА ДА - НЕ ЗАБЫВАЙТЕ, что там VAR
 Application.CreateForm(TSomeForm, l_Form);
 Assert(l_Form <> nil);
 Assert(l_Form Is TSomeForm);
 Assert(l_Form.InheritsFrom(TSomeForm));
 l_Form.SomeProperty := SomeData; // - тут получаем AV
end;

О чём я?

НАДО "читать исходники" и "писать Assert'ы". (Коротко. Ещё немного "рассуждений о RAII")

Это в ПЕРВУЮ очередь.

А во ВТОРУЮ очередь - ИЗБАВИТЬСЯ от ХОККЕЯ -  О термине "хоккей" и Портирование на Delphi XE4 идёт вполне успешно

И Embarcadero - ТОЖЕ.

Простите за ГРУБОСТЬ.

P.S. А "простым программерам" скажу - "ну забудьте уже про эту глупость - CreateForm" - пользуйтесь конструкторами.

Опять же. Простите за ГРУБОСТЬ.

P.P.S. Пишите Assert'ы.

3 комментария:

  1. Напишите в CodeCentral. Можно без слова ДЕБИЛЫ. Они и сами догадаются :) Хотя можно и с этим словом, все равно не оценят...
    Иначе НИКОГДА не будет исправлено. Не пишут об ошибке, значите ее вроде бы и нет.

    ОтветитьУдалить
  2. Я про "Reference - в "ветке else" - нигде не инициализируется"

    ОтветитьУдалить
    Ответы
    1. Ну так и напишите :-) Я - "все козыри дал".

      Самому - "лень". Ибо уже писал и не раз. Толку то?

      Удалить