写点什么

在大学中教授现代软件开发技能

2016 年 12 月 01 日

关键要点:

  • 人们常会觉察到大学中所教授的东西与“现实世界”间存在着巨大的鸿沟。
  • 引入实践者到大学的学位教育中,可使学位教育与时俱进。
  • 现代工具和技术在教学中的使用有助于改进课程的相关性和参与度。
  • 我们在软件设计的教学中使用了 TDD 和重构,而非预定的教学规范。
  • 将研究论文与产业界的播客帖子和文章相对比,会对当前业界水平产生有意思的探讨。

大部分的毕业生在修完计算机科学学位之后,会继续在产业界从事软件开发工作。他们在各种规模企业的内部团队中做着业务核心软件开发,而在当前高度发展的世界中,正是这些软件支撑了每个人日常生活中的方方面面。

不少学位课程可为学生在计算理论基础方面打下坚实的功底,但是对于产业界开发项目中所使用的软件工程技术和实践,大学环境是难以提供相应的训练的。我们常会听到技能在软件工业中是多么的短缺,以及大学中所教授的东西是如何与“现实世界”间存在着巨大的鸿沟。在本文中将阐述在伦敦帝国理工大学中,我们是如何开发一个旨在缩小这一差距的项目,并为学生提供产业界软件工程师职业生涯中的相关技能。我们也将阐述我们是如何做到让课程侧重于围绕着一些工具、技术和关注展开,对于工作于现代团队中的专业开发人员而言,这些内容在他们的日常生活中占有重要的地位。

大学的课程几乎总是由学术研究人员授课的,但是鲜有学术人员具有产业环境中软件开发的亲身经历。虽然一些学术人员,尤其是计算机科学家,的确将编写软件作为他们研究工作的一部分,但是他们项目开发的运作方式一般并非是在产业设置下运行开发项目的代表性方式。研究人员主要致力于相当小的软件项目上,这些项目只用于展示研究思路的原型或是做概念验证。就研究人员自身而言,他们没有为批量销售要求而开发鲁棒软件的压力。因为他们可能只是专注于添加那些可推进他们的研究而需要的新特性,很少关注鲁棒性和可维护性。类似地,他们通常并不需要支持大量的用户,或是需要支持 24X7 运行的系统,而这些是在线零售商、金融服务或是电信企业等业界所需要做的。

大学教师和研究生通常是各自为政,因而他们在不少方面上缺乏经验,这包括:规划和管理软件项目中许多不同贡献者的工作;在对支持可维护性的整体架构运维的同时,将所有贡献者的工作集成起来,并根据预定的计划向用户定期发布软件。正因为如此,鲜有大学教师有机会能形成项目管理和质量控制方法的实际经验,这些项目管理和质量控制的方法广泛地使用于产业软件开发中。

我们解决这些问题的方法是邀请来自产业界软件工程团体的成员,让他们帮助我们设置软件工程课程的教学,利用他们的实践经验去指导学业组成课程的内容和讲授方式。具体做法包括:对当前问题给出各个部分的建议,帮助建立课程内容大纲,让实际从业者做嘉宾讲座或指导,甚至像我自身这样加入到教职团队中。我们发现实际从业者通常很乐意为修订课程大纲以培养下一代的软件工程师和反馈社区提供帮助。当然如果这些人受雇于公司的话,帮助教学也是一个可提升他们公司知名度的机会。

课程内容

在伦敦帝国理工大学,我们有一个为期三年到四年的计算机学业规划。学生可经三年学业获得工学本科学位,或是经四年学业获得工学硕士学位。对于这两类学位课程,前三年学业在根本上是一样的,但是对于那些进行四年学业的学生,还需要在第三年和第四年间完成为期六个月的在企业中的工作实习。本文只探讨那些我们认为是“软件工程”组成的课程元素,当然在这些课程以外,学生还需学习数据、逻辑、编译器、操作系统及其它被认为是“计算机科学”的课程。

第一学年

在学位课程的第一年,我们侧重于基础的编程技能。我们相信这对所有的学生而言都是基础的。授课是通过讲解课的方式,针对函数、面向对象和系统程序设计,并由集成于课程中的基于计算机的实验所支持。实验是十分重要的,因为只有通过实验学生才能接触到实践编程,获得个性化反馈并得到提高。

我们所面对的一个问题是,一些学生在进入大学前就具有了很多的编程经验,有的是从学校学到的,但是更多的是在自己的时间中通过自学和参与项目而得到的。另有一些学生在入学前是从未写过一行代码的。我们需要基础入门课程能支持各类的学生,不能使毫无编程经验的学生感觉他们是处于劣势地位的,同时也不能让更加有经验的学生感到无聊,认为对所讲授的内容是他们早就知道的。为实现公平的竞争,我们对所做的是以讲授 Haskell 作为第一门编程语言为开始。Haskell 几乎对所有的新学生而言都同样不熟悉,即使是对于那些已做了很多编程的学生,通常也不会在前期使用过这类的编程语言。

