ЛОГИКА ВЕРХНЕГО УРОВНЯ - РЕДАКЦИЯ 2

В этом году моя работа с программой dalvjaz2 практически оказалась
замороженной в связи с отсутствием интересных для меня новых мыслей по
дальнейшему развитию программы.
И вот пришла мысль набросать материал на тему "КП и Delphi". Для ясного
понимания нижеследующего текста было бы полезно ознакомиться с материалом
1-го сообщения темы "КП и Delphi" (если вкратце, то программа на Delphi
вызывает обработчики событий из DLL на КП, которая, в свою очередь,
вызывает функции нижнего уровня из DLL на Delphi).

Написание материала "КП и Delphi" подвигло меня перетащить на логику
верхнего уровня (далее по тексту - ЛВУ) процедуру вывода схемы из проекта
dal2851.
Весь материал по ЛВУ 2 выложен в файле lvu2.txt.
Здесь привожу сокращенный вариант.

Исходный текст процедуры вывода схемы приведен в файле lvu2.txt.

В файле kpdll.txt находится текст полученной процедуры ЛВУ для вывода
схемы (я редактировал kpdll.txt в обычном текстововом редакторе,
загружал в BB, компилировал и линковал, а при обнаружении ошибок
компиляции опять редактировал и повторял процедуру сборки DLL).

