gdiplus::real

个人编程史第二章第二部分

在本系列的最后一篇文章中,我写到了在编程历史的前二十年中,该领域的大多数程序员(即编写在现实生活中使用过的程序的程序员)是自学成才的。 没有为程序员而设的学校,没有正规的实践,没有知识体系,没有学科可言。 程序员要么从导师那里学习,要么追求自己的直觉和直觉。

说明这个现实一个真正愉快的故事是梅尔的故事,发布到新闻组由埃德·纳瑟于1983年梅尔裸机程序员¹。 实际上,“裸机”的术语文件条目就是这个故事。

如果您不了解以下故事中的每个字词或技术细节,请不要担心,您仍然会喜欢它,而且我相信您会明白的。 这是一个非常友善的舌头在脸颊响应有点自我严重的信到回收真实男人不吃上世纪80年代的基切比喻和有权Datamation杂志杂志的编辑真正的程序员不使用PASCAL ²作者声称FORTRAN是“真正的程序员”将使用的唯一语言。 Pascal是一种非常结构化的语言,也许是所有语言中最结构化的语言。 故事结束后,我将对此进行解释。

梅尔的故事

最近一篇致力于编程的“男子气概”方面的文章提出了一个光头而未变的声明:

真正的程序员用Fortran编写。

在这个轻度啤酒时代的衰落时代,也许他们现在已经开始使用手计算器和“用户友好”软件,但是在“美好的旧时光”中,“软件”一词​​听起来很有趣,而Real Computers由鼓和真空管组成,真正的程序员用机器代码编写。 不是Fortran。 不是RATFOR。 甚至不是汇编语言。 机器码。 原始的,未经修饰的,难以理解的十六进制数。 直。

为了避免新一代程序员在对这个辉煌过去的无知中长大,我有责任尽我最大的努力来描述一代程序员如何编写代码。 我称他为梅尔,因为那是他的名字。

我去梅尔(Royal McBee Computer Corp.)工作时初次见到梅尔,这家打字机公司现已倒闭了。 该公司生产了LGP-30,这是一种小型的,便宜的(按当今的标准)鼓式存储计算机,而刚开始生产RPC-4000,这是一种经过改进,更大,更好,更快的鼓式存储设备。电脑。 核心成本太高,而且无论如何都无法保留。 (这就是为什么您没有听说过公司或计算机的原因。)

我被雇用为这个新奇迹编写Fortran编译器,而Mel是我探索奇迹的指南。 梅尔不赞成编译器。

他问:“如果程序不能重写自己的代码,那有什么用?”

梅尔用十六进制编写了公司拥有的最受欢迎的计算机程序。 它在LGP-30上运行,并在计算机展览会上与潜在客户打了二十一点。 其效果始终是戏剧性的。 LGP-30的摊位在每个展会上都挤满了人,IBM销售人员围坐在一起互相交谈。 我们是否从未讨论过这个实际出售的计算机是一个问题。

梅尔的工作是为RPC-4000重新编写二十一点程序。 (端口?这是什么意思?)新计算机具有一种一对一的寻址方案,其中除操作代码和所需操作数的地址外,每条机器指令还具有第二个地址,该第二个地址指示在哪里,在转鼓上,找到了下一条指令。 用现代的话说,每条指令后都跟着去! 将* that *放在Pascal的烟斗中并抽烟。

梅尔(Mel)喜欢RPC-4000,因为他可以优化自己的代码:也就是说,在鼓上找到指令,以便一个完成任务时,下一个就可以到达“读取头”并立即执行。 有一个程序可以做到这一点,即“优化汇编程序”,但梅尔拒绝使用它。

他解释说:“您永远不知道它将放置在什么地方”,因此您必须使用单独的常量。

我很久以前才明白这句话。 由于梅尔知道每个操作代码的数值,并分配了自己的感光鼓地址,因此他编写的每条指令也可以视为数字常数。 如果它具有正确的数值,他可以选择一个较早的“加”指令,然后乘以该指令。 他的代码对其他人来说不容易修改。

