尽管软件开发过程很复杂,但这些年来它已经变得更好了。“成熟的”程序员记得过去有多少事情需要人工干预和手工调优。如今的软件开发工具可以自动执行复杂的功能,而这些功能曾经是程序员必须明确编写的。大多数开发者都为此感到高兴!
年轻的自以为是的人甚至可能没有意识到我们这些老古董必须手工做这些事情。这些函数仍然存在于您编写的软件中,一些专门的程序员,如Linux内核开发人员,继续手工应用这些技术。然而,大多数人依赖于内置库、操作系统或开发环境的其他部分提供的功能。
让我们花一点时间来欣赏事情有了多大的改善。在本文中,我询问了几位资深开发人员关于他们最头疼的老派编程问题,并添加了许多我自己的问题。加入我们的行列,让我们沉浸在怀旧中,展示我们的伤疤——然后告诉我们你很高兴自己留在了开发技术文章的评论.
排序算法和其他手工编码的繁琐东西
您现在编写的应用程序需要对数据进行排序,但您所要做的只是调用一个排序例程。但直到20世纪80年代,程序员们还在为排序算法而激烈争论:二叉树和修改后的冒泡排序在50步!
开发者不仅需要选择一种算法;我们每次都得重新写代码。Donald Knuth写了关于这个主题的整卷书在他的“计算机编程的艺术”系列中;你不是一个真正的程序员,除非你想买那本书。
荣誉奖:
- 自己实现链表或哈希表
- 用于SOAP部署的手工编码XML
- 选择直接文件访问,如顺序,直接访问,索引访问
创建自己的图形用户界面
文本模式界面曾经统治着地球。直到20世纪80年代的某个时候,甚至可以说是90年代,任何想要创建窗口系统的开发者都要编写自己的窗口抽象,并在CGA、EGA和VGA卡上进行测试,就像现在在Firefox、IE和Safari上测试一样(我希望如此)。或者她买了一个昂贵的附加窗口库,仍然连续几天摆弄设置。
难怪这么多“界面”由“输入1添加记录,2编辑记录,3删除记录”组成。
现在,要创建GUI,您可以使用内置在您最喜欢的IDE (集成开发环境)或使用独立的工具进行GUI设计。您可以拖放组件,调用一些函数,并声明一些逻辑。它的魔法。
Go To和意大利面条代码…
...或者实际上,在结构化编程和面向对象开发出现之前的任何编程方法——除了当时只有严谨的学者使用“方法论”这样的词之外我们大多数人都没有大学学位.
在许多早期的编程语言中,应用程序流是由GOTO 10之类的指令控制的,因此代码会跳转到Label 10(可能出现,也可能不会出现在9到11之间),并继续执行。跳过并进入代码是非常容易的,创建了一个可执行代码的Gordian knot,这成为了一个维护偏头痛,并产生了一个贬义术语“意大利面条式代码."
结构化程序设计,它认为代码可以分为决策、序列和循环,“在70年代是天赐之物……比它所取代的‘先写代码,后设计’的方法要好得多,”当时的Cobol程序员杰伊·埃尔克斯(Jay Elkes)说。(然而,我必须指出,1968年结构化编程支持者Edsger Dijkstra撰写的开创性文章“Go To Statement Considered Harmful”产生了太多的问题"...认为有害”的模仿.)
较新的面向对象语言,从90年代早期的c++开始,消除了对结构化编程的需求——这并没有阻止一些开发人员进行完整的循环重塑自己的Go To.
手动多线程和多任务处理
今天,我们期望计算机通过多任务(在一个操作系统上运行多个进程)和多线程(运行多个进程,或者线程的执行,在程序中)。但早期的PC操作系统,如CP/M和MS-DOS,都是一次只做一件事。
拥有专业知识的优秀程序员可以破解替代方案,但这是一种混乱而痛苦的体验。例如,C程序员可能会使用setjump和longjump来实现线程,这是一个漫长的调试周末,同时还要喝至少三壶咖啡的方法。
多线程仍然不容易,但是开发工具和操作系统已经简化了这个过程。例如,自从Windows 2000推出以来,开发人员已经能够使用重叠I / ONova Enterprise Systems首席顾问Dan Rosanova指出:他指出,这“比旧的‘启动x线程来完成y线程’要好得多”。
荣誉奖:
编写终止驻留(TSR)例程,这是一种早期和非常流行的方法多任务处理,在ms - dos。软件开发人员Mark W. Schumann回忆道:“一个系统调用——当你调用Interrupt 21h时留下的一组寄存器设置——有将控制权返回给DOS的效果,但将你的代码留在分配的堆空间中。重要的结果他在大学时就开始制作DEC PDP-11。
“如果您也重定向,例如,Interrupt 9——键盘处理程序——指向您自己的代码,然后链接回原始中断向量,那么您的代码将在正常处理击键之前执行,”Schumann继续说。“过去,你就是这样编写弹出式程序的。你必须小心文件系统操作,因为DOS本身是不可重入的,你必须让你的代码超快,这样它就不会掩盖下一个中断。”
变为无效来代码
在20世纪60年代,当内存以“K”(1024字节)来衡量时,程序员想尽一切办法把10磅的代码塞进5磅的计算能力包里。一个例子是,编写的程序在运行时改变自己的指令。例如,我的一个编程朋友通过将(汇编语言)执行向右移动一位,将7K打印驱动程序放入5K。其中一些解决方案非常优雅,但维护起来却是一场噩梦。
这个主题有好几种变体。一个程序员回忆说,把一个寄存器的内容作为另一个寄存器的数据使用。另一种技术是编写堆栈修改代码,作为绕过语言生成限制的捷径。
相关的项目
在糟糕的情况下,你可能需要在程序还在运行时给它打补丁。这可能需要拨动电脑前面板上的开关(是的,我们有)来修改指令或数据。
或者,您可以连接到一个重要的守护进程(比如打印假脱机程序),手动组装代码,将其放置在内存的一些未使用的部分,然后在程序的活动区域修补一个跳转指令,以分支到您的新代码。如果你犯了一个错误,砰!
另外,您必须记住在源代码中再次进行相同的更改并重新编译,否则在下次重新启动系统时,您将再次执行相同的操作,这可能是在几个月之后,在您忘记了自己所做的事情之后。
内存管理
直到过去的十年左右,RAM和存储空间都非常有限,所以高效的编程需要令人印象深刻但耗时的解决方案。例如,开发人员不得不花费大量时间跟踪内存分配和回收——这个过程后来被称为“垃圾收集”。否则,他们将花费大量时间修复最终导致计算机崩溃的内存泄漏(无意的内存消耗)。
早期的垃圾收集例程,比如最初的Ada编译器中的那些,在清理内存时基本上会冻结计算机;对于试图为飞机驾驶舱编写软件的开发人员来说,这并不是有用的行为。今天,几乎每个开发环境都有一个像样的垃圾收集器。
但是PC的内存管理需要更多的关注细节。不是使用应用程序编程接口(API)写入屏幕,而是通过内存块复制操作将字符(以及它们的属性字节)放在屏幕上,直接写入硬件。一位程序员记得,在Apple II上,你写道:位传图函数,将两个或多个位图合并成一个,以处理苹果奇怪的图形存储映射。
穿孔卡片和其他早期开发环境
今天,你的打字速度可能比你的击键精度更重要。但在那个一切都是用霍勒里斯卡片打孔的时代(至少整个20世纪70年代),情况并非如此。撞到错误的关键,卡片就毁了;你必须重新开始,或者用透明胶带和小纸片来修补。
大多数开发人员都学会了包含行号,即使语言并不需要行号,这样卡片(不可避免地)被丢弃后还能被重新拾起。卡片有多种颜色可供选择,允许对一副牌的不同部分进行颜色编码,如JCL(作业控制语言)、程序源和数据。另一种技巧是在牌组上用魔术记号笔写下程序名称,如果一张牌出了问题,就会给你一个快速的视觉提示。
荣誉奖:
- Non-WYSIWYG编辑平台。我们中的一些人仍然习惯使用vi/ emacs、命令行编译选项或.nroff文档格式,但最初我们程序员没有选择。
- 文件名的8个字符限制,这无疑使编写自文档化代码变得困难。
- APL键盘。APL在当时是一种伟大的编程语言,但它的符号需要一个特殊的键盘,而且比大多数没用的Windows图标更难记住。
- 内存转储。如果你的代码崩溃了,大型机会打印出至少100页的绿条,显示内存的全部内容。埃尔克斯苦笑着回忆道,你必须在整个冗长的列表中筛选,才能知道自己曾尝试过除以0。专业的程序员学习了用DEADBEEF(一个“可读的”十六进制值)填充内存的调试技术,以帮助他们找到core-walker(相当于内存泄漏的大型机)。
指针数学和日期转换
与排序和哈希算法一样,在cpu数量有限的时代(直到90年代),所有数学函数都是留给开发者的。您可能需要在8位处理器上模拟16位数学指令。您编写代码来确定用户的PC是否具有8087数学协处理器,只有在明确编写代码来利用它的情况下,才能显著提高性能。有时你不得不使用位移和查找表来“猜测”浮点数学和三角函数例程。
这也不仅仅是简单的数学。每个开发人员都必须使用Julian日期转换进行日期计算(即“从今天算起的三周是什么时间?”),包括计算复活节是什么时候,并根据闰年进行调整。(并不是每个开发者都有算出闰年即使现在)。
匈牙利符号和其他语言限制
归功于微软的查尔斯·西蒙尼匈牙利表示法是一种命名惯例,主要用于为Windows编写程序。
它向标识符名称添加前缀以指示其函数类型。例如,"pX"表示函数是指向x的指针。如果你改变了标识符的类型,你必须重命名变量;这导致了一些丑陋的补丁。
尽管一些开发人员今天仍在使用匈牙利表示法,但这通常是不必要的;大多数文本编辑器会立即告诉您变量类型。
荣誉奖:
- Fortran的格式化输入和绑定到类型的变量名(以I、J和K开头的变量总是整数)
- 需要行号的BASIC代码
- 将所有变量初始化为已知值
- Null-terminating C字符串
做一些奇怪的事情让代码运行得更快
在编程(相对而言)的早期历史中,通常依赖于未归档的特性,比如早期的Windows API。Visual Basic编程需要侵入Windows的内部,其中很多都是非法入侵。当然,每当微软发布新版本的Windows时,这些黑客就会经常被攻破,有时只是因为安全补丁。
如今,每件事都有很好的文件记录,都是值得信赖的。是的。确实是这样。
荣誉奖:
- 编写自己的实用程序来搜索在哪里使用了函数或过程,以及在哪里调用了它们
- 手动优化编译器生成的代码,以满足项目的性能目标
- 在BASIC解释器中使用单字母变量名,因为可以看到执行速度的提高
被病人
很难解释当时编程的速度有多慢。你开始编译,然后去吃午饭。当编译时间花了几个小时时,您可以编写尽可能多的代码,然后进入一个多部分调试会话。
不幸的是,正如大多数程序员所知道的,您搅乱的东西越多,就越难找到导致问题的bug。不是一次编写和调试一个例程,而是花了数周的时间来编写和测试代码。
为了加快开发时间,程序员会在早上的某个不合适的时间到达办公室,在大型机上占用专门的时间(如果他们没有在分时系统上按CPU周期付费的话)。
长调试周期的唯一好处是,它让程序员思考他们的代码,而不是把它们拼凑在一起。我们有时间吃午饭。
还有什么?
哪些老式的编程技能是你今天不需要的?请在评论中告诉我们。
Esther schindler从1992年开始写有关技术的文章,1973年开始编程。她不承认在这个故事中她使用了多少技巧,但她仍然有一些Hollerith卡片在周围漂浮。
这篇题为“你可能不会错过的老派编程技术”的文章最初是由《计算机世界》 .