## Код:
```
MODULE Dal2Kpdll;

IMPORT S := SYSTEM, WinApi;

VAR
    dll: WinApi.HINSTANCE;
    ot:WinApi.BOOL;

(*==========================================*)

КОНСТАНТЫ
      ОТВЕТ_ДА         = 1;
      ОТВЕТ_НЕТ        = 0;
      НЕ_ЗАДАН         = -1;
      
      (* типы элементов схемы, см. u_ls.pas *)
      т_ЕСЛИ           = 1; 
      т_ИНЕСЛИ         = 2;
      т_ИНАЧЕ          = 3;
      т_КОНЕЦ          = 4;
      т_ЦИКЛ           = 5;
      т_КОНЕЦ_ЦИКЛА    = 6;
      т_ЗАГОЛОВОК      = 7;  (*// заголовок схемы (1-я запись схемы) *)
      т_АДРЕС          = 8;  (*// t_AD пока исключен
                               // адрес следующей ветки силуэта  N | EXIT
                               // N - номер следующей ветки
                               // EXIT - переход к ветке ВЫХОД *)
      т_ДЕЙСТВИЕ       = 9; 
      т_ВЫХОД          = 10; (* конец, возврат из процедуры *)
      

      (* типы вертикалей *)
      ГЛАВНАЯ_ВЕРТИКАЛЬ  = 1;
      ВЕРТИКАЛЬ_ДОЧЬ     = 2;
      ВЕРТИКАЛЬ_ЦИКЛА    = 3;


      (* запросы от dal2 *)

      ОСВОБОДИТЬ_БИБЛИОТЕКУ              = 1000;
      ЗАГРУЗИТЬ_БИБЛИОТЕКУ               = 1001;
      ВЫВОД_СХЕМЫ                        = 1002;

      (* команды (К*_)/ данные (Д*_)/ запросы (З*_)/ значения (В*_) *)
        (* 1. вывод_схемы *)
      К1_ПОЛУЧИТЬ_РАЗМЕРЫ_КАНВЫ             = 10001;
      К1_ВЫВОД_ТЕКСТА                       = 10002;
      К1_ОБНОВИТЬ_КАНВУ                     = 10003;
      К1_СТИЛЬ__СОЕДИНИТЕЛЬНЫЕ_ЛИНИИ        = 10004;
      К1_СТИЛЬ__ЦВЕТ_ФОНА                   = 10005;
      К1_ФОН_СХЕМЫ                          = 10006;
      К1_ВЫВОД_ЭЛЕМЕНТА                     = 10007;
      К1_ЛИНИЯ                              = 10008;
      К1_СТРЕЛКА_ЦИКЛА                      = 10009;
      Д1_ВЕРТИКАЛЬ                          = 10010;
      Д1_ИНДЕКС_ЭЛЕМЕНТА                    = 10011;
      Д1_ТЕК_ЭЛ_ВЕРТИКАЛИ                   = 10012;
      Д1_КООРД_Х1                           = 10013;
      Д1_КООРД_У1                           = 10014;
      Д1_КООРД_Х2                           = 10015;
      Д1_КООРД_У2                           = 10016;
      З1_НАЧАЛО_ПРОГРАММЫ                   = 10017;
      З1_ТЕКСТОВАЯ_ЗАПИСЬ                   = 10018;
      З1_ПОДСЧЕТ_МАКС_КООРДИНАТ             = 10019;
      З1_КОЛ_ДОП_ВЕРТИКАЛЕЙ                 = 10020;
      З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_Х                = 10021;
      З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_У                = 10022;
      З1_ШАГ_ТЕКСТА_ПО_У                    = 10023;
      В1_ИНД_1_ЭЛ_ВЕРТИКАЛИ                 = 10024;
      В1_КОЛ_ЭЛ_ВЕРТИКАЛИ                   = 10025;
      В1_ВЕРТИКАЛЬ_ЭЛЕМЕНТА                 = 10026;
      В1_ЭЛЕМЕНТ_ИСПОЛЬЗУЕТСЯ               = 10027;
      В1_РОДИТЕЛЬ_ВЕРТИКАЛИ                 = 10028;
      В1_ТИП_ДОП_ВЕРТИКАЛИ                  = 10029;
      В1_ШИРИНА_РОДИТЕЛЯ_ВЕРТИКАЛИ          = 10030; 
      В1_Х_ВЕРТИКАЛИ_РОДИТЕЛЯ               = 10031;
      В1_Х_ДОП_ВЕРТИКАЛИ                    = 10032;
      В1_У1_ДОП_ВЕРТИКАЛИ                   = 10033;
      В1_ТИП_1_ЭЛ_ДОП_ВЕРТИКАЛИ             = 10034;
      В1_ФЛАГ_ВЕТКИ_1_ЭЛ_ДОП_ВЕРТИКАЛИ      = 10035;
      В1_ШИРИНА_1_ЭЛ_ДОП_ВЕРТИКАЛИ          = 10036;
      В1_ВЕРТИКАЛЬ_ЭЛ_КОНЦА_ВЕРТИКАЛИ       = 10037;
      В1_Х_ВЕРТИКАЛИ                        = 10038;
      В1_ТЕК_У_ДОП_ВЕРТИКАЛИ                = 10039;
      В1_КОЛ_ЭЛ_ДОП_ВЕРТИКАЛИ               = 10040;
      В1_ВЫШЕ_ЗАГОЛ_ВЕТОК                   = 10041; 
      В1_ЭЛ_ЗАКРЫВАЮЩИЙ_ДОП_ВЕРТИКАЛЬ       = 10042; 
      В1_ШИРИНА_ЭЛЕМЕНТА                    = 10043;
      В1_ИНД_1_ЭЛ_ДОП_ВЕРТИКАЛИ             = 10044;
      В1_ДОП_ВЕРТИКАЛЬ                      = 10045;
      В1_У1_1_ЭЛ_ДОП_ВЕРТИКАЛИ              = 10046;

ТИП

ПРОЦЕДУРА_ПАР_ЦЕЛЫЙ = ПРОЦЕДУРА(К:ЦЕЛЫЙ);
ПРОЦЕДУРА_2ПАР_ЦЕЛЫЙ = ПРОЦЕДУРА(п1,п2:ЦЕЛЫЙ);
ПРОЦЕДУРА_4ПАР_ЦЕЛЫЙ = ПРОЦЕДУРА(п1,п2,п3,п4:ЦЕЛЫЙ);
ФУНКЦИЯ_П_ЦЕЛ_Р_ЦЕЛ = ПРОЦЕДУРА(К:ЦЕЛЫЙ): ЦЕЛЫЙ;
ФУНКЦИЯ_2П_ЦЕЛ_Р_ЦЕЛ = ПРОЦЕДУРА(п1,п2:ЦЕЛЫЙ): ЦЕЛЫЙ;
ПРОЦЕДУРА_ПАР_ЦЕЛЫЙ_УСТР  = ПРОЦЕДУРА
               (Н:ЦЕЛЫЙ; У:УКАЗАТЕЛЬ НА МАССИВ ИЗ ЛИТЕР);

ПРОЦЕДУРА_10ПАР_ЦЕЛЫЙ = ПРОЦЕДУРА(п1,п2,п3,п4,п5,
                                  п6,п7,п8,п9,п10:ЦЕЛЫЙ);


ПЕРЕМЕННЫЕ


команда:           ПРОЦЕДУРА_ПАР_ЦЕЛЫЙ;
данные:            ПРОЦЕДУРА_2ПАР_ЦЕЛЫЙ;
запрос:            ФУНКЦИЯ_П_ЦЕЛ_Р_ЦЕЛ;
значение:          ФУНКЦИЯ_2П_ЦЕЛ_Р_ЦЕЛ;
адрес_формы:       ПРОЦЕДУРА_ПАР_ЦЕЛЫЙ_УСТР;

отладка:           ПРОЦЕДУРА_10ПАР_ЦЕЛЫЙ;


ПРОЦЕДУРА ^ вывод_схемы;



PROCEDURE [ccall] _zapros* (n: INTEGER): INTEGER;
ПЕРЕМЕННЫЕ 
  ответ:ЦЕЛАЯ;
BEGIN
   ответ := -1;   

   IF (n = ЗАГРУЗИТЬ_БИБЛИОТЕКУ) THEN
      
      dll := WinApi.LoadLibrary( "pasdll.dll" );
      ASSERT( dll # 0, 100 );
      
      команда := S.VAL( ПРОЦЕДУРА_ПАР_ЦЕЛЫЙ,
             WinApi.GetProcAddress( dll, "_komanda" ) );
      данные  := S.VAL( ПРОЦЕДУРА_2ПАР_ЦЕЛЫЙ,
             WinApi.GetProcAddress( dll, "_dannye" ) );
      запрос := S.VAL(  ФУНКЦИЯ_П_ЦЕЛ_Р_ЦЕЛ,
             WinApi.GetProcAddress( dll, "_zapros" ) );
      значение := S.VAL(  ФУНКЦИЯ_2П_ЦЕЛ_Р_ЦЕЛ,
             WinApi.GetProcAddress( dll, "_znachenie" ) );
      адрес_формы := S.VAL(  ПРОЦЕДУРА_ПАР_ЦЕЛЫЙ_УСТР,
             WinApi.GetProcAddress( dll, "_adres_formy" ) );     

      отладка := S.VAL(  ПРОЦЕДУРА_10ПАР_ЦЕЛЫЙ,
             WinApi.GetProcAddress( dll, "_otladka" ) );   

   ELSIF (n = ОСВОБОДИТЬ_БИБЛИОТЕКУ) THEN

      ot := WinApi.FreeLibrary(dll);

   ELSIF (n = ВЫВОД_СХЕМЫ) THEN

      вывод_схемы;
   END;

   ВЕРНУТЬ  ответ;
END _zapros;


PROCEDURE [ccall] _adres_formy* 
                (Н:ЦЕЛЫЙ; У:УКАЗАТЕЛЬ НА МАССИВ ИЗ ЛИТЕР);
BEGIN
   адрес_формы(Н,У);

END  _adres_formy;


ПРОЦЕДУРА  вывод_схемы;
ПЕРЕМЕННЫЕ ж, ии, и, смещение_эл_х, х1,х2,у1,у2,
           вэкв, эздв:ЦЕЛЫЙ;
НАЧАЛО
         
         ЕСЛИ (запрос(З1_НАЧАЛО_ПРОГРАММЫ) = ОТВЕТ_ДА) ТО  
           ВЫХОД; 
         КОНЕЦ;  
         
         команда(К1_ПОЛУЧИТЬ_РАЗМЕРЫ_КАНВЫ);

         ЕСЛИ (запрос(З1_ТЕКСТОВАЯ_ЗАПИСЬ) = ОТВЕТ_ДА) ТО
           команда(К1_ВЫВОД_ТЕКСТА);
           команда(К1_ОБНОВИТЬ_КАНВУ);
           ВЫХОД;
         КОНЕЦ;

         команда(К1_СТИЛЬ__СОЕДИНИТЕЛЬНЫЕ_ЛИНИИ);
         команда(К1_СТИЛЬ__ЦВЕТ_ФОНА);

         команда(К1_ФОН_СХЕМЫ);        

         ЕСЛИ (запрос(З1_ПОДСЧЕТ_МАКС_КООРДИНАТ) = ОТВЕТ_НЕТ) ТО
           команда(К1_ОБНОВИТЬ_КАНВУ);
           ВЫХОД;
         КОНЕЦ;

         (** вывод главной вертикали *)         
             ж :=0;
             ии :=значение(В1_ИНД_1_ЭЛ_ВЕРТИКАЛИ, ж);
             и :=0;
         
         ЦИКЛ_ПОКА (и < значение(В1_КОЛ_ЭЛ_ВЕРТИКАЛИ, ж)) ДЕЛАТЬ
         
           ЕСЛИ (значение(В1_ВЕРТИКАЛЬ_ЭЛЕМЕНТА, ии) = ж) ТО
             ЕСЛИ (значение(В1_ЭЛЕМЕНТ_ИСПОЛЬЗУЕТСЯ, ии) = ОТВЕТ_ДА) ТО
               данные(Д1_ВЕРТИКАЛЬ, ж);
               данные (Д1_ИНДЕКС_ЭЛЕМЕНТА, ии);
               данные (Д1_ТЕК_ЭЛ_ВЕРТИКАЛИ, и);
               команда (К1_ВЫВОД_ЭЛЕМЕНТА);
               УВЕЛИЧИТЬ(и);
             КОНЕЦ;
           КОНЕЦ;        
         
           УВЕЛИЧИТЬ(ии);
         КОНЕЦ_ЦИКЛА;

         ЦИКЛ_ДЛЯ  ж := 0 ДО запрос(З1_КОЛ_ДОП_ВЕРТИКАЛЕЙ)-1  ДЕЛАТЬ
         (* цикл вывода элементов дополнительных вертикалей *)

            смещение_эл_х := 0;
            
            ЕСЛИ ((значение(В1_РОДИТЕЛЬ_ВЕРТИКАЛИ, ж) # НЕ_ЗАДАН) &
                  (значение(В1_ТИП_ДОП_ВЕРТИКАЛИ, ж) # ВЕРТИКАЛЬ_ЦИКЛА)) ТО

               смещение_эл_х := значение(В1_ШИРИНА_РОДИТЕЛЯ_ВЕРТИКАЛИ, ж);            
            КОНЕЦ;   

            х1 := значение(В1_Х_ВЕРТИКАЛИ_РОДИТЕЛЯ, ж) +
                  запрос(З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_Х) + (смещение_эл_х ДЕЛИТЬ 2);
                  
            х2 := запрос(З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_Х) + значение(В1_Х_ДОП_ВЕРТИКАЛИ,ж);
            у1 := запрос(З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_У) + значение(В1_У1_ДОП_ВЕРТИКАЛИ,ж);                  
            
            ЕСЛИ (значение(В1_ТИП_ДОП_ВЕРТИКАЛИ,ж) = ВЕРТИКАЛЬ_ДОЧЬ) ТО
            
               ЕСЛИ (значение(В1_ТИП_1_ЭЛ_ДОП_ВЕРТИКАЛИ,ж) = т_ИНЕСЛИ) ТО
               
                 ЕСЛИ (значение(В1_ФЛАГ_ВЕТКИ_1_ЭЛ_ДОП_ВЕРТИКАЛИ,ж) = ОТВЕТ_ДА) ТО
                                
                   смещение_эл_х := значение(В1_ШИРИНА_1_ЭЛ_ДОП_ВЕРТИКАЛИ,ж);
                   
                   х2 := х2 - (смещение_эл_х ДЕЛИТЬ 2);
                   
                 КОНЕЦ; 
               КОНЕЦ;

               данные(Д1_КООРД_Х1, х1);   данные(Д1_КООРД_У1, у1);
               данные(Д1_КООРД_Х2, х2);   данные(Д1_КООРД_У2, у1);
               команда(К1_ЛИНИЯ);                                

               вэкв := значение(В1_ВЕРТИКАЛЬ_ЭЛ_КОНЦА_ВЕРТИКАЛИ, ж);

               х1 := запрос(З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_Х) + значение(В1_Х_ВЕРТИКАЛИ,вэкв);
               
               х2 := запрос(З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_Х) + 
                                           значение(В1_Х_ДОП_ВЕРТИКАЛИ, ж);
                              
               у2 := запрос(З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_У) + 
                     значение(В1_У1_ДОП_ВЕРТИКАЛИ,ж) +
                     значение(В1_ТЕК_У_ДОП_ВЕРТИКАЛИ,ж);
                                                           
               данные(Д1_КООРД_Х1, х1);   данные(Д1_КООРД_У1, у2);
               данные(Д1_КООРД_Х2, х2);   данные(Д1_КООРД_У2, у2);
               команда(К1_ЛИНИЯ);                                

               ЕСЛИ (значение(В1_КОЛ_ЭЛ_ДОП_ВЕРТИКАЛИ, ж) # 0) ТО   
               
                  ЕСЛИ (значение(В1_ТИП_1_ЭЛ_ДОП_ВЕРТИКАЛИ,ж) # т_ИНАЧЕ) ТО
               
                    ЕСЛИ (значение(В1_ТИП_1_ЭЛ_ДОП_ВЕРТИКАЛИ,ж) # т_ИНЕСЛИ) ИЛИ 
                      (значение(В1_ФЛАГ_ВЕТКИ_1_ЭЛ_ДОП_ВЕРТИКАЛИ,ж)=ОТВЕТ_НЕТ) ТО
                      
                      у1 := запрос(З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_У) +
                            значение(В1_У1_ДОП_ВЕРТИКАЛИ,ж);
                      
                      у2 := у1 + значение(В1_У1_1_ЭЛ_ДОП_ВЕРТИКАЛИ,ж);
                      
                      данные(Д1_КООРД_Х1, х2);   данные(Д1_КООРД_У1, у1);
                      данные(Д1_КООРД_Х2, х2);   данные(Д1_КООРД_У2, у2);
                      команда(К1_ЛИНИЯ);                                
                    КОНЕЦ;
                  КОНЕЦ;
               КОНЕЦ; 
            КОНЕЦ;
            
            ЕСЛИ (значение(В1_ТИП_ДОП_ВЕРТИКАЛИ,ж) = ВЕРТИКАЛЬ_ЦИКЛА) ТО
              
               у1 := значение(В1_ВЫШЕ_ЗАГОЛ_ВЕТОК, у1);
                                               
               данные(Д1_КООРД_Х1, х1);   данные(Д1_КООРД_У1, у1);
               данные(Д1_КООРД_Х2, х2);   данные(Д1_КООРД_У2, у1);
               команда(К1_ЛИНИЯ);                                

               данные(Д1_КООРД_Х1, х1);
               данные(Д1_КООРД_У1, у1);
               команда(К1_СТРЕЛКА_ЦИКЛА);              

               у2 := у1 + значение(В1_ТЕК_У_ДОП_ВЕРТИКАЛИ,ж) +
                          (запрос(З1_ШАГ_ТЕКСТА_ПО_У) ДЕЛИТЬ 4);
               
               эздв:= значение(В1_ЭЛ_ЗАКРЫВАЮЩИЙ_ДОП_ВЕРТИКАЛЬ,ж);
                               (* КОНЕЦ/КОНЕЦ_ЦИКЛА *)
               смещение_эл_х := значение(В1_ШИРИНА_ЭЛЕМЕНТА, эздв);
               
               х1 := х1 + (смещение_эл_х ДЕЛИТЬ 2);
               
               данные(Д1_КООРД_Х1, х1);   данные(Д1_КООРД_У1, у2);
               данные(Д1_КООРД_Х2, х2);   данные(Д1_КООРД_У2, у2);
               команда(К1_ЛИНИЯ);                                
            КОНЕЦ;

            ЕСЛИ (значение(В1_КОЛ_ЭЛ_ДОП_ВЕРТИКАЛИ, ж) = 0) ТО
               
               у1 := запрос(З1_СМЕЩЕНИЕ_СХЕМЫ_ПО_У) + 
                     значение(В1_У1_ДОП_ВЕРТИКАЛИ, ж);
               у2 := у1 + значение(В1_ТЕК_У_ДОП_ВЕРТИКАЛИ, ж);
               
               ЕСЛИ (значение(В1_ТИП_ДОП_ВЕРТИКАЛИ, ж)= ВЕРТИКАЛЬ_ЦИКЛА) ТО
                 у1 := значение(В1_ВЫШЕ_ЗАГОЛ_ВЕТОК, у1);
               КОНЕЦ; 
               данные(Д1_КООРД_Х1, х2);   данные(Д1_КООРД_У1, у1);
               данные(Д1_КООРД_Х2, х2);   данные(Д1_КООРД_У2, у2);
               команда(К1_ЛИНИЯ);                                

            ИНАЧЕ
               ии := значение(В1_ИНД_1_ЭЛ_ДОП_ВЕРТИКАЛИ, ж);

               и := 0; 
               
               ЦИКЛ_ПОКА (и < значение(В1_КОЛ_ЭЛ_ДОП_ВЕРТИКАЛИ, ж)) ДЕЛАТЬ
               
                 ЕСЛИ (значение(В1_ВЕРТИКАЛЬ_ЭЛЕМЕНТА, ии) =
                       значение(В1_ДОП_ВЕРТИКАЛЬ, ж)) ТО

                   ЕСЛИ (значение(В1_ЭЛЕМЕНТ_ИСПОЛЬЗУЕТСЯ, ии) = ОТВЕТ_ДА) ТО
                     данные(Д1_ВЕРТИКАЛЬ, значение(В1_ДОП_ВЕРТИКАЛЬ, ж));
                     данные (Д1_ИНДЕКС_ЭЛЕМЕНТА, ии);
                     данные (Д1_ТЕК_ЭЛ_ВЕРТИКАЛИ, и);
                     команда (К1_ВЫВОД_ЭЛЕМЕНТА);
                     УВЕЛИЧИТЬ(и);
                   КОНЕЦ;
                 КОНЕЦ; 

                 УВЕЛИЧИТЬ(ии); 
               КОНЕЦ_ЦИКЛА;  
            КОНЕЦ; 
         КОНЕЦ_ЦИКЛА_ДЛЯ;

         команда(К1_ОБНОВИТЬ_КАНВУ); 

КОНЕЦ  вывод_схемы;


END Dal2Kpdll.

(* в начале строки DevLinker ... вставить коммандер: Ctrl+Q,
    а затем щелкнуть по нему левой кнопкой мыши *)
DevLinker.LinkDll kpdll.dll := Dal2Kpdll# ~
```