我将梅尔的手动优化程序与优化的汇编程序输出的相同代码进行了比较,并且梅尔的运行速度始终更快。 那是因为还没有发明程序设计的“自上而下”的方法,而Mel也不会使用它。 他首先编写了程序循环的最内部部分,因此它们将成为Selenium鼓上最佳地址位置的第一选择。 优化的汇编程序还不够聪明,无法做到这一点。

即使笨拙的Flexowriter要求输出字符之间的延迟才能正常工作,Mel也从未编写过延时循环。 他只是在鼓上放置了指令,所以每一个连续的指令都“过去”了,需要时只是“读”头。 鼓必须再执行一次完整的旋转才能找到下一条指令。 他为这一程序创造了一个难忘的名词。 尽管“最优”是一个绝对术语,例如“独特”,但使其相对成为一种普遍的口头惯例:“不是很理想”或“不太理想”或“不是很理想”。 梅尔称最大时延位置为“最悲观”。

在他完成了二十一点程序并使其运行之后,(“甚至优化了初始化程序,”他自豪地说道)他从销售部门收到了“变更请求”。 该程序使用了一个优雅的(优化的)随机数生成器来混洗“卡片”并从“卡片组”中进行交易,一些销售人员认为这太公平了,因为有时客户会流失。 他们希望梅尔修改程序,以便在控制台上设置感应开关时,他们可以改变赔率并让客户获胜。

梅尔退缩了。 他认为这显然是不诚实的,而且确实影响了他作为程序员的个人诚信,因此他拒绝这样做。 首席销售员与梅尔(Mel),大老板(Big Boss)进行了交谈,并在老板的敦促下与一些资深程序员进行了交谈。 梅尔最终屈服并编写了代码,但他却倒退了测试,当打开感应开关时,程序就会作弊,每次都赢。 梅尔对此感到高兴,声称自己的潜意识是无法控制的道德,并坚决拒绝解决。

在梅尔离开公司以更环保的态度离开之后,大老板让我看一下代码,看看我是否可以找到测试并将其撤消。 我有点勉强地同意看。 跟踪梅尔的代码是一次真正的冒险。

我经常感到编程是一种艺术形式,只有真正精通这项奥术的其他人才能欣赏它的真正价值。 这个过程的本质使人们看不到可爱的宝石和出色的妙招,有时甚至永远无法掩盖。 您可以通过阅读代码(即使是十六进制的代码)也可以学到很多有关个人的知识。 我认为梅尔是一个无名的天才。

也许当我发现一个没有测试的无辜循环时,我最大的震惊就来了。 没有测试。 *没有*。 常识说,它必须是一个闭环,程序将在其中无限循环。 但是,程序控制直接通过它,并安全地从另一端通过。 我花了两个星期才弄清楚。

RPC-4000计算机具有称为索引寄存器的真正现代化的功能。 它允许程序员编写程序循环,该循环使用内部的索引指令。 每次通过时,索引寄存器中的数字都会添加到该指令的地址中,因此它将引用系列中的下一个数据。 他只需要每次都增加索引寄存器。 梅尔从未使用过它。

取而代之的是,他会将指令拉入机器寄存器,在其地址中添加一个,然后将其存储回去。 然后,他将直接从寄存器执行修改后的指令。 编写该循环是为了考虑到这一额外的执行时间-就像该指令完成时一样,下一条正好在感光鼓的读取头下方,可以开始使用。 但是循环中没有测试。

当我注意到索引寄存器位(位于指令字中的地址和操作代码之间的位)被打开时,最重要的线索就出现了-但梅尔从未使用索引寄存器,一直使它为零。 当光亮时,我几乎看不见了。

他将自己正在处理的数据放在内存顶部附近(指令可以寻址的最大位置),因此,在处理完最后一个数据之后,增加指令地址将使其溢出。 进位将向操作码添加一个,从而将其更改为指令集中的下一个:跳转指令。 果然,下一条程序指令位于地址零位置,并且程序顺利进行。

我没有与Mel保持联系,所以我不知道他是否曾经屈服于那些漫长的日子以来淹没于编程技术的变革之潮。 我喜欢认为他没有。 无论如何,给我留下了深刻的印象,以至于我放弃寻找令人讨厌的测试,告诉大老板我找不到它。 他似乎并不感到惊讶。

当我离开公司时,如果您打开正确的感应开关,二十一点程序仍然会作弊,我认为应该是这样。 我对破解Real Programmer的代码感到不自在。

