acm-header
登录

ACM通信

BLOG@CACM

教学实际的编程


Philip Guo 2012年11月爆头

在这篇文章中,我将描述一种普遍存在的编程风格,据我所知,这种风格从未在课堂上正式教授过。

在大多数编程课上,学生用一种语言(如Java、Python)及其标准库编写程序;他们可能会使用文档完善的第三方库,比如图形库。学生填写导师提供的框架代码模板,或者最多“从头开始”编写一些代码块。规范和接口被清晰地定义,并且使用自动化测试套件对任务进行分级,以验证规范的符合性。

我刚才所描述的内容对于向初学者介绍基本编程和软件工程概念是必要的。但这与这些学生以后必须在现实世界中进行的编程几乎没有相似之处。

在我过去十年的编程生涯中,我建立过研究原型,扩展过开源软件项目,在初创公司中交付过产品,在大公司中从事过正式的软件工程实践。不管设定如何,以下是我和同事在开始一个新项目时采取的典型步骤:

1.饲料:找到现有的代码片段来构建我的项目。这可能包括我过去写的代码,或者同事在不同阶段发给我的代码数据腐败.如果幸运的话,我可以找到一个软件库,它可以实现我想要的一些功能;如果我足够幸运,它会附带有用的文档。几乎没有人再“从零开始”编写现实世界的项目;现代程序员通常从现有项目中寻找部分。

2.修改:使用这些现有代码片段来评估它们的功能和限制。这个过程包括在各种输入上编译和运行代码,插入“print”语句以了解某些行何时执行以及执行的值是什么,然后调整代码以查看其行为如何变化以及何时中断。

(现在在第1步和第2步之间循环,直到我对项目的构建块选择感到满意。然后进行第3步。)

3.焊接:尝试将现有代码片段相互连接(“焊接”)。由于缺少或相互冲突的依赖关系,我可能要花费大量时间来编译和链接这些片段。阻抗不匹配是不可避免的:很有可能,我刚刚焊接在一起的代码从来没有被设计成可以“很好地”与其他代码一起使用,或适合我的项目的特殊需求。

4.成长: Hack up一些硬编码的例子,我的新代码接口与现有的“焊接”代码。在这一点上,我的新代码是草率的,一点也不抽象,但这没关系——我只是想让事情尽可能快地工作。在这个过程中,我调试了我的代码和外部代码之间的许多特殊交互。与极端案例较劲已成为我日常工作的一部分。

5.怀疑:当实现一个新特性时,我经常问自己:“我需要自己编写这部分代码吗?还是有一些惯用的方法可以使用现有的代码库来实现我的目标?”我不想重复工作,但是很难弄清楚现有的代码是否可以被塑造成我想要的样子。如果幸运的话,我可以向外部代码的作者寻求帮助;但我尽量不抱太大希望,因为他们在设计代码时可能没有考虑到我的特定用例。的海湾的执行概念上简单的功能需要比预期的更长的时间来实现。

6.重构注意代码中的模式和冗余,然后创建抽象来泛化、清理和模块化代码。随着我逐渐重构,我的代码和外部代码之间的接口开始感觉更清晰,我也对下一步在哪里抽象有了更好的直觉。最终,我“打磨”了第4步中开始的代码片段之间的大部分粗糙边缘。

(现在重复步骤4到6,直到我的项目完成。)

对于这种编程风格,我没有一个好名字,所以我很感激任何建议。最接近的是投机取巧的编程我和我的同事在我们的气2009年的论文在那里我们研究了网络程序员搜集信息的习惯。而且,我创造了这个术语研究编程在我博士论文但上述六步法在研究实验室之外也很普遍。(一位读者建议使用这个词能够进行.)

目前,学生们不是通过正式的CS课程,而是通过研究项目、暑期实习和业余爱好来学习这些动手编程技能。

一种观点认为,目前的现状已经足够了:计算机科学课程应该侧重于教学理论、算法设计、问题分解和工程方法论。毕竟,“CS ! =编程”,对吧?