Фрагмент файла  u_pasdll.pas из проекта pasdll:
## Код:
```
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls;


  type uchar = ^char;


procedure  _komanda(k:integer);  export;  stdcall;
procedure  _dannye(k1, k2:integer);  export;  stdcall;
function   _zapros(n:integer):integer;  export;  stdcall;
function   _znachenie(n1,n2:integer):integer;  export;  stdcall;
procedure  _adres_formy(n:integer; uch:uchar);  export;  stdcall;


implementation

uses  u_dalvj, u_ls, u_files, u_img;


var
  f1: Tform_dalvjaz;
  f2: Tform_ls;
  f3: Tfajly;
  f4: Tform_img;


procedure  _adres_formy(n:integer; uch:uchar);
begin
  if (n = 1)  then  f1 := Tform_dalvjaz(uch);
  if (n = 2)  then  f2 := Tform_ls(uch);
  if (n = 3)  then  f3 := Tfajly(uch);
  if (n = 4)  then  f4 := Tform_img(uch);
end;


procedure  _komanda(k:integer);
var ot:integer;
begin
   ot := f1.obrabotka(k,0);
end;


procedure  _dannye(k1, k2:integer);
var ot:integer;
begin
   ot := f1.obrabotka(k1,k2);
end;


function   _zapros(n:integer):integer;
var ot:integer;
begin
   ot := f1.obrabotka(n,0);

   _zapros := ot;
end;


function   _znachenie(n1,n2:integer):integer;
var ot:integer;
begin
   ot := f1.obrabotka(n1,n2);

   _znachenie := ot;
end;
```

