Здравствуйте, Aleх, Вы писали:
A>Здравствуйте, Философ, Вы писали:
Ф>>Да, говно, но не поэтому (не из-за var блока и не из-за скобочек).
Ф>>Из-за модульной парадигмы (namespace'ов приделанных сбоку, unit vars, initialization/finaliztion), из-за наследования конструкторов, и тучи других причин масштабом поменьше.
A>Имеется ввиду конкретная реализация модульной парадигмы или же модули vs заголовочные файлы?
1)
Имеется ввиду сложность предсказания потока исполнения: слишком сложно сказать в каком порядке будут исполнены секции initialization/finalization а от этого может многое зависеть, т.к. там иногда переопределяются некоторые глобальные вещи, типа функций управления памятью. В делфе процветает чёрная магия.
Даже если ты точно сможешь сказать, что секции initialization будут выполнены в том порядке, в котором указаны модули в файле проекта, то о необходимости блюсти этот порядок посторонний разработчик может и не знать. Ловить потом баги порождённые этим очень сложно долго.
2) Такая парадигма крайне плохо дружит с многопоточностью. Вот, представь:
| | code |
| | //файл проекта---------------------------------------------------
program ThisProgramDemonstrateFuckingShitFromDephiWorld;
uses MyFuckignUnit,
MyFuckignUnit2;
begin
WriteLn('Hello from delphi hell');
end.
//файл модуля---------------------------------------------------
unit MyFuckignUnit;
interface
uses SysUtils, MyFuckignUnit2, MyFuckignUnit3;
implementation
function CreateMyObjectWithThreads() :TObject;
begin
//here creating object that uses threads
end;
var o :TObject;
initialization
o := CreateMyObjectWithThreads();
finalization
FreeAndNil(o);
end.
//файл модуля---------------------------------------------------
unit MyFuckignUnit2;
interface
procedure UseModuleVar();
implementation
procedure UseModuleVar();
begin
moduleVar := false;
end;
var moduleVar :boolean;
initialization
moduleVar := true;
finalization
|
| | |
В коде показана ситуация, когда во время инициализации
модуля 1 создаётся объект, который создаёт и использует поток (пусть это будет неявно). Из потока читается булевская переменная из
модуля 2, которая там инициализируется в секции инициализации. Никакого криминала в незащищённом чтении булевской переменной нет — это атомарная операция. Косяк здесь в том, что поток может её прочитать до того, как она была выставлена в правильное значение — всё, ты попал на часы нудной отладки.
С потоками всё значительно сложнее потому, что распределение квантов времени ты предсказать не можешь: в одном случае переменная уже будет выставлена, а в другом нет.
Даже если без потоков, просто до инициализации модуля дело ещё не дошло, но уже оттуда зовутся функции ситуация оказывается подобной, хотя и проще.