上海英语培训费用联盟

三分钟聊一聊计算机发明前的编程 | 写代码容易,编程并不容易

STEAM解密2018-04-15 20:00:33

编程到底在多早就出现了呢?在大约公元60年的古希腊,一位发明家,亚历山大的希罗,设计了一款通过绕绳让小车按特定路线行走的三轮车。科学家根据历史文献复现了这部“可编程”三轮车。三轮车的两个对称轮有可以独立旋转的轴承,给三轮车的编程就通过在轴承上的绕绳方式来实现。轴承上钉有钉子,绳子可以通过钉子实现反向绕绳。绳子的另一头绕过一个滑轮挂有重物。当绳子在轴承上绕了多圈后,重物被拉起,这时绕绳的人松手,重物会拉动绳子,绳子再带动轴承旋转。两个轴承通过正转和反转的组合搭配,就实现了三轮车的转弯或走直线。

在古代中国,人们也发明了自动计算路程的工具,这就是汉代的记里鼓车,车中安装了精巧的机械装置,每前进一里,车上木制机械人就敲鼓一次,每前进十里,机械人就敲一次铃铛。通过这种方法,人们就能知道路程是多少。这些“程序”只能固化在机械结构中,无法进行自由改动,所以还不能称之为真正的程序,但这些自动操作机械的方法孕育了编程的思想。

到了十九世纪,工业革命的技术飞跃让人们能够生产更精密的机械,也对机械自动化运作提出了更高的需求。十九世纪的钟表匠将机械制作推向极致,例如这个自动写字机械人偶,在如此小的体积内容纳了大量的机械零件,人偶可以自动地纸上写下优美的文字。

与此同时,还诞生了另一类不同的机器,通过打孔纸带,人们能够控制机器制造出不同的东西。最典型的案例是法国人雅卡尔发明的提花织布机,它有一个接口可以嵌入打孔纸带,通过纸带中坑洞的不同位置,指令织布机作出不同的动作,编织出不同的图案。尽管提花是一个复杂的过程,但它的本质是重复的操作,所以能够交给机械完成。这时候我们已经可以看到编程的曙光。

第一个公认的程序出现在十九世纪中叶。英国科学家巴贝奇从提花织布机中获取灵感,设计出能够进行通用技术的差分机和分析机。分析机能够通过输入特定数值,机器每运转一轮进行一次函数运算,输出计算结果。由于种种因素,巴贝奇最终没有完成分析机的制作。当时拜伦之女埃达·洛夫莱斯与巴贝奇合作,为分析机写的一段关于伯努利数的算法,这段算法成为第一个计算机程序,埃达也被称为第一个程序员。

随着第二次工业革命中电力被广泛应用,人们在二十世纪中期发明出电力引导的计算机,编程迎来了它的的寒武纪生命大爆发。只有认识了计算机发明前的编程发展史,我们才更能够深刻地理解编程是什么,更好地开展科技教育。



当我的编程生涯开始的时候,我认为“编程很简单……怎么会需要去学校学习呢?”但经过学习和实践,我了解到编程很难。

不知道是编程不难还是我什么都不懂。 ~MemeGenerator.net

自我评价对我自己来说一直都很重要,因为在一天结束的时候,不管别人怎么想,自己的想法都很重要。我会在评价中思考强项、弱项、学习、训练和个人成长。这个过程让我反思、理解并思考成为一个程序员究竟意味着什么。

教育:编码?编程?关键性的抨击?

我在技术领域的第一份工作主要是通过 HTML、CSS 和 JavaScript 操作一些元素并创建视觉效果。在这段时间里,我没有真正想到自己是一个程序员,对于这个问题,我从来没有想要成为一个真正的程序员。不久以后我想使用 NodeJS、PHP 和 MySQL 做更多事情,这时候我开始考虑这个问题。把我作为程序员的所有宏伟想法加起在一起,我在第一份工作中把自己当作一个小小的“软件工程师”,一直都在积极地制定方案。

“经验告诉我,我会颇具气势地拍、打和敲击键盘,但那并不是编程。”

编程需要思考和理解各种数据类型、结构,并理解编程语言赖以构建服务的技术。差异主要在于完成特定任务时所使用的流程。重点不在于数据类型、设计模式、算法类型、性能或任何与代码和应用程序质量相关的内容。相反,它被纳入了实际的工作机制和技艺之中,这往往需要耗费大量的时间,最终变成一只难以维护的巨兽。一直运行输出到不同地方,并积极地测试输出,直到它非常类似于一个功能。如果有什么事情给我一种编程的感觉,但我在实际操作中并没有做到将想法付诸行动。

思考数据

数据结构是我感受到教育不足的一个方面。数据结构背后的想法是,你有不同的方法去存储、提取、排序和搜索数据。最初当我开始编程,我从来没有想过各种数据的任务与数据类型的性能。对需要存储、排序或遍历的任何事物,通常默认使用数组(包括哈希、json、字典,以及键-值数据集的其他术语)。