Обработчик, находящийся в файле u_obr.pas проекта dal2871 (бывший
dal2851), содержит всю логику, вырезанную из исходного текста процедуры
вывода схемы. Ниже приведен фрагмент исходного кода обработчика,
содержащий одну из ветвей сложного условия для обработки вызовов
процедуры ЛВУ.

. . .

end else if (n1= K1_WYWOD_EXLEMENTA) then begin  // К1_ВЫВОД_ЭЛЕМЕНТА

form_dalvjaz.wywod_elem(nil, dannye_wertikalx,
dannye_ind_exl, dannye_tek_exl_wert);

end else if (n1= K1_LINIQ) then begin            // К1_ЛИНИЯ

. . .


Головной обработчик ЛВУ выглядит следующим образом:

function  _obrabotka(n1, n2:integer):integer;
var ot:integer;
begin
ot := -1;

if (n1 >= 10001) and (n1 < 10100) then begin
(* 1. вывод_схемы *)  ot := _obrabotka_1(n1,n2);
end;

. . .

_obrabotka := ot;
end;


ЛВУ, описывающей работу со списками или одномерными массивами, вполне
достаточно процедурных вызовов четырех типов:  команда, данные, запрос,
значение (типы этих вызовов см. выше).
Каждой процедуре ЛВУ неявно (в комментарии к процедуре) присваивается
свой номер, который уже явно (в начале имени) присваивается константам,
подставляемым в процедурные вызовы ЛВУ, и обработчику этой процедуры ЛВУ.
Префиксы констант ЛВУ указывают на типы процедурных вызовов, в которых
эти константы используются:
команды (К*_) / данные (Д*_) / запросы (З*_) / значения (В*_)

