Написание полностью динамического ПО (18.03.2020). Печать
2020 - Март
18.03.2020 19:53
Save & Share
Лет 11 назад попались на работе исходники к программе. Все бы ничего - но в исходниках она не имела ни одной формы, ни одного элемента интерфейса. Была написала исключительно с использованием динамических объектов вместо статических - все элементы интерфейса создавались в момент старта ПО. И в ПО очень четко прослеживался комментарий, что написание ПО исключительно с помощью динамических объектов - быстро и удобно. Это оказалось жестоким троллингом.

Спустя 11 лет было принято решение разработать ПО исключительно на динамических объектах (Borland C++ Builder v.6.0). Оно имело 224 текста (Label), 64 флажковых переключателя (CheckBox), 9 фреймов (GroupBox), 32 текстовых поля (Edit). Разработка похожего ПО ранее статическими объектами (около 400 текстов, суммарно около 800 элементов) показала, естественно, рутину переименований элементов - и исправление человеческого фактора в процессе дебага. Эта рутина отнимает время.

В случае с полностью динамическими объектами ситуация развивается не по противоположному сценарию:
- когда располагаешь элементы на форме - работает зрительный анализ. Оптимизация по ряду критериев (например, минимизация размеров формы, раскраска элементов и т.д.). Общее понимание вида формы без необходимости компиляции и запуска ПО. Доступ к свойствам элементов именно графически;
- когда же создаешь элементы динамически - предугадать правильность его положения и внешнего вида затруднительно. Вместо того, чтобы мышкой подтянуть элемент куда надо - приходится исправлять это в коде. Мало того, свойства по умолчанию у статического и динамического объекта - разные. Например, динамический объект при создании не имеет значения в поле Name. Создав динамически 224 текста - они будут неотличимы друг от друга ни по каким критериям - и эти критерии нужно задавать на момент создания объекта;
- в исходном коде становится невозможно написать "Label_ADC0_Channel32_Value->" для обращения к элементу, т.к. компилятор ничего об этом объекте не знает. Обращение к динамическим объектам становится возможным только через циклический перебор всех элементов в Components[] с выделением типа через ->InheritsFrom(__classid(TCheckBox)). Даже если существует абстрактная функция GetObjectByName, она занимается именно таким перебором - и не факт, что перебор происходит быстро, и его можно использовать в задачах с реальным временем;
- элементы в Components[] требуют перетипирования вида "((TGroupBox*)Components[iTemp])" для обращения к нужному свойству;
- необходимо текстом прописывать вручную все изменяемые умолчания элементов интерфейса, вместо привычной работы в Object Inspector. В том числе Parent, положение и размеры элемента;
- все динамические элементы необходимо выгружать при выходе из ПО, чтобы не терять память. Благо, на момент выгрузки можно не отличать динамические от статических - и выгружать все подряд;
- если допущена ошибка при создании динамического элемента - сложно искать такую ошибку. Например, если по ошибке CheckBox будет присвоено несуществующее свойство (например, ParentCtl3D, свойственное GroupBox) - все скомпилируется и запустится без ошибок. Но, по факту, изменение несуществующего свойства приведет к изменению участка памяти, который в худшем случае приведет к неправильной работе этого или любого другого элемента, а в лучшем случае - ПО просто вылетит при отработке функции создания элементов.

В итоге время, затраченное только на написание функции создания элементов интерфейса, - больше в 3-4 раза времени, затраченного на создание этих элементов на форме и их ручное переименование. Требуется чрезмерная точность (такая же, как требуется при ручном переименовании статических элементов).

Стоит отметить, что именно при доработке ПО есть вероятность уменьшения временных затрат: добавление динамического фрейма между несколькими другими, с 32 текстами, - отняло около 2 минут. Общее количество кода при написании рабочих процессов ПО резко сокращается.

Из особенностей:
- динамические объекты сохраняют свой порядок в Components[], как были созданы;
- в Components[] сначала создаются динамические объекты, затем статические.

Итог: создание динамических элементов интерфейса имеет место в случаях, когда их количество 500 и выше, и их однообразность высока. А также нет привязки к реальному времени.

Философия. Верно ли определение "статический объект" как объект, созданный без NEW? Статический объект класса bool, по логике, - это static bool. Но это же совсем другое.

(добавлено 01.09.2022) Достался проект, в котором нет одинаковых элементов - но при этом они все создаются динамическими. Да, отлаживать и дорабатывать такой проект, особенно когда он чужой и большой, - это ад.
Обновлено ( 01.09.2022 17:08 )