但相反的观点是,教师应该直接说明现实世界的编程——CS最直接的应用——往往是一种混乱和特殊的努力;现代编程更多的是一门手艺和经验科学,而不是数学上美丽的形式主义的集合。

教师如何实现这一目标?可能是通过基于项目的课程、同伴辅导、结对编程、一对一指导或教学代码评审。一个出发点是思考如何教授更一般的知识概念原位当学生遇到本文中描述的六步过程的特定部分时。例如,“代码焊接”能教会学生API设计方面的什么?关于模块化和测试,重构能教会学生什么?调试能教给学生什么科学的方法?

我之前在中国科学院的职位是。”教一个高度积极的初学者编程,这是对这种动手教学方式的一次尝试。然而,目前还不清楚如何将这种一次性体验扩展到满是学生的教室(或部门)。主要的挑战是在让学生接触到真实世界编程的本质,同时又在教他们强大的、可推广的CS原理之间取得微妙的平衡。


评论


Kayur帕特尔

在过去的一年里,我花了相当多的时间思考人们如何实际构建代码和我们如何在课堂上教授编程之间的脱节。本文涉及到我已经考虑过的一些相同的观点,特别是关于当今编程越来越多地涉及到信息搜集和现有解决方案的组合这一事实。这个过程是通过实验和迭代来定义的。

这也更像是一项社交任务,在线资源和同伴提供了越来越多的支持。当我开始我的新工作——为goog人编写代码时,我一直在思考这些因素。与许多大公司一样,这里有大量的现有代码,我已经与团队成员建立了一些结对编程会议。这些人在我将要使用的工具方面比我有更多的经验。他们可以帮我找到我自己很难找到的资源。

我想知道课程能否反映现实。一个可行的办法是开设一门新课程,让本科生、大二学生和大四学生跨年配对。大四学生应该通过课程和实习获得更多的项目工作经验。

一种选择是根据高年级学生的技能提供开放式项目。有应用编程经验的资深开发者可能会被要求创造一款全新的Android或iPhone游戏,而致力于构建系统的资深开发者可能会被要求在hadoop上创造一款大型数据处理应用。另一个选择可能是有一个两个阶段的课程,专注于一个特定的项目,在几年之间分开。目前的大二学生必须在两年后回来分享他们的知识。

当然,这只是众多解决方案中的一种,但我认为我们可以在教授构建软件的社会性方面做得更好。

- k


约翰内斯·布劳尔

我认为很难在课堂上反映真实的编程场景,因为课堂不是真实的世界。但这并不意味着针对初学者的编程课程必须由使用单一编程语言的简短、孤立的编程练习构成。几年来,我们一直在学习第一年的编程课程,标题是“web应用程序的面向对象开发”。当然,在这门课上,学生程序主要使用一种语言,在这种情况下是Smalltalk。但是因为开发web应用程序,他们必须从一开始就学习web框架(Seaside)、HTML和CSS的用法。稍后再讲Javascript。

在整个课程中,每个学生开发一个web应用程序。网络教学的发展以网络教学为指导。在第一步中,单元测试由教师提供,但在项目的进一步进展中,学生必须开发自己的单元测试。

在第二学期开始的时候,学生们必须组成三个人的小组。他们学会了合作开发软件和合并独立开发的组件。

由于完整的课程内容是通过在线讲座呈现的,教师可以扮演教练的角色而不是讲师。这使得他们能够调整学生之前异质的知识。

当然,并不是所有现实世界的编程问题都可以通过这种方式进行预测,但是我们认为这种编程课程比传统的编程课程能够涵盖更多的典型问题。


卡洛斯Rodriguez-Fernandez

我的编程经验就是这样;创建、重用、测试,以及基于你在学校学到的所有概念的自我批评:大O、可维护性、模式、数据结构、算法,等等……然后,您迭代这些代码,以优化您的代码,使其达到最好的效果。


帕特里克•林