Ветви сложного условия обработчика ЛВУ сгруппированы по типам
обрабатываемых процедурных вызовов в следующей последовательности:
- обработка команд;
- обработка данных;
- обработка запросов;
- обработка значений.

Каждая ветка сложного условия обработчика ЛВУ может содержать либо вызов
процедуры логики нижнего уровня, либо вызов процедуры ЛВУ, либо анализ или
обработку каких-либо данных с получением соответствующего выходного
значения для передачи его в процедуру ЛВУ.

Присвоение номеров процедурам, константам и обработчикам ЛВУ позволяет
создать замкнутое пространство имен для каждой процедуры ЛВУ, что
упрощает процесс разработки и отладки процедур ЛВУ.

Если ПО пишется на Delphi 2010 и выше, то нет необходимости переносить
процедуры ЛВУ в отдельную DLL. Тексты процедуры ЛВУ для вывода схемы и
обработчика для этой процедуры ЛВУ приведены в файле lvu2.txt.



Использование ЛВУ позволяет решать следующие задачи:

1) обеспечение самодокументирования процедур ЛВУ

Многие пренебрежительно относятся к документированию своего кода.
А между тем в англоязычных странах, где ПО пишется на родном языке,
программистам легче, чем нам, разбираться в чужом коде и подхватывать
начатые другими программистами программные проекты. Отсюда меньше
переписываемых с нуля проектов, а значит и материальные издержки на
разработку ПО тоже меньше.

