Сегодня публикуем вторую часть перевода материала о математике, о COBOL, и о том, почему этот язык всё ещё жив.
Рекуррентное соотношение Мюллера и COBOL
Взглянем на то, как рекуррентным соотношением Мюллера справится COBOL. Вот программа на COBOL, реализующая исследуемое нами рекуррентное соотношение.
IDENTIFICATION DIVISION.
PROGRAM-ID. muller.
AUTHOR. Marianne Bellotti.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 X1 PIC 9(3)V9(15) VALUE 4.25.
01 X2 PIC 9(3)V9(15) VALUE 4.
01 N PIC 9(2) VALUE 20.
01 Y PIC 9(3)V9(15) VALUE ZEROS.
01 I PIC 9(2) VALUES ZEROS.
PROCEDURE DIVISION.
PERFORM N TIMES
ADD 1 TO I
DIVIDE X2 INTO 1500 GIVING Y
SUBTRACT Y FROM 815 GIVING Y
DIVIDE X1 INTO Y
MOVE X1 TO X2
SUBTRACT Y FROM 108 GIVING X1
DISPLAY I'|'X1
END-PERFORM.
STOP RUN.
Если вы впервые видите программу, написанную на COBOL, то давайте сразу проясним некоторые вещи. Во-первых — это так называемый «free form» COBOL, который был представлен в 2002 году для того, чтобы приблизить COBOL к тому, как структурированы современные языки. Традиционно код на COBOL имеет фиксированную ширину, когда определённые сущности размещаются в определённых столбцах. Идея рассмотрения кода в виде структуры, в которой выделяются строки и столбцы, может показаться странной, но такая структура кода предназначалась для имитации форматирования перфокарт. Во времена появления COBOL программы создавали именно так. Перфокарта имеет 80 столбцов — определённые столбцы предназначены для определённых данных. Такой же подход является традиционным и для COBOL.
Самое важное в этом коде, нечто такое, что, возможно, привлекает к себе больше всего внимания, заключается в том, как здесь объявляют переменные:
01 X2 PIC 9(3)V9(15) VALUE 4.
Код 01
в начале строки называется номером уровня (level number). Он сообщает COBOL о том, что мы объявляем новую переменную. COBOL позволяет связывать или группировать переменные (классический пример — это адрес, который может включать в себя названия улицы, города и страны в виде отдельных переменных), в результате в данном случае номер уровня становится важным.
X2
— это имя переменной — тут всё довольно просто. В конце имеется конструкция, устанавливающая начальное значение переменной, которая выглядит как «VALUE 4.
». Точка в конце — это не опечатка. Это — способ завершения строк в COBOL.
Теперь нам осталось рассмотреть лишь то, что находится в середине строки — конструкцию PIC 9(3)V9(15)
.
PIC
— это нечто вроде оператора для описания символьного типа данных. Он может хранить буквенно-цифровые значения. Он даже может хранить десятичные числа. COBOL — это язык со строгой статической типизацией и с одной необычной особенностью, которая заключается в том, что большинство типов COBOL оказываются гораздо более гибкими, чем типы в других языках. Кроме того, при объявлении переменных нужно указать то, из скольких символов они могут состоять. В нашем случае это — число в скобках. Конструкция PIC 9(3)
означает, что переменная может хранить три символа, которые являются числами (на это указывает число 9
).
В результате конструкцию 9(3)V9(15)
надо читать так: «3 цифры, за которыми следует десятичная точка (v), за которой следуют ещё 15 цифр».
Вот результаты работы этой программы:
01|004.470588235294118
02|004.644736842105272
03|004.770538243626253
04|004.855700712593068
05|004.910847499165008
06|004.945537405797454
07|004.966962615594416
08|004.980046382396752
09|004.987993122733704
10|004.993044417666328
11|005.001145954388894
12|005.107165361144283
13|007.147823677868234
14|035.069409660592417
15|090.744337001124836
16|099.490073035205414
17|099.974374743980031
18|099.998718461941870
19|099.999935923870551
20|099.999996796239314
Это получилось с использованием чисел, имеющих 15 знаков после запятой. Если поменять свойства переменных X1
, X2
и Y
на PIC9(3)V9(25)
— то мы сможем продвинуться дальше:
01|004.4705882352941176470588236
02|004.6447368421052631578947385
03|004.7705382436260623229462114
04|004.8557007125890736342050246
05|004.9108474990827932004556769
06|004.9455374041239167250872200
07|004.9669625817627006050563544
08|004.9800457013556312889833307
09|004.9879794484783948244551363
10|004.9927702880621195047924520
11|004.9956558915076636302013455
12|004.9973912684019537143684268
13|004.9984339443572195941803341
14|004.9990600802214771851068183
15|004.9994361021888778909361376
16|004.9996648253090127504521620
17|004.9998629291504492286728625
18|005.0011987392925953357360627
19|005.0263326115282889612747162
20|005.5253038494467588243232985
Разные мэйнфреймы предлагают разные верхние ограничения для типов данных COBOL. У IBM (по крайней мере — в моём случае) это — 18 цифр. У MicroFocus это — 38 цифр.
Сколько стоит точность?
Всё, о чём мы только что говорили, направлено на то, чтобы показать, что COBOL выполняет вычисления не лучше, чем другие, более распространённые языки программирования. Из-за ограничений на размеры чисел с фиксированной точкой COBOL, на самом деле, может уступать языкам, которые дают разработчику больше контроля над происходящим.
Но тут есть одна особенность. Дело в том, что Python (да и Java) не имеет встроенной поддержки чисел с фиксированной точкой. А в COBOL эта поддержка есть.
Для выполнения вычислений с фиксированной точкой в Python мне пришлось импортировать модуль Decimal
. Если вы когда-нибудь работали с проектом, в котором имеется целая куча команд импорта — вы должны знать о том, что у каждой подобной команды есть определённая «цена». В языках наподобие Java (а именно этот язык обычно рассматривается теми, кто собирается избавиться от COBOL) «цена» подходящей библиотеки может быть значительно выше. Это, на самом деле, скорее вопрос о том, играет ли какую-то роль в вашем проекте «стоимость» импорта библиотек. Для многих программистов размышление над влиянием на производительность, которую оказывают команды импорта — это вершина преждевременной оптимизации.
Но COBOL-программисты обычно работают над системами, которые должны обрабатывать миллионы, а возможно — и миллиарды операций в секунду, делая это точно и надёжно. И, к несчастью, очень сложно привести убедительный аргумент за COBOL или против него для подобного сценария, так как это, на самом деле, область бесчисленных вариаций. Является ли определяющим фактором при выборе языка для решения подобных задач встроенная в COBOL поддержка чисел с фиксированной точкой? Или, может быть, соответствующие проблемы можно решить, правильно подбирая комбинацию из процессора, памяти, операционной системы? Или, может, для решения задач быстрых, точных и надёжных вычислений нужно прибегнуть к «танцам с бубном»? Может быть — ограничим рассуждения? Сведём их к поиску ответа на вопрос вроде «Что лучше — COBOL или Java при условии использовании одного и того же аппаратного обеспечения?». Но и так нам будет сложно оценить то, как недостатки каждого из языков повлияют на производительность в момент, когда система начнёт выполнять вышеупомянутые миллиарды операций в секунду. В результате можно сказать лишь то, что те же COBOL и Java — просто очень разные языки.
Вот что пишут по этому поводу здесь, исследуя производительность Java-кода, транслированного из COBOL-кода.
COBOL — это компилируемый язык, использующий стек, поддерживающий указатели и объединения. Конверсия типов не создаёт нагрузку на систему во время выполнения программы. Здесь нет диспетчеризации или преобразований типов во время выполнения программ. Java-код, с другой стороны, выполняется на виртуальной машине. Он использует кучу и не поддерживает объединения. Конверсия типов создаёт нагрузку на систему во время выполнения программы. Java использует динамическую диспетчеризацию и вывод типов во время выполнения программ. Хотя и можно минимизировать объём использования этих возможностей, обычно это приводит к тому, что код получается в той или иной мере «непохожим» на обычный Java-код. При изучении результатов трансляции Java-кода из COBOL обычно жалуются на то, что код получается нечитаемым и неподдерживаемым. Это сводит на нет большинство целей перехода с COBOL на Java.
Прежде чем вы решите отмахнуться от этих рассуждений фразой «Да, но это Java, а Java — тоже не подарок» — вспомните вот о чём: большинство современных языков программирования совершенно не имеют встроенной поддержки вычислений с фиксированной точкой. (Я так думаю, что правильнее было бы сказать, что ни один из современных языков это не поддерживает, но я не могу это надёжно проверить.) Конечно, можно выбрать другой язык, имеющий свой набор достоинств и недостатков, но если нужна точность в вычислениях с фиксированной точкой, и если вы думаете, что небольшая потеря в производительности от импорта библиотеки, реализующей такие вычисления, может вам повредить, это значит, что у вас есть единственный вариант — COBOL.
Именно поэтому столь сложна так называемая «модернизация»: она зависит от множества факторов. Некоторые организации получат ощутимые результаты от инвестиций в смену программной платформы, а другие обнаружат, что потеряли что-то важное взамен на «улучшения», которые, на самом деле, ничего особенно и не улучшают. Если организация — это крупный финансовый институт, обрабатывающий миллионы транзакций каждую секунду и нуждающийся в десятичной точности вычислений — то, на самом деле, дешевле будет обучить специалистов работе с COBOL, чем заплатить ресурсами и производительностью за миграцию на более популярный язык. В конце концов, популярность — явление временное.
Итоги
В результате, говоря о том, почему так много организаций всё ещё используют COBOL, нужно понимать, что задача по переработке программ отличается от задачи создания программ. Программисты, создававшие решение, имели преимущество в виде его поэтапного внедрения. Приложения обычно стремятся максимально приблизить к пределам тех возможностей, которые поддерживают реализованные в них технологии. Дилемма, касающаяся миграции с COBOL — это не вопрос о переходе с одного языка на другой. Это — задача о переходе с одной парадигмы на другую. Пределы возможностей Java или Python на Linux — это совсем не то, что пределы возможностей COBOL на мейнфрейме. В некоторых случаях COBOL-приложения способны на то, что современные языки не могут. Для подобных случаев использование COBOL на современном мейнфрейме окажется, на самом деле, более дешёвым, производительным и точным решением.
Уважаемые читатели! Как вы думаете, действительно ли COBOL — это язык, который в некоторых ситуациях оказывается по-настоящему лучше более современных языков?
Автор: ru_vds