石家庄铁道大学 2016 上半年软件工程课助教总结

通常,总结会相对整个过程短不少。然而,因为过程的内容本就很多,所以需要总结的东西似乎就有不少,所以这篇总结计划分成三个部分:

  • 关于《构建之法》
  • 关于软工课和同学们
  • 关于我自己

关于《构建之法》与软件工程

关于软件工程的一些思考

2013 年,当时的我刚刚决定将目光从数学转向计算机。在上学时,我接触过 Cpp/Python 等编程语言,也学过算法分析、数据结构、离散数学等基础知识,甚至毕业设计就是编写一个在 GPU 上的大整数高精运算库。这样的经历,应当可以说已经「有一定经验了」。然而,当谈及「写软件」这件事情本身,当时的我却不敢滥竽充数,因为其时关于软件开发的工程知识我还知之甚少。

一个主动学习者遇到不懂但是想要弄懂的东西之后,会做的第一件事情通常是上网检索。而想要学习「软件工程」,首先就要搞清楚软件工程是做什么的。当时的维基百科是这样告诉我的:

软件工程研究和应用如何以系统性的、规范化的、可定量的过程化方法去开发和维护软件,以及如何把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来的学科。它涉及到程序设计语言、数据库、软件开发工具、系统平台、标准、设计模式等方面。

你说什么?系统性、规范化、可定量、过程化、系统平台、标准、设计模式?WTF!

这样一个「粗暴」的介绍纯粹是在用抽象定义抽象。对于业内人士,这样的介绍当然足够清楚;然而,对「门外汉」来说,用抽象定义抽象唯一的作用是将「一头雾水」变成「两头雾水」——当然,可能还可以用来装 X。

既然暂时搞不清楚软件工程是做什么的,那么我们就只能扩大语义,看一看「工程学」是做什么的。美国专业发展工程师会,给工程学做了如下定义:

The creative application of scientific principles to design or develop structures, machines, apparatus, or manufacturing processes, or works utilizing them singly or in combination; or to construct or operate the same with full cognizance of their design; or to forecast their behavior under specific operating conditions; all as respects an intended function, economics of operation or safety to life and property.

冗长的部分不必深究,我们只需要看整段话的最后一部分:所作所为,都是为了确保功能、经济运作、生命和财产的安全。也就是说,工程学是为了保证人们的实践活动能够如其运行(保证功能)、带来效益(保证经济价值)、确保安全(避免或正确处置意外情况)。

有了这样的指导思想,结合「软件工程」更多的介绍,就不难提炼出软件工程的目标:想办法构建和维护功能正常的、实用的以及高质量的软件。在这里,「正常」、「实用」和「高质量」分别就对应了功能、效益和安全三个方面。当然,除了继承上级意象的内涵,软件工程必然在自己所处的环境中发展出有别于其他领域工程学的内涵。相对于传统的工程学,比如机械工程,软件工程所要面对的需求往往是容易变化的。这种特点,就要求软件工程提出一种方法论,以期在保证功能、效益和安全的同时,能够适应容易变化的需求。

《构建之法》的好

我自小对榫卯结构很是喜爱。幼时睡的床是木工用榫卯拼起来的,幼时做的板凳,则是父亲亲手做的榫卯木工。长大后,我也亲手做过一个榫卯结构的小书架。《构建之法》封面上的鲁班锁,我自是不陌生的;自在书店第一眼看到这把鲁班锁,就此和《构建之法》结下了缘分。

在群里的时候,本书的作者邹欣老师曾经转过一则对《构建之法》的差评,讲「这本书充斥着最佳实践,却并没有什么干货」。群里不少前辈大牛纷纷表示这位给出差评的读者没有眼光,而我却没有说话。我心里当然是不服气的,但凡事都讲个道理,所以正好借这个机会,说说《构建之法》的干货都在哪里。

在我看来,这是一本充满干货的书,而且干货太多,所以需要常读常新

为什么说「干货太多」呢?我觉得需要从几个方面讲起,并且分别都可以从书中举出切实的例证。

首先,《构建之法》不光告诉你怎样做是对的,而且会告诉你为什么这样做是对的,不仅如此,还会告诉你典型的错误有哪些。

在「给任课老师和助教的建议」一节中,作者邹欣老师尝试讨论了软工课上师生应当有怎样的关系,以期能够让教师取得的授课效果。

「字典式」的书会告诉你,软工课上师生关系应该是「健身教练和健身学员」的关系,然后就没有然后了。对于这种书,读者往往只能「被动地接受知识」,却不知道为什么应该这样。这种书适合做速查表(cheatsheet),而不是和做教材。更多的书,可能会这样做:软工课上的师生关系应该是健身教练和健身学员的关系,因为 blahblah。如果能够在这个层面上,将每一个概念都介绍清楚,那么这已经是一本一般意义上的好书了。对于这样的书,认真的读者能够做到知其然且知其所以然,然后尝试运用到实践中去。不过,这样的书却无法触发读者更多的思考。