在第一周的教学中就引入版本控制,这已被证实是一个十分成功的创新。我们不是将版本控制用做后期的“协作项目的工具”,而是在每个实验中包括了从 git 代码库中克隆一个开始点做增量提交、进而由学生评估所做的提交,该提交是一个指向他们想要标记版本的 git 提交哈希。这使得版本控制成为完全自然和日常的行为。

第二学年

在学业的第二年中,我们旨在教授学生如何去设计和开发大规模系统。我们打算以讲授特定语言的编程为开始而继续前进,进而考虑更大规模的设计问题。在该课程的前期迭代中,教程注重于概念、规范说明语言和设计模式目录,这意味着学生将掌握一系列文档化和交流软件设计的方法,这并没有绑定到特定的实现语言。但是将这样的课程内容与在产业项目中所主要使用的设计实践相比,我们还是发现了一些不匹配的地方。

形式化描述技术被工程师用在苛求安全的和高精度系统的开发中,但是开发这样系统的团队仅占全部团队的一小部分。更多的团队所致力开发的是那些支持企业、客户 Web 服务、App 和游戏等的不同类型业务的系统,这些系统无疑也是重要的,但是它们并非是苛求安全的系统。对形式化描述技术的使用在这类团队中是相对较为少见的。此外,鉴于现在敏捷开发方法是十分常见的,设计不再被认为是一个需要在编码开始之间就完成的独立项目阶段,而是一个持续的过程,实现了在软件的多轮迭代更新中决策的制定和改进。现在仍要解决软件设计相关的问题,但这并不需要预先在抽象层次上指定软件的设计,而更常见的情况是在考虑如何对现有软件部分地改变和添加新特性时,团队成员需要讨论和评估设计理念的方法。

我们依然为学生讲授设计模式和架构类型的相关概念,但是在我们教学中所考虑的是每个概念所解决的目标问题(例如移除复制)和可使用到的任何权衡考虑(例如由使用集成所导致的耦合问题,以及该问题将如何影响后期改进)。我们倾向于在代码中引入经测试的实例,并且将设计改变投影为演进和重构,这会影响工作所依赖的代码库的质量。通过在代码上所做的切实工作,我们发现相对于学生们在抽象考虑设计时所能做的而言,在系统中进行操作使学生更直接地接触到不同的设计问题及各种影响力的作用。我们可以使用现代 IDE 将代码改写为不同的结构,使用度量对代码质量、复杂度、耦合等进行清晰的探讨,学生可通过解决问题并给出实际的解决方案而动态地学习知识。

第三学年

在第三学年中,学生的主要任务是在 5 到 6 人的组中进行为期约三个月的项目工作(这与他们的讲解课是并行进行的)。每个组的任务是不同,但是都针对构建对同伴解决特定问题或提供特定服务的软件部分。每个组具有一位客户,客户指导产品的方向,可以由一位教职人员担当,或是一个工业伙伴。从教学角度看,项目工作的主要目的是在团队工作和协作中构建学生的技能,并将支持开发工作的软件工程技能置于实践之中。为支持这些目的,我们并行运行了一个软件工程实践课程,课程涉及了开发方法、工具、质量管理、项目和产品管理技术等内容。

但该课程是我们最难以恢复常态的课程,其主要问题在于相关性。我们想要软件工程课程支持小组项目,并使两者结合起来。但是从学生那里得到的反馈常是,学生们感觉软件工程课程分散了他们的注意力,他们更愿意花费时间去“仅是继续去做一个项目”。这显示了在学生自己的项目中,他们并未从软件工程实践的教学中感到受益。对此问题,我们想到了两个可能的原因。

首先,不同的小组所开展的项目范围过于宽泛。一些可能是去开发移动应用,而另有一些可能是去建立 Web 应用、桌面软件或甚至是命令行工具。如果我们考虑关于特定主题的教学计划中的内容,这些主题与一些项目小组是相关的,例如云部署,但就可能与其它的小组工作是完全不相关的。我们试图在课程中包括越多的内容,更可能的是,我们要求学生花费在学习一个主题上的时间越长,他们越有可能感觉到这些主题对他们的项目并无作用。

另一个原因是我们认为学生并未感受到软件工程实践教学的好处,虽然这些项目绝非琐碎事宜,但是它们还是没有达到足够大的规模或足够长的开发周期,以使学生感受到集成各个不同方面或长时间维护一个软件项目的痛苦所在。我们鼓励学生去建立协作工具和过程,帮助他们从技术代码、软件管理以及更普遍的项目管理等方面一起共事。在项目开始的时期,这些看起来就是一些额外开销,尤其花费在工具建立上的时间看上去就像是“继续做项目”中所丢失时间。直至项目末期,当压力是在产品发布上时,对这些工具和技术的投资才得到回报。