梅尔·凯(Mel Kaye),站在右边。

正如这个故事很好地说明的那样,前几代程序员已经习惯了使用特殊方法和高度个性化的编程风格来按自己的意愿进行操作。 有时候,他们之间对学者及其为促进结构化程序设计所做的努力感到不满。

为了使非程序员的读者受益,结构化编程的概念与编程语言紧密相关,因此人们称其为“结构化编程语言”,有时也简称为“结构化语言”。 在非结构化语言中,代码的格式不会为我们提供有关控制流 (执行语句或指令的顺序)的任何线索。 这是用伪代码 (不是用任何特定计算机语言编写的程序的描述)写成的样子:

1 START PROGRAM2 GET list_of_names from user3 COUNT = number of items in list_of_names4 READ first item from list_of_names5 DO thing a6 DO thing b7 IF result of thing b is TRUE GOTO line 118 DO thing c9 DO thing d10 END IF11 DELETE first item from list_of_names12 SUBTRACT 1 from COUNT13 IF COUNT = 014 EXIT15 END IF16 GOTO LINE 417 END IF18 END PROGRAM

只要列表中有要处理的名称,该代码就会循环,如果第7行的结果“评估”为TRUE,它将跳过第8和9行。 只需看一眼,该代码的结构就不会告诉您。 您必须逐行阅读才能知道。 即使这样,也没有线索告诉您第8和9行是特殊情况,“事物b的结果”通常为TRUE。

“结构化语言”将是不提供GOTO指令(上面的第7和16行),而是提供诸如WHILE和FUNCTION之类的更高级概念的语言,如下例所示:

START PROGRAMGET list_of_names from user

WHILE list_of_names is not empty    READ first item from list_of_names    DO thing a    DO thing b

IF result of thing b is TRUE        DO somethingSpecial    END IF

DELETE first item from list_of_namesEND WHILE

FUNCTION somethingSpecial    DO thing c    DO thing dEND FUNCTION

END PROGRAM

这两个例子做同样的事情。 但是,结构化编程的支持者认为,第二种方法更具可读性,更不易出错,并且更容易/更快地编写,因此提高了生产率。 尤其重要的是可读性,因为在发生这种情况时,程序员要花更多的时间阅读已经编写的代码(即使是自己编写的代码),而不是编写代码。³

在60年代,Dijkstra发表了七篇论文。 在1996年对一千多名计算机科学教授进行的民意测验中,其中四篇论文被选为有史以来有关计算机科学的38篇最具影响力的论文之一。 但是到目前为止,他最著名的贡献是为防御结构化编程而写的五页短信,该信于1968年发送给当时计算机科学领域的领先刊物《计算机协会杂志的编辑。 迪克斯特拉(Dijkstra)寄来了一封标题不切实际的信: 《反对Goto声明的案例》 ,但编辑Niklaus Wirth(于1970年创立了Pascal)用当时流行的新闻陈词滥调地将标题更改为Go To Statement About Harmonful。

给编辑的这封信引起了至少二十年的争论,并且(可能)仍然是有史以来最知名的(但可能读得最少的)计算机科学文章。 寻找当代的引文和讨论不必走远。 该出版物在许多方面都具有重要意义,尤其是它引发了最早的(也许是第一个) 好家伙其中宗教战争 真正的程序员不使用PASCAL梅尔的故事都只是小例子。 从1970年起,狂热的倡导和极权主义者对竞争性概念模型的至高无上的主张将标志着编程的进步。

编程(可能比其他任何应用科学都重要)激发了对完美和纯净的狂热追求。 弗雷德·布鲁克斯(Fred Brooks)提出,这可能是由于以下事实:“ 程序员,就像诗人一样,只不过从纯思想领域中删除了一点。 他凭空发挥想象力,在空中建造自己的城堡。 很少有创作媒介如此灵活,易于抛光和返工,因此很容易实现宏伟的概念结构。”⁹

商业内幕 》 ( Business Insider)在2015年发表的一篇文章对“ 程序员为什么要在编程语言上进行'宗教战争' ”的浪漫解释,说:“ ……每种编程语言都代表着一种哲学,就像代表一种产品一样。”