从计算机科学的角度看,集合、堆栈和队列对我来说是很有趣的,但在 Ruby 编程语言中看到一些实际操作之后,对我来说并不那么吸引人。在我看来,堆栈和队列是一样的,它们允许你从数据的末端获取信息,队列的例外情况是,你只能按照它们加入的顺序获得这些项。当我开始想象这一点时,我想把东西放在一个列表中,等待处理,减少可在后台运行的任务的开销。事实上在高层次的编程语言如 Ruby 中对此付诸实践,并没有多大意义,因为它基本上是在往数组中 push(后追加)或 unshift(前添加)元素。

它的简单性是基于一个非常简单的数组,这本身就体现了它的美。我看到自己在命令行脚本中使用栈或队列,但我不确定还可以在别的什么地方使用它们。

二叉搜索树在处理搜索数据的时间和速度上吸引了我。我经常发现从数据中获取数据非常容易,但在数组中搜索需要花大量时间。这就是为什么需要二叉搜索树,我非常喜欢哈佛的这段视频。虽然我并没有使用这些东西来做过什么,但是非常想用它们来实现点东西,然后将之与原生 Ruby 的数组方法进行比较,看看二叉树比普通的数组或哈希快多少。我在关于二叉权势的研究中试图找到实际的用例,于是发现了这些有意思的文章。

  • 搜索字符串 — 来源于 yuya-takeyama 的 Gist

  • 数值搜索 — 来源于 Zach Kemp

可维护性

我的第一个 Web 应用在可维护性方面可笑极了。没有编码规范,没有设计模式,没有对定义的方法进行整理,没有使用命名空间,也没有对象和模型。如果一定要我去修复缺陷(肯定会有),与其去找实际导致缺陷的方法,还不如重写来得快些。

设计拙劣导致乱糟糟的代码。

我难以处理的问题之一是条件嵌套和循环嵌套。这些循环中存在大量的 if 语句和验证,但这个问题本身来源于一个系统性的问题,即不清楚怎样恰当地组织和拆分程序的不同部分。我曾尝试着在一个巨大的方法中处理所有事情,不关心哪些代码可以重用,也没创建一个模块来扩展对象和方法的功能。为了节省篇幅,下面的代码截取自真实的代码。我不会把责任推到别人身上,这段坏代码是我写的,我会承认这一点,然而其中一些本来可以通过代码导师、或者通过代码审查和“拉”请求来加以缓解。回顾这段代码,我感到惭愧,但这是一件好事,因为它表明了我作为一个开发人员的成长程度。自由在某些意义上是一个问题,但不是在其他方面。例如,对这个项目我被限制于使用 LAMP 技术栈,这是不容协商的,但与此同时,这真的是唯一的限制。我没有使用设计模式,遵循任何风格指南, 使用代码分析器,或遵循代码公约的任何政策。这就创建了一个系统,你可以自由地使用自己的设备,并且如果你还没有了解应用程序的长期性和错误修复,那么它会损害你的最终结果。

我已经真正体会到了文本编辑器的好处,在你编写代码时它会给出提示(指出潜在的错误)从而为你节省很多时间,同时我也开始欣赏与编程相关的一些美好细节。一个写得很好的代码库,会遵循文档标准、清晰的约定和风格指南,阅读起来就像一封电子邮件或一篇网文那样流畅。

 

测试驱动开发

在我看来,测试驱动开发的好处足以证明其优点,但我明白,并不是每个人都同意测试为代码库提供任何价值。我不会争论测试的有效性,但我确实想分享它如何帮到我。在实际创建代码之前,为代码编写集成测试和单元测试已经在很多方面帮到我。它帮助我编写更整洁的代码,高效地编写代码,并帮助我解决了我遇到麻烦的问题。

编写更整洁、更高效的代码与编程中的许多事情有交叉。可读性、性能和编码时间是 TDD 帮到我的主要方面。我发现我能编写代码,不必重构(多次)使其可以上生产线或进入版本控制库。它不仅帮助我减少了 bug,而且帮助我减少了跟踪和修复 bug 所花费的时间。修复 bug 时,我发现我可以接受预期的输入或输出,编写一个与之匹配的测试,然后努力使该测试和所有其他测试通过。这样可以消除 bug,并确保代码实现其预期的目的。

在开始编写实际的方法或对象之前,TDD 可以帮助我组织思路。在更复杂的功能中,它可以帮助我将功能分解成其需要正常工作的集。也就是说,边界条件就是边界条件,并且在最初创建代码时往往更难于考虑到边界情况。最终我觉得测试驱动开发有助于使我成为更好的程序员。



长按下图二维码添加公众号,获得更多有价值信息。


Copyright © 上海英语培训费用联盟@2017