2) обеспечение механизма сокрытия данных путем разбиения логики программы
на маршрутную (процедура ЛВУ) и функциональную (обработчик процедуры ЛВУ)

Механизм сокрытия данных на уровне ЛВУ обеспечивает гибкость разработки
логики процедур ЛВУ, сопоставимую с гибкостью разработки программ,
обеспечиваемой механизмом сокрытия данных через интерфейсы модулей и
классов. Например, при замене типов данных, используемых в обработчике
процедуры ЛВУ, для самой процедуры ЛВУ ничего не изменится.

3) разбиение функциональной логики программы на мелкие фрагменты с
полностью прозрачной логикой, находящиеся в ветках сложных условий
обработчиков процедур ЛВУ

4) формирование унифицированной трехуровневой логики разработки программы

При программировании с использованием ЛВУ логика программы разделяется на
следующие логические уровни:
- процедуры ЛВУ для обработки возникающих событий;
- обработчики процедур ЛВУ;
- процедуры логики нижнего уровня.

Введение унифицированной логики разработки программы (шаблона разработки
ПО) позволит упростить передачу сопровождения фрагментов программы другим
программистам за счет упрощения ознакомления с унифицированной ЛВУ того
или иного фрагмента программы по сравнению с общепринятой логикой
написания ПО с минимально возможным документированием логики программы
и размытой от постоянного внесения новых изменений иерархической и
логической структурой программы.
Вложение:lvu2.txt[40.48 КБ]
Скачиваний: 769
