Некоторое время
назад я занимался программированием на КОБОЛе для большой машины (mainframe),
переболел этим и почти забыл вид этих здоровых железок, как вдруг неожиданный
контракт на крупную сумму заставил меня вспомнить прошлые дела.
Несколько клиентов
просили меня написать подсистему, способную общаться с большим компьютером.
У всех требования сводились к получению возможности посылки запроса на
большую машину и приема ответа для обновления файла заказов на персональном
компьютере.
В главе я привожу
пример приложения, в котором использованы обобщенные методики. Можно разработать
универсальный инструментарий для решения некоторых из такого рода задач,
так как на каждом этапе разработки используются списки полей, длины полей,
протоколы преобразований и стандартные форматы. Однако, мне кажется, что
при чрезмерном обобщении есть опасность потерять основную идею. Если вам
потребуется писать по приложению в неделю, тогда есть смысл придумать нечто
универсальное.
Я выбрал в
качестве примера электронную систему заказов, так как она вполне может
оказаться той первой задачей, с которой вам придется иметь дело. Обычный
сценарий работы подразумевает посылку на большой компьютер файла с данными
из .DBF-файла и ожидание ответа. Большие машины обычно выполняют
запись и чтение в формате стандартного КОБОЛа, и обмен данными является
ключевым участком всего приложения.
Когда я только
взялся за разработку, то предполагал, что самой трудной частью будет написание
программы связи с большим компьютером. На самом деле этот участок оказался
самым легким: сделать это было невозможно, так что я даже и не пытался.
Я просто использовал коммерческий пакет ProComm PLUS и нанял парня, который
написал программу связи (script) примерно за пару часов. Если вы решите
стать экспертом по программному обеспечению поддержки телекоммуникаций,
то вам придется провести несколько месяцев в уединении на острове с неограниченным
бюджетом для оплаты телефонной связи. В конце такого добровольного заключения
вы будете знать достаточно, чтобы понять, что гораздо проще нанять программиста,
который за 200 долл. сделает эту работу вместо вас.
Больше всего времени у меня заняла
разработка формата файлов для посылки на большую машину. В этой главе вы
увидите как это реализуется средствами функций низкого уровня доступа.
Проектирование программы
Большие компьютеры
не способны читать файлы в формате xBASE. Они работают с файлами последовательной
иерархической структуры (Hierarchical Sequential File Structure HSAM).
В системе заказов на покупки, построенной на xBASE, вы имеете дело с файлом
заголовков, по одному заголовку на каждый заказ, определяющему общую информацию
о заказе. Кроме того, у вас имеется файл с полными данными по заказам.
Каждому заказу соответствует по одной записи в файле данных. Поле номера
заказа связывает два файла вместе. В нашем примере мы предполагаем, что
такая система у вас уже имеется.
В мире КОБОЛа
оба типа записей находятся в одном файле, и им предшествует символьный
идентификатор (1-3 байта), определяющий тип записи. Это позволяет считать
запись в буфер, определить ее тип и перенести в другой буфер (подобно структуре
на Си), который интерпретирует поля должным образом. В итоге файл заказов
может выглядеть примерно так:
01PO#0000103/12/910008795002000000
02PO#0000100001ITEM#01001295001295
02PO#0000100003ITEM#02002500007500
01PO#0000203/15/910002590001000000
02PO#0000200002ITEM#01001295002590
Для меня это
выглядит вполне обычно. В КОБОЛе вы можете иметь несколько структур записи
в одном файле, и, поэтому, заголовки не располагаются в верхней части файла,
как это имеет место в формате xBASE. Надо сказать, что правительство регулярно
складирует миллионы бобин с лентами, содержащими данные по переписке, за
счет налогоплательщиков, но при этом не хранит дескрипторы файлов КОБОЛа
и, следовательно, прочитать данные невозможно. Напишите жалобу вашему конгрессмену!
Чтобы считать
наш файл вам необходимо иметь дескриптор, описывающий структуры записей
в соответствии с их типами. Для приведенного выше примера дескриптор выглядит
так:(Табл. 9-1)
В нашем примере
первая запись имеет тип [01] заголовок, для заказа #00001 от 12 марта 1991
на общую сумму $87.95. Две следующие записи типа [02] описывают заказ,
который включает один предмет #01 и два предмета #02. Обратите внимание,
что все записи имеют одинаковую длину (в нашем примере 34 байта), так как
они входят в один и тот же файл и для доведения записи типа 01 до нужной
длины используется заполнитель (необязательно использовать нули, но они
более наглядны чем пробелы, а я собираюсь показать принцип работы наглядно).
Обычно программы
связи предпочитают иметь дело с пакетным заголовком (batch header record),
предшествующем всем записям, и, вы правильно догадались, пакетным концевиком
(batch trailer record), завершающим передачу. Это позволяет компьютеру
определить можно ли начать работу.
После того
как вы послали один из таких файлов на большой компьютер, он некоторое
время его помусолит и пошлет назад ответ: у нас есть то, у нас нет этого,
я не знаю, что такое ITEM#02 и т. п. Вы считываете файл подтверждения приема,
обновляете заказ по информации от большого компьютера и готово.
Что нужно сделать
Если все настолько
просто, почему так много программистов для xBASE впадает в панику при необходимости
сделать что-либо подобное? (Меня неоднократно спрашивали как решаются такие
задачи и могу сказать, что слово паника вполне адекватно описывает состояние
спрашивающих). Собственно говоря, с такой или похожей проблемой приходится
сталкиваться всем, кто имеет дело с системами электронных заказов:
1)Индексные ключи системы на большом
компьютере слегка отличаются от тех, что используются в вашей работающей
системе учета заказов.
2) Некоторые из полей, которые требуются для указания в пакетном заголовке, не существуют в ваших файлах.
3) В вашем файле заголовков нет некоторых полей, необходимых в заголовке файла заказов для большой машины.
4) Используются различные системы кодирования (например, они используют "1" для указания отсутствия товара, а вы используете "O/S" (Out of Stock).
5) Почти наверняка они не работают с дробными числами.
6) Разумеется, вы получите в качестве ответа на ваш запрос файл в формате HSAM КОБОЛа, что означает что вам необходимо не только писать в файл такого формата, но и обеспечить его чтение.
Не стоит беспокоиться.
Подобно большинству проблем, возникающих у программистов, эти поддаются
решению. Все что нужно - это свести до минимума блуждание в тупиках.
Пункт 1 означает,
что вам всего лишь нужно преобразовать ваши ключевые выражения при отправке
и конвертировать в исходный вид при приеме. Пункт 2 потребует изменения
структуры файла. Пункт 3 подразумевает добавление недостающих полей в файл
заголовков. Проблема по пункту 4 решается трансляцией значений соответствующего
поля в обоих направлениях. Пункт 5 потребует использования:
TRANSFORM(numfield*100,[@L ######])
для каждого числового поля с десятичной
частью. Пункт 6 решается довольно просто: посмотрите на программу CONFIRM.PRG.
Вот и все.
Предлагаемая вашему вниманию программа может быть довольно близка к тому,
что вам придется написать при столкновении с такой задачей.
Заказы на покупку
собираются в пакет во время передачи, так что пользователь может посмотреть
данные перед построением пакета.
Для построения
экрана просмотра я использовал SET SKIP и BROWSE.
У меня есть некоторое предубеждение против использования BROWSE
из-за его медлительности. Но в данном случае это то, что нужно.
Пользователь выбирает заказы
для посылки, пользуясь меню, построенным командой DEFINE POPUP MULTI.
Ctrl-Enter снимает выделение, Enter назначает выделение,
а клавиши управления курсором распространяют выделение на последующие /
предыдущие записи. Т. е., если вы выделите запись 1, нажмете Shift
и перейдете к записи 2, она также окажется выделенной. Я надеюсь пользователи
привыкнут к этому, особенно потому, что такой интерфейс очень недорого
написать. Нажатие ESCAPE заканчивает процесс выделения.
И, наконец,
появляется панель управления, позволяющая пользователю снова перейти в
режим выбора, выполнить передачу или отменить выполнение. Этот режим построен
на основе цикла, в котором выбор <edit> возвращает управление
в начало цикла, <transmit>обеспечивает выход из цикла, а <cancel>
также выводит из цикла, но при этом переменная Done принимает значение .Т..
Программа имитирует
передачу данных. Я включил команду, запускающую ProComm PLUS с файлом
сценария "MyScript". Вы посылаете файл с именем ORDERS, ожидаете
некоторое время и получаете файл с именем CONFIRM. Сценарий представляет
сокращенный вариант поставляемого с ProComm PLUS, но вы всегда можете
нанять кого-нибудь, кто знает эту работу лучше вас и сделает ее быстрее.
Для того, чтобы
программа могла читать записи, оканчивающиеся CHR(13)+CHR(10), я
использую переменную Testing. Просмотреть результаты можно командой
MODI FILE, а возврат к рабочему варианту выполняется присваиванием
Testing=.F..
Спецификации
Структуры файлов
Purchord.Dbf, Poitem.Dbf и Settings.Dbf приведены
в Табл. 9-2. Структуры файлов большой
машины приведены в Табл. 9-3. Структура
файла подтверждения от большой машины приведена в Табл.
9-4.
Код всей программы
приведен в Листинге 9-1.
Как это работает
Система предполагает,
что у вас уже имеется система приема заказов. Опция View используется
для планирования передачи данных. Заказы вводятся в файл ORDER с
использованием функций низкого уровня доступа. Если переменная Testing
имеет значение .Т. (а вам придется присвоить ей такое значение,
если только вы не найдете большой компьютер, согласный обработать ваши
файлы), то создается парный ему файл с именем ORDER.TXT, и вы можете
посмотреть результаты работы. Аналогично, наш имитатор читает файл CONFIRM
как ASCII-файл, в котором каждая запись оканчивается возвратом каретки
в том случае, если у нас установлен режим тестирования. При реальном использовании
ни один из файлов не будет иметь окончаний в виде CrLf.
В реальной
жизни заполненные строки станут записями по приему и будут исключены из
массива заказов. Частично заполненные строки делятся на две части: одна
для частичной отправки имеющегося заказа и другая для задержанной отправки
по гарантированным заказам при поступлении товара. В нашей системе мы не
обрабатываем разделенные поставки и не удаляем выполненные или отмененные
заказы. Мы просто печатаем данные и оставляем их в файле.
При выборе
из меню режима <Transmit> программа просит вас построить список
заказов из предлагаемого меню со списком номеров заказов, после чего создает
файл ORDERS и передает его. Я использую вызов программы ProComm
PLUS и передаю ей в качестве параметра имя файла сценария; настоятельно
рекомендую вам аналогичную методику. При получении ответа в виде файла
CONFIRM я использую TEXTMERGE для печати.
Заключение
Приведенная программа
дает пример гибкости языка FoxPro 2.0. Это основное свойство большинства
языков, но у FoxPro оно действительно доставляет удовольствие.
|