cobol

COBOL是编程语言的Rodney Dangerfield,它不受任何尊重。 它经常因其冗长而被贬低,并被认为是过时的。 然而,COBOL 绝非一成不变的语言 。 它估计处理所有业务交易的85%,并且每年编写50亿行新的COBOL代码。

我作为COBOL程序员工作了10年,但我认为它的声誉不会像人们认为的那样糟糕。 实际上,它非常擅长处理货币和固定格式的记录。 但是COBOL确实有其怪癖,其中许多根源在于编程初期的计算环境。 这是关于打Kong卡如何吃掉我的程序的故事。

一个神秘的错误

这是问题代码的示例,该代码尝试计算订单的运费和预计的运送日期:

1      identification division . 
2      program-id .
3          test-ship .
4
5      data division .
6      working-storage section .
7
8      01 shipping-method            pic x ( 2 ) value 'US' .
9      01 cust-type                  pic x ( 2 ) value 'EM' .
10      01 normal-ship-date-yyyymmdd  pic 9 ( 8 ) value 20170522 .
11      01 nextday-ship-date-yyyymmdd pic 9 ( 8 ) value 20170508 .
12      01 expected-shipping-date     pic 9 ( 8 ) .
13      01 shipping-charge            pic 99v99 value 4.99 .
14
15      procedure division .
16          if shipping-method <> 'FX'
17              move normal-ship-date-yyyymmdd to expected-shipping-date
18          else
19              move nextday-ship-date-yyyymmdd to expected-shipping-date .
20
21          if cust-type = 'EM'
22              move 0 to shipping-charge .
23
24          display expected-shipping-date .
25          display shipping-charge .

即使您以前从未看过COBOL代码,其逻辑也应易于遵循。 如果运送方式为“ FX”,则客户将获得第二天的运送,否则运送需要两个星期。 (这是90年代。)员工获得免费送货; 其他所有人支付$ 4.99。 该代码对我来说看起来是正确的,但是有一个错误-发货日期计算正确,但是向员工收取了全部运费。

问题出在19点末。那个时候,它花费了一些侦探性的工作才能找到答案,但是现代语法高亮的编辑器会立即对其进行标记。 但是为什么这是一个问题呢? 当COBOL对第22行结尾处的那个完全满意时,为什么不喜欢那个时期呢?

句子代替障碍

要回答这个问题,我们需要回到1950年代后期的COBOL起源。 在此之前,大多数语言都是为解决科学和工程问题而设计的,因此它们的语法类似于数学方程式。 (Fortran是这种语言的经典示例。)另一方面,COBOL则用于业务计算。 为了使外行人更容易学习,Grace Hopper和她的国防部团队以及IBM工程师为COBOL提供了英语语法。 COBOL程序具有大多数结构,而不是大多数现代语言具有的递归语法。 COBOL而不是块,将语句组合在一起成为“句子”。 就像英语一样,每个句子都以句点结尾。

尽管从理论上讲这似乎是个好主意,但实际上却是有问题的。 由于流浪期可能会意外终止一个块,因此很难四处移动代码。 周期也很难注意到-在90年代的CRT终端上它们通常只是一个像素。 但是这里存在一个更深层次的问题,一个与最初开发COBOL时程序员如何编写代码有关的问题。

打卡

cobol_在尝试之前不要讨厌COBOL-编程之家

COBOL打Kong卡 ,Rainer Gerhards, CC BY-SA 3.0

设计COBOL时,硬盘的价格过高,因此大多数程序都是在打Kong卡上编写的。 最常见的打Kong卡由12×80网格组成,其中Kong表示1,非Kong表示0。每列是单个12位字符,每张卡是单个80个字符的文本行。 要运行程序,您需要将一副打Kong卡放入读卡器中。 每张卡的前六列和最后八列保留用于序列号和标识符。 这样,如果您放下甲板(可能是您程序的唯一副本),则可以通过机械分拣机喂入卡片,以将卡片放回正确的顺序。

这意味着COBOL会忽略第72列之后的任何字符。如果恰好是一个句点,则代码的整个逻辑可能会更改。 而且,正如您现在无疑已经猜到的那样,第19行的那个时期在第73列。这是COBOL编译器实际上解释这些行的方式:

 16          if shipping-method  <>  'FX' 
17              move normal-ship-date-yyyymmdd to expected-shipping-date
18          else
19              move nextday-ship-date-yyyymmdd to expected-shipping-date
20
21              if cust-type = 'EM'
22                  move 0 to shipping-charge .

一旦发现问题所在,修复起来就很容易:我从第19行的开头删除了一个空白字符,将句点放在第72列。尽管我以前从未遇到过,但这是一个常见的错误许多大型机COBOL程序员会在其终端的第72和73列之间绑一条线程。

今天的COBOL

COBOL-85标准添加了范围终止符(例如end-if) ,因此不再需要句号来结束句子。 尽管许多编译器早在此之前就已支持,但COBOL 2002标准允许使用自由格式的代码。 写入2002标准的相同代码看起来更像是现代编程语言:

 16 if shipping-method  <>  'FX' 
17     move normal-ship-date-yyyymmdd to expected-shipping-date
18 else
19     move nextday-ship-date-yyyymmdd to expected-shipping-date
20 end-if
21
22 if cust-type = 'EM'
23     move 0 to shipping-charge
24 end-if

注意,行首的空白也不再需要。 我通常使用的系统同时支持范围终止符和自由格式代码,因此,在必须对另一个系统进行一些更改之前,我从未遇到过此问题。

对于开源爱好者来说,了解COBOL一直很困难。 传统上,COBOL编译器是开源且昂贵的,并且大多数COBOL代码是在公司环境中编写的。 但是,一个名为OpenCOBOL的开源编译器的工作始于2002年。2013年,它被正式接受为GNU软件包,并更名为GnuCOBOL。 要了解有关GnuCOBOL的更多信息,包括访问400页的程序员指南,请访问项目的主页 。

在Walt Mankowski的演讲“ Punch Card Ate My Program”中了解有关COBOL的更多信息! ,于8月26日在费城举行的FOSSCON上。

翻译自: https://opensource.com/article/17/8/what-about-cobol

cobol