《构建之法》是这样做的,它首先告诉读者现有的很多师生关系模型是怎样的,以及为什么是不好的。于是,读者会去思考发生在自己身上的师生关系以及自己身边的师生关系是不是能够代入到这些模型中;而后,代入成功之后会与书中的描写互相印证,发现这样的师生关系确实会带来一些不好的结果。循循善诱完毕,《构建之法》才将正确答案搬到读者面前,并以类比解释为什么要这样做,以及这样做的好处。在最后,又用风趣的类比给学生一个不得不努力的理由:

「老师,你讲得特别好,我很想提高。但是我太忙了,没时间写程序,我就是来听听。」这种话和健身房里「教练,你讲得特别好,我特别想减肥健美。但是我太忙了,没时间练。所以我办了卡,放在钱包里面,有时间的时候就拿出来瞻仰一下。」没什么差别。

《构建之法》中每一个重要的概念,邹欣老师几乎都是用这样的套路缓缓道来。因此,我可以说,这是一本充满干货的书。

其次,《构建之法》在讲每一个工具的时候,都会告诉你:这件事情为什么要做、这件事情应该怎么做以及这件事情怎样才算做好了(标准)。当然,不一定每一次都按照这个顺序来。

在第二章讲单元测试的时候,邹欣老师首先会讲到,因为软件是多人合作完成的,如果相互依赖但是模块功能定义不明确、质量不稳定,那么就会影响他人的工作,所以我们需要用单元测试。然后,《构建之法》会手把手地教读者如何创立和执行一个单元测试。最后,《构建之法》会将「怎样才算是一个好的单元测试」的标准写出来,并且做到每一条要求都明确可执行。

这样的阐述流程,其实是循循善诱地告诉读者:

  • 单元测试好啊,你得做啊,不然就会出乱子啊;
  • 什么,你不会,那我手把手教你啊;
  • 你看啊,我这里有个表格,如果你按照上面的要求一个个完成目标,那么你就能保证你的模块的正确性,不至于因此惹出乱子。

而后,如果读者在今后的开发中惹出了乱子,就应该想一想:

  • 啊,我没做单元测试——活该!邹欣老师说了,不做单元测试,就可能惹出乱子。
  • 啊,我做了单元测试,但是没有达标——活该!邹欣老师说了,只有合格的单元测试才有意义,不然测试结果就没有说服力,就可能惹出乱子。

最后,《构建之法》在讲每一个方法论的时候,都会告诉你:这个方法是为了解决什么问题而出现的、具体的流程是怎样的、执行过程中遇到常见的问题要怎么解决、这个方法的适用范围是什么。

前三个部分自不必多说。我想着重说的是最后一个部分:这个方法的适用范围是什么。

我在一个知乎回答中引述了我高中物理老师周智辉的话:

当你们看见一个物理公式或者定理的时候,一定要牢记它成立的条件。

正如每一个物理公式或者定理都有成立的条件,每一种方法论都有自己使用的范围。具体使用哪一种方法来解决我们当前遇到的问题,这依赖于当前项目的具体情况,不可一概而论(以敏捷开发为例,见书中 6.6 节的第一个问题)。书中,邹新老师以问答的形式指出:敏捷不是万能的,它能做的事情有限。

我认为,明确方法论能够解决的问题和适用的范围,是理性思考之后的真知灼见,也是每一本设计方法论相关的书必须要明确写出来的内容。在这一点上,《构建之法》做得无疑很好。

综上所述,《构建之法》不仅有干货,而且有很多干货。并且,因为干货内容太多,所以需要常读常新——我甚至多次和我爱人提及:「《构建之法》是一本好书,其中介绍的很多方法论,不仅可以用在软件工程中,而且可以适当改变,使用到生活中去」。

这些内容本不该写在助教总结当中,但是这些在软工涉及到的方法论之上的方法论(请想象:一个能写程序的程序),我认为也是软工很重要的一部分。所以写出来,希望看到的同学们能够再多学到一点什么。

《构建之法》的不好

那么《构建之法》是一本完美的书吗?

其实我认为自己是不太有资格去评判一本由实践得来的真知构成的书的。好在,我想要「挑剔」的也并非是书中的内容,而是本书的组织形式。

在上一节谈及《构建之法》的好的时候,我多次谈到,这本书通常会以循循善诱的方式将道理传达给读者。这很好,也很不好。一如刚才谈到的,每一种方法,都有其适用范围。这样的组织形式,可能获得诸如惊艳、鲜活、有血有肉的评价,但是也不可避免地会引入一个问题:知识点过于分散。毕竟,作为一本能够充当教材的书,让学生能够有机会快速找到自己想查找的知识点,这是很重要的。

对此,我有如下建议:

  • 在每一章的章首,新增一个练习;
  • 这个练习是一个未完成的 cheatsheet;
  • 作者将书中的重点以结构化的方式组织起来,留空;
  • 读者在读书过程中,要留心这些空白,并逐步将 cheatsheet 填满。

这样有几个好处:

  • 提纲挈领,告诉读者本章有哪些重点;
  • 反复强调,让读者自己动手,将重点反复印刻在读者脑海;
  • 形成一个知识点集中的结构化表格,利于翻查。

