Системы IBM i (бывшие AS/400) десятилетиями хранят критически важную бизнес-логику в программах на RPG. Старый код на RPG III или раннем RPG IV часто выглядит монолитным: циклы, цепочки к файлам, подпрограммы с EXSR и GOTO. Такой подход работал надежно, но сегодня он усложняет поддержку, интеграцию и привлечение новых разработчиков. Модернизация через переход на современный RPG IV с free-format, subprocedures и embedded SQL делает код модульным, читаемым и эффективным. Многие компании уже прошли этот путь, сохранив стабильность и повысив производительность.

Переход начинается с простого шага - конвертации источника командой CVTRPGSRC. Она переводит RPG III в RPG IV, сохраняя логику, но открывая доступ к новым возможностям. Дальше разработчик вручную очищает код, переводит в free-format и разбивает на модули.

Subprocedures как основа модульности

В старом RPG подпрограммы ограничивались локальными переменными и вызовом через EXSR. Subprocedures в RPG IV меняют подход кардинально. Каждая процедура получает свои параметры, возвращает значения и компилируется в ILE-модули или service programs.

Это позволяет вынести повторяющуюся логику в отдельные процедуры. Например, валидацию данных, расчеты или работу с файлами. Программа превращается в набор вызовов процедур, а не в сплошной цикл.

Технически subprocedure определяется с DCL-PI (интерфейс процедуры) и DCL-PR (прототип), а тело в DCL-PROC и END-PROC. В free-format код выглядит чисто:

rpg
 
dcl-proc CalculateTax export; dcl-pi *n packed(11:2); amount packed(11:2) const; rate packed(5:4) const; end-pi; return amount * rate; end-proc;
 
 

Лучшие практики рекомендуют:

  • Выносить бизнес-правила в service programs для повторного использования.
  • Использовать EXPORT для видимых процедур и LOCAL для внутренних.
  • Применять CTL-OPT MAIN для линейных программ без цикла.
  • Избегать глобальных переменных, передавая все через параметры.

Такой код легче тестировать и отлаживать. Один разработчик отмечал: после разбиения монолитной программы на 20 процедур время поиска ошибок сократилось втрое.

Embedded SQL для современного доступа к данным

Традиционный доступ через CHAIN, READ или SETLL работает, но embedded SQL открывает мощь DB2 напрямую. SELECT, INSERT, UPDATE и DELETE встраиваются в RPG, избавляя от ручного управления индикаторами и цепочками.

В free-format SQL начинается с EXEC SQL и заканчивается точкой с запятой. Прекомпилятор CRTSQLRPGI обрабатывает источник.

Простой пример выборки:

rpg
 
exec sql SELECT COUNT(*) INTO :count FROM CUSTOMERS WHERE STATUS = 'ACTIVE';
 
 

Для множественных строк используют курсоры:

rpg
 
exec sql DECLARE c1 CURSOR FOR SELECT ID, NAME, BALANCE FROM CUSTOMERS WHERE BALANCE > :threshold; exec sql OPEN c1; exec sql FETCH c1 INTO :id, :name, :balance; dow sqlcod = 0; // обработка exec sql FETCH c1 INTO :id, :name, :balance; enddo; exec sql CLOSE c1;
 
 

SQL эффективнее для сложных запросов с JOIN, GROUP BY или подзапросами. Он автоматически оптимизируется планировщиком DB2. Многие заменяют циклы по файлам на один SELECT с INTO массивом для блочной выборки.

Комбинация subprocedures и SQL в модернизации

Настоящая сила раскрывается при совместном использовании. Бизнес-логика разбивается так: главная процедура оркестрирует вызовы, каждая subprocedure выполняет задачу с SQL внутри.

Представьте legacy-программу обработки заказов. Раньше - цикл по файлу заказов, CHAIN к клиентам и товарам, расчеты в подпрограммах.

После модернизации:

  • GetCustomerData - процедура с SELECT по ID клиента.
  • ValidateOrder - проверка с SQL на наличие товаров.
  • CalculateTotal - чистый расчет с возвратом значения.
  • UpdateOrder - UPDATE через SQL.

Service program собирает эти процедуры, а главная программа вызывает их по мере надобности.

Один набор преимуществ такой подхода:

  • Модульность упрощает unit-тесты
  • SQL снижает I/O и ускоряет выполнение
  • Free-format повышает читаемость в разы
  • ILE позволяет биндинг с другими языками
  • Легче интегрировать с веб-сервисами или API

Инструменты вроде RDi или VS Code с Code for i помогают автоматизировать конвертацию в free-format.

Практические наблюдения из реальных проектов

Компании, прошедшие модернизацию, отмечают рост производительности на 20-50% за счет оптимизированных запросов. Код становится понятным даже новичкам, знающим SQL. Один случай: монолит на 10 тысяч строк разбили на 50 процедур - поддержка ускорилась, ошибки уменьшились.

Если задуматься, этот подход не просто обновляет код, а переводит его на современные рельсы. Логика остается той же, но обретает гибкость. Переход требует времени, но окупается быстро - особенно когда нужно добавить новые функции или интегрировать с внешними системами.

Природа IBM i позволяет эволюционировать постепенно: конвертировать по одной программе, тестировать, внедрять. Embedded SQL и subprocedures открывают путь к чистому, эффективному коду, который прослужит еще десятилетия. Стоит ли откладывать? Многие уже увидели разницу и не жалеют о шагах в сторону современного RPG IV.