自从发表《认为有害的声明》以来,就没有缺乏发动战争的理由。 在其出版之前,仅创建了200种语言,但是从那时起,又产生了数千种语言。

在本系列文章中,我将不再写许多重要的语言,因为我特别关注企业IT和IT项目失败。 例如,我喜欢Python和Ruby语言,但是它们在公司IT和项目失败中没有扮演重要角色。 相反,您会发现研究人员正在使用Python进行数据挖掘和人工智能。 此外,Python和Ruby都经常出现在Google,Dropbox或Uber这样的互联网公司中,而在创业公司中也很常见。

照明和边缘

我认为1949年后的头二十年是编程的黑暗时代。 从那时起,没有多少历史文献可供编程 。 有关计算机本身的历史文档很多。 如我先前所写,硬件工程受到高度尊重和认可。 电气工程行业的组织得很好,有据可查,并且被认为非常重要。 然而程序员却默默无闻。

典型的程序员是自学成才,并且具有很高的内在动力。 除了少数年轻的神童外,程序员比以前受过高等教育的可能性更高,他们通常拥有硕士或博士学位,这就是他们成为计算机的起点。 他们往往是非常聪明的一群。

没有面向程序员的学校或课程,当计算机耗资数百万美元时,就不会有临时的程序员。 仅仅由于当时成为一名程序员有多么困难,它们才是人类最耀眼的光芒。

对于我们所知道的每一个Dijkstra或Knuth或Wirth,都有一千个Mels,他们创造出纯净的天才,优雅和稀有之美的作品,这些东西将永远丢失,因为磁带和打Kong卡保留了最深刻的思想。隐藏的一代变得过时了,被毫不客气地装在了盒子里,看不见了。“程序员的麻烦是,在为时已晚之前,您永远无法说出程序员在做什么。”

〜西摩·克雷
克雷超级计算机的发明者

<-上一章

下一章->

[1] Post,Ed(1983年7月)。 “真正的程序员不使用Pascal” 数据化 原始内容 存档 于2012-02-02)。 “……真正的程序员使用FORTRAN。 吃乳蛋饼的人使用PASCAL…”

[2] Martin,Robert C.和Lei Han。 干净的代码。 电子工业出版社,2012

[3] http://www.catb.org/jargon/html/H/holy-wars.html

[4] Brooks,Frederick P. 神话般的月刊和其他有关软件工程的文章 。 教堂山,北卡罗来纳大学教堂山分校计算机科学系,1974年,第21页

[5] http://www.businessinsider.com/why-coders-get-into-religious-wars-over-programming-languages-2015-6

本文摘自我即将出版的《混沌工厂》 ,该书解释了为什么大多数公司和政府无法编写“有效”的软件,以及如何对其进行修复。

翻译自: https://hackernoon.com/the-second-decade-of-programming-all-about-real-programmers-2556758b5e51

gdiplus::real