第四学年

我们为期四年学业规划的最后一部分被命名为“服务于产业的软件工程”课程。该课程的主要哲理在于赋予学生对产业软件工程所面对的一些问题的一个视图,尤其是使学生为工作世界做好准备。正如我们在第二和第三学年课程中所做的教学迭代,我们努力引入越来越多的产业相关内容,这通常也意味着要从第四学年的课程中移出一些教学材料。例如,本来是第四学年讲授的关于测试驱动开发的一些教学材料,现在为了支持小组项目的教学开展,在第三学年就被讲授了。尽管我们并不想赶上所有正在发生的业界趋势,但这些高级课程为我们讨论和提取当前实践状态提供了载体,并在某个教学内容一旦成为核心的实践时,就将该内容滤出放置到更低的学年中教授。

我们想在课程中涵盖的一个重要主题就是如何使用遗留代码高效地工作。实际上,大部分的软件工程师是花费了毕生职业生涯在改变已有的代码库,而非从草图开始构建。这不是一件坏事,也是很正常的。导致原因包括:持续的系统演进需要将更新需求作为新的需求,市场条件发生了变化,或是其他的新系统需要被集成进来。但这并不是一个二等工作,工程师需要在这种方式下工作的技能,这种技能不同于在自由区域中从空白状态开始工作时可能做的事情。问题在于软件在什么情况下更适合于重构,或在什么情况下应去重写?

这个问题是情感领域中的,而非是不可动摇的事实。因而我们在教学中的一个目标就是让学生去培养自己的批判性思维,去发出自己观点的声音,并围绕每个已提出的主题,基于对它们的理解开展讨论。他们每周工作的主要是去通过博客、文章、论文、会议演讲视频等去研究主题,并基于这些撰写一个短篇的立场声明,去回答一个讨论问题。这样我们就有了一个讨论课,其中学生概要展示并讨论他们从每周工作中的发现。为了添加尽量产业界的视角,每周我们会邀请业界专家做为嘉宾做“主题演讲”。我们通过讨论抽出主题演讲中对主题的观点,专家带来了他们自己的故事、例子和案例研究以分享。我们在制订课程中,感觉上并不像是在交付内容,更像是通过学生可以为自身参与并学习而设计体验。

教学观点

并非所有的教学材料都是用同样的方式讲授的,我们不断地尝试改进教学体验。一种对思考和讲述这些教学内容有帮助的方式是考虑到学生的不同学习方法。这里的不同教学方法是源自于近期出版的 Mark Guzdial 所著《Learner-Centred Design on Computing Education》一书中所给出的三种视角。Guzdial 将不同的教学体验特征化为三种方式:传播式(Transmission)、学徒式(Apprenticeship)和启发式(Developmental)。传播式教学是通过做报告这类单向的媒介传递知识,学徒式教学是指学生侧重于通过实践发展技能,而启发式教学中每个学生将得到个性化帮助,使每个学生获得个人的提升,并不必与班上其它的同学看齐。