此外,我还发现了书中(2015 年 7 月第 2 版)一些小强:

  • p50,「工程师比学生要少花 1/3 强的时间」,「强」字多余
  • p77,「例如:fFileExist」,应当是「例如:ifFileExist」
  • p142,「好处有两点:\n(1)被授权的人」,编号和「被授权」之间没有合适的铅空
  • p167,「那就要做实 用并且创新的项目」,「实用」之间有多余的空格
  • p180,「你还在看博客!」,这应当是从博客到书籍转换过程中的遗留问题
  • p193,「很多不确定性 -- 风险」,破折号的问题
  • p200,「似乎指挥了团队的行动 ——就像」,破折号前面有多余的空格
  • ……

关于软工课和同学们

在大学中,我们是怎么做的?

在大学中,很多学生会写一些程序。特别是计算机学院、软件学院以及其他学院中一些编程能力较强的同学,可能会去实现一些功能丰富的程序。比如,据我了解,很多学校的计算机学院或者软件学院,都会要求学生写一套五子棋的 AI。

不过,令人遗憾的是,很少会有学校引领学生思考类似下列的问题并对所写的程序进行改善:

  • 你的程序能够支持黑棋禁手、五手两打之类的规则吗?
  • 如果棋盘大小从 15×15 扩展到 100×100,你的程序还能保证高效运行吗?
  • 如果需求变化,要求你的程序同时支持五子连珠、六子连珠甚至更多的连珠棋,你的程序能够快速修改实现吗?

而思考这些问题,并提出解决这些潜在问题的办法,才是工程上更重要的能力——会写代码的人很多的。

索性,在邹欣和周筠两位老师的推动下,很多学校的软工课堂以《构建之法》为教材,开始了「课改」,尝试代领学生进入「真正的」工程中去。

助教工作的内容总结

这是我第一次担任助教,那自然也就是第一次担任石家庄铁道大学王建民老师的助教。因为是第一次,所以经验为零——虽有一腔热情,却没能尽可能好地完成助教任务。

下面是已完成部分的总结:

  • 学生规模:两个班的学生,共 70 人。
  • 批改作业次数:10,包括个人作业、结对作业
  • 给出作业总结:每次实践作业都给出了总结,并给出了思路、解法和应当注意的问题
  • 作业点评:每次实践作业,都在每位同学的作业下进行了明确的点评

因为已经工作,加上本学期时间对应到我工作中,有两个多月的封闭开发的经历,所以能空闲出来给学生评作业的时间十分有限。评作业的时间,通常集中在早起 -- 上班前以及周末空闲时间(在这里要特别感谢我爱人这段时间中对我的支持)。因为软工课涉及到代码及其质量的问题,通常需要仔细审阅每一份作业代码。评作业的大多数时间都放在了审阅代码上,平均下来,每份作业需要花费 5 分钟左右的时间才能看完。这意味着,如果我每天花费 1 小时的时间来评作业的话,一周只能评完一次作业。这显然是不好的。为此,在后期,我尝试用自动化脚本的方式,代替人工审阅,以期快速发现大多数基础问题,这样提高了不少效率。

这学期的个人作业和结对作业偏重算法较多,因此在个人作业和结对作业进行的过程中,我明显能感觉到很多同学在算法方面有力不从心的现象。结对作业中涉及到的「子序列求和」问题及其各种变种,其实是练习动态规划(DP)的极好例子。但是很多同学显然对 DP 不熟悉,写了不健壮的代码、错误的代码甚至是用暴力穷搜的方式解决问题。

关于同学们

在助教任务进行中,最让我无奈的是反馈和沟通不够。我在博文中留下了很多评论,其中绝大多数都是有针对性的评论,指出当前作业中不足的地方。但是应者寥寥:

  • 前次指出代码应该放在代码环境中,与正文区分开来,但是后续的作业都没有改进;
  • 前次指出作业还有未能完善的地方,学生回应说会改,但是直到学期末再次询问,却得到「这个还没有改」的回复。

给老师的建议

首先是关于作业设置的建议。个人的感觉,本学期前半段的作业设置偏向算法的内容较多,可以更多地倾斜到偏向软工实践的内容:比如每次作业都要求学生给出单元测试的用例以及测试结果(而不仅仅是单元测试那一课)。

关于我自己

自我评价,本学期我在助教任务中的表现是不满意的——虽然有客观原因。不满意的几个方面在于:

  • 和老师沟通不够及时、流畅,导致部分作业老师在课堂上改过了截止时间,但我却按照原有时间评分,造成重复劳动;
  • 自己在 GUI 相关项目上经验不足(工作中做高性能的后端服务,接触不到 GUI),导致在评价涉及到 GUI 的作业时,需要现学很多基础知识才能给出客观的评分;
  • 后期因为客观原因,没能及时给出评分结果,给王老师带来不少麻烦——请王老师接受我真诚的歉意。

后续我还会继续关注同学们的博客,知道给团队作业作出点评——虽然这于最终评分已经无补,但是一则善始善终,二则对希望提高软工实践的同学还是有益的。: )

posted @ 2016-07-02 18:50 孟晨 阅读(...) 评论(...) 编辑 收藏