今天,我在第一年的编程课程中谈到了软件拼贴:http://patricklam.ca/ece155,第12讲。我认为,对学生来说,至少听到“课堂之外的编程”是非常有用的,即使他们没有时间去实践它。(我们的学生有一个四年级的设计项目,所以他们肯定会做一些拼贴。)


匿名

嗨,菲尔,

好文章!我曾经是一名全职程序员,在那之前我是一名设计师。现在我管理着一个程序员团队,因为使用这些技巧,我找到了比大多数其他开发团队更聪明的工作方法。很高兴你能分享这些,所以这里有一些我们做的事情有点不同。也许我们可以为程序员和CS制作一个漂亮的Kluge过程。

1)评估,知道你可能也会这么做,但我认为这是编码过程中必不可少的一部分。评估项目,并提出高层次的描述,过程流,线框图,IO图。如果你不清楚自己在建造什么,获取材料是没有意义的……

2)草料,和你一样,我们不介意代码库不是“我们的”。实际上,我们喜欢使用MIT或GPL代码的想法,我们可以将这些代码反馈给社区,并对外更新为可计费小时数。奇怪的是,我们不只是寻找我们自己语言的代码,而是寻找我们能够阅读的语言的代码,所以我们实际上已经完成了c#到python和php的完整源代码移植。我们还将一些非常老的VB转换成c#、Java和c++的应用程序。

3)适应。这是一个我们可能不同的领域。我们确实喜欢为我们使用的功能创建适配器,所以我们可能在c++项目中有一些C代码。我们知道代码不是很面向对象,所以我们将创建一个单独的对象,而不是重新编码。这将保持原始代码的原始用途,并通过一个或一组符合我们的需求和业务逻辑的专门对象增加我们对该代码的访问。

4)记录。我们相信为我们使用的每个项目启动一个新的存储库,并更新我们所做的更改,分别存储系统的各个部分。没有什么比做ABCDE的项目更糟糕的了……然后当FGHI项目来了,你必须重新开始。这东西要靠它才能正常工作,不过,嘿……

5)集成(就像焊接一样,但我们试图保持尽可能多的独立,所以我们只是称之为集成,所以没有人去建造所有唱歌、跳舞的物体……

6)怀疑

7)重新调整或完善我们的添加内容。基本代码应该可以正常工作,适配器位于我们所依赖的任何代码的前面


匿名

我个人的做法是“现在编码,以后再重构”。在编写了几年代码之后,我才发现我的设计模式有众所周知的名字。最重要的是,一个人需要为自己的代码感到自豪,并不断提高自己的技能。


匿名

经过深思熟虑的。虽然通常情况下是这样的,但当使用旧代码段时,这是因为您知道以前编写的代码的功能,并将这些“模式”与您需要的功能相适应,并调整或塑造接口以满足需求。(假设您正在创建的软件有一个设计或体系结构)。另外,如果从设计的角度考虑问题,在步骤2中分析设计元素可以防止不包含所需设计元素的代码执行Weld和Grow步骤。
我曾经把你在大学里学到的东西称为,获得工具集,在现实世界中编程就是学习如何使用那个工具集。


匿名

你从没上过我的编程课。


匿名

我开始编程时,你不得不建立自己的“图书馆”,因为没有互联网可以窃取(呃。find)从六种方法来编写“Hello World”的代码。我发现最好的模式是“小红书”方法。对我来说,这意味着你不仅要了解结果是什么,还要了解到达那里的路径,并认识到路径点。这样,无论你窃取(或借用)什么代码,或者你必须自己创建代码;所有部分同时达到目标,从而使项目、客户和付款(PCP)协调一致。


匿名

有可能一些刚出校门的人会被分配到某种维护任务。那么学习代码库(有或没有设计文档)并必须修复其中的一些bug的任务呢?这将是有用的——也是现实世界的——经验。在此基础上,我们继续添加功能,也许还需要附带更新设计文档这一附加任务。


查看更多评论

Baidu
map