gdiplus::real_编程的第二个十年:关于Real™编程器的全部相关推荐

  1. 编程的第二个十年:关于Real™编程器的全部

    个人编程史第二章第二部分 在本系列的最后一篇文章中,我写了关于编程历史的前二十年,该领域的大多数程序员(自学成才的人)是如何自学的. 没有程序员的学校,没有正式的实践,没有知识体系,没有学科可言. 程 ...

  2. python对象编程例子-python(十二)面向对象编程、类

    面向对象编程 面向对象--Object Oriented Programming,简称oop,是一种程序设计思想.在说面向对象之前,先说一下什么是编程范式,编程范式你按照什么方式来去编程,去实现一个功 ...

  3. 歌词big big no_编程的第二个十年:Big Iron

    歌词big big no 个人编程史的第二章 恐龙在地球上漫游¹ 第一台计算机一天要花费数百万美元,相当于今天的数千万美元. 促使他们成立的公司一年最多只能卖出几十个. 计算机本身(称为大型机)和制造 ...

  4. C语言编程>第二十周 ② 下列给定程序中,函数fun的功能是:求出数组中最大数和次最大数,并把最大数和b[0]中的数对调、次最大数和b[1]中的数对调。

    例题:下列给定程序中,函数fun的功能是:求出数组中最大数和次最大数,并把最大数和b[0]中的数对调.次最大数和b[1]中的数对调. 注意:不要改动main函数,不能增行或删行,也不能更改程序的结构. ...

  5. C语言编程>第二十二周 ④ 从键盘输入一组小写字母,保存在字符数组str中,请补充fun函数,该函数的功能是:把字符数组str中字符下标为偶数的小写字母转换成对应的大写字母,结果仍保存在原数组

    例题:从键盘输入一组小写字母,保存在字符数组str中,请补充fun函数,该函数的功能是:把字符数组str中字符下标为偶数的小写字母转换成对应的大写字母,结果仍保存在原数组中. 例如,输入 " ...

  6. C语言编程>第二十二周 ⑥ 请补充fun函数,该函数的功能是:把字符下标能被2和3同时整除的字符从字符串s中删除,把剩余的字符重新保存在字符串s中。

    例题:请补充fun函数,该函数的功能是:把字符下标能被2和3同时整除的字符从字符串s中删除,把剩余的字符重新保存在字符串s中.字符串s从键盘输入,其长度作为参数传入fun函数. 例如,输入 " ...

  7. C语言编程>第二十六周 ⑥ 请补充fun函数,该函数的功能是:按 “0”到 “9”统计一个字符串中的奇数数字字符各自出现的次数,结果保存在数组num中。注意:不能使用字符串库函数。

    例题:请补充fun函数,该函数的功能是:按 "0"到 "9"统计一个字符串中的奇数数字字符各自出现的次数,结果保存在数组num中.注意:不能使用字符串库函数. ...

  8. C语言编程>第二十二周 ③ 下列给定的程序中,函数fun的功能是根据整型形参n,计算如下公式的值:

    例题:下列给定的程序中,函数fun的功能是根据整型形参n,计算如下公式的值: 例如,若n=1000,则应输出0.000155. 注意:不要改动main函数,不能增行或删行,也不能更改程序的结构. 代码 ...

  9. C语言编程>第二十六周 ① 函数fun的功能是:将形参b所指数组中的前半部分元素的值和后半部分元素的值对换。形参n中存放数组中数据的个数,若n为奇数,则中间的元素不动。

    例题:函数fun的功能是:将形参b所指数组中的前半部分元素的值和后半部分元素的值对换.形参n中存放数组中数据的个数,若n为奇数,则中间的元素不动. 例如,若a所指数组中的数据依次为:11 22 33 ...

最新文章

  1. 【转】通过Hibernate将数据 存入oracle数据库例子
  2. 【EMC】电磁兼容性相关名词解释、基础知识
  3. 技术网站 --人人都是产品经理
  4. 漂洋过海来看你 可惜Uber不便宜
  5. 重构战略到执行的绩效管理体系
  6. Python 字符串与列表去重
  7. i.mx6 Android5.1.1 servicemanager本地服务
  8. class vue 添加图片_vue+element 添加图片组件
  9. Zookeeper java客户端ZkClient使用详解
  10. cout输出16进制_c++随堂测16优化方案
  11. 让普通用户可以kill自己用户下的session(转)
  12. 蓝桥杯 入门训练 Fibonacci数列
  13. spark机器学习电影推荐
  14. C#调用三菱的MX Component控件与三菱PLC进行通讯
  15. 数学中常见的曲面方程及形状
  16. C语言|temp=a,a=b,b=temp;|同行语句可以用逗号隔开
  17. Go 的时间转换和时区校对总记不住?给你一份备忘单
  18. 安装Aras Innovator12 sp9全过程
  19. Android四大组件-Boardcast
  20. linux开机启动出现grup,开机出现grub解决方法

热门文章

  1. 网络通讯学习(3)-----UDP通讯(仅了解)
  2. Hbase的二级索引和RowKey的设计
  3. bin文件夹是个什么东西?
  4. 【钉钉-场景化能力包】企业系统和钉钉工作流打通
  5. pytorch中fuse_modules
  6. 苏州技师学院计算机专业怎么样,苏州技师学院是怎样的一个学校
  7. 临时表空间不足ORA-01652: unable to extend temp segment by 64 in tablespace
  8. matlab:反三角函数
  9. 香港武侠电影十大金曲
  10. 三种数据库的 SQL 注入详解