在软件工程的教学中,我们仍采用了相当多的传播式教学方式(虽然有证据 [ http://www.pnas.org/content/111/23/8410] 表明这并非是有效的,但是传统是难于克服的),但我们已开始更多地侧重于学徒式教学模型及对技能的刻意训练,尤其是在软件开发方面。当然在班上具有 150 名学生和相对较少指导老师时,频繁地给予学生一对一的关注是困难的,但是当鼓励学生在更多的小组工作,尤其是结对编程时,我们发现学生可以从彼此那里得到教练和学习,并从对方那里获得个性化发展帮助。北卡罗来纳州立大学的 Laurie Williams 教授对此做了很多的研究工作,他的工作展示了在教学中结对编程的有效性 [ http://collaboration.csc.ncsu.edu/laurie/pair.html]

使学习经验更有效

在努力改进我们的教学内容和方式的同时,我们考虑到一个有用的方法,就是将理念作为价值流交付。如果我们从一个庞大的学生应学内容需求列表(即教学大纲)为开始,用数个月的课程时间以讲课的方式去付诸实践,并最终通过考试对教学过程实现质量管理,这样我们所得到的感觉上与瀑布开发过程是十分相似的。在软件开发中,产业界已演进为价值快速反馈和小规模频繁的批量价值交付。我们能在教学经验的迭代上为实现同样的目标而奋斗吗?

在这条道路上,我们已经做到的一件事情是采用了每周的小规模作业,而非大型学期末评估。这鼓励学生可在整个学期中用更可持续的节奏学习,赋予学生和他们的指导老师对每个概念理解程度的反馈。例如,在我们的软件设计模块中,我们打算每周都有一个设定的实践练习,这样学生可以通过编写代码并测试去练习特定的设计方面,并在数日内得到对他们工作的反馈。当然这对指导老师产生了很大的负担,他们需要短周期内批改并返回大量的作业。他们会轻易的妥协,改为每两周一次或者每月一次的作业。但是再次遵循我们将在敏捷项目中所应用的原则,我们试图使用自动化去尽早地给予初步反馈,使完成人工批改工作更加简单和频繁。我们还没有实现这些目标,老师每周为给出高质量的反馈还要做很多的工作,但是感觉上我们应是正朝着正确的方向前进。

我们仍然还有很多问题需要去解决,而且软件工业的状态是频繁改进的,这意味着为保持计算机科学基础(希望是不那么频繁地改变)与产业趋势和当代工具和技术应用的相关性和平衡性,我们也将要频繁地更新我们的课程计划。但是,正如在运行软件项目中所我们所应做的那样,我们希望能继续地审查、调整和持续改进。

关于作者

Robert Chatley是伦敦帝国理工大学软件工程的首席教员。在商业领域,他是一位以敏捷方向为重点的顾问、教练和培训讲师。Robert 曾供职于从初创企业到跨国企业的多家企业,其中包括作为工程师在 Google 工作,在英国最早大规模采用 XP 的企业之一的 Kizoom 担任技术领导人。他曾担任 XPDay 大会的主席,并在 SPA 会议中任程序主席。Robert 具有伦敦帝国理工大学的信息系统工程的工学研究生学位和软件工程博士学位。

查看英文原文: Teaching Modern Software Development Techniques at University


感谢冬雨对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016 年 12 月 01 日 16:32942
用户头像

发布了 226 篇内容, 共 59.9 次阅读, 收获喜欢 15 次。

关注

评论

发布
暂无评论
发现更多内容

anyRTC - 模仿微信音视频通话功能

anyRTC开发者

WebRTC 语音 直播 RTC 安卓

大数据2学习总结

周冬辉

架构师0期Week13作业

Nan Jiang

架构师13周练习

小蚂蚁

架构师0期Week13总结

Nan Jiang

java快速开发平台功能特点之代码生成器

力软.net/java开发平台

Java 分布式 代码组织 平台应用服务

云栖大会倒计时8天,新一代CDN的技术突破和应用实践专场有什么看点?

阿里云Edge Plus

CDN CDN加速

GitHub上14个屌炸天的Java进阶教程、面试真题项目,建议收藏!

Java成神之路

Java 编程 程序员 Spring Boot

淘宝服务端高并发分布式架构演进之路

简爱W

Java java架构师

每周花6小时跟清华大牛学Java:JVM、高并发多线程、算法、微服务。

Java成神之路

Java 编程 程序员 面试

微信群总是有人发广告?看我用Python写一个自动化机器人消灭他!

刘早起😶

Python

干货来袭!20例JavaWeb项目开发精粹;(内含源码)

Java架构师迁哥

架构师训练营-第十一周作业

Geek_a327d3

CommonMistakes

卓丁

面试阿里太难了!二本毕业、两年crud经验,侥幸通过面试定级P6

Java成神之路

Java 编程 程序员 面试

35岁以上的程序员们,后来都干什么去了?

华为云开发者社区

程序员 职业规划 架构师

物联网为什么需要5G?

华为云开发者社区

5G 物联网

从零开始搭建完整的电影全栈系统(一)——数据库设计及爬虫编写

刘强西

爬虫 Scrapy

anyRTC小程序SDK 4.0上线

anyRTC开发者

小程序 WebRTC 语音 直播 RTC

从零开始搭建完整的电影全栈系统(二)——简单的WEB展示网站的搭建

刘强西

Yii2 yii

【DevCloud · 敏捷智库】暴走在发布前夜的开发,你怕不怕?

华为云开发者社区

版本控制 系统集成 发布

常用数据分析指标

捡到宝啦!阿里内部人手一本的Springboot进阶手册,先学为敬

Java架构师迁哥

LeetCode题解:225. 用队列实现栈,一个队列, 压入 - O(n), 弹出 - O(1),JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

java安全编码指南之:表达式规则

简爱W

Java java架构师

Securecrt 使用

yuanhang

securecrt

JavaScript中的原型到底该如何理解?

Walker

Java 前端 面向对象编程 原型

限量版Netty纯手打笔记,年薪80W架构师耗时1个月整理出

Java架构师迁哥

Linux 基础操作

yuanhang

linux命令

到底什么是分布式系统?你需要了解这些

华为云开发者社区

分布式 部署

架构师训练营-第十二周作业

Geek_a327d3

微服务架构下如何保证事务的一致性

微服务架构下如何保证事务的一致性

在大学中教授现代软件开发技能-InfoQ