学习构建之法(2):课程总结

 

 

年底、期末,在繁忙之中,我和我的团队完成了“微学堂”这一产品。伴随着它的交付,《软件工程》结课了。我现在是本科三年级,两年半以来修了五十多门课,应该说这一门是挑战度最高的。最后几周,不时有通知“下周的课不上了,各个小组自己做团队项目”:相对于课堂听讲,课外需要付出的精力之多,由此可见。

即使以代码行数衡量并不是,我感觉这个团队项目是我经历过的规模最大的项目,大到另我有无法驾驭的恐慌。不过这样说也不公平,这种“out of hand”的感受不仅来自这个项目本身,也有来自其他课程、辅修专业、社会工作等等带来的压力。然而话说回来,我直观上的感受就是,作为组长我不清楚每一个组员都具体做了什么、用什么方法做的。不可能有一人 review 每一段代码;不可能有一人了解项目中的全部实现细节;更不可能凭一人之力完成。

与此相比,此前的和本学期其他的“大作业”都只是小打小闹。不点名提及这学期的某些课程的某些 Project:一人花几个小时就做完,好意思说它是 Project?顶多算个 Assignment 好吧。如果把这些都算上,那么我这学期可能做了 20 个大作业,恩,说出来挺唬人(划掉)。

 

Donald Knuth 有一句名言:过早优化是万恶之源。项目中还存在一些过度设计的问题。其实这些词我都不是很懂,通过这个团队项目,只是感觉对此有了一些浅薄的理解。

中途出现的需求变更对我们造成了不利影响——来自教师的一条非功能性需求:我们被要求使用另一小组提供的 API 服务,而非自己编写相关模块。为了保证进度,我没有选择重构,而是把这个 API 服务做了一层包装,以保持接口不变而替换原有模块。这带来了架构上的冗余和“不优雅”。

这里所说的模块是一组爬虫。爬虫总有个运行频率的限度,而用户总是希望得到最新的信息,而且希望在最短时间内得到最新的信息。针对这一矛盾,我们设计了后台定时触发的“自动刷新”和用户手动触发的“强制刷新”这两种不同的刷新,同一个接口设计同步和异步两种调用方法。结果,因为他们 API 服务没能支持,全都白费功夫啦。

值得一提的是,做 API 服务的那组同学似乎并没有考虑运行频率的限度的问题。他们对爬虫的目标,也就是我校网络学堂和综合教务系统,发起高频次、高并发的请求,形成 DoS 攻击,造成网络学堂压力过大、反复宕机。运行着他们 API 服务的那台服务器,其 IP 被学校封禁。不巧的是,该台服务器是由我管理的。简言之,我因为他们被查水表了……这导致我不得不花大量的精力来与上级管理人员沟通,撰写需要同时抄送给三四个单位的整改报告——这影响了我们的进度。

我们在最初设计时,在安全性上花了很多精力。我们使用 OAuth,我们使用 https,避免用户信息的泄露。实现时,微信公众平台 OAuth 那一套牵扯了我们更多的精力:除代码编写外,开发环境搭建、调试、测试等方方面面都有复杂性的增加。结果呢,直到最后,我们的上游,也就是上文提及的 API 服务,也没有实现任何对调用者身份的验证。数据全部明文传输。他们的 mongodb 数据库甚至不设密码,直接暴露在外(这也是上文提及我被查水表的原因之一,原话是“存在高危安全隐患”)。

只要有一环出了问题,整个安全链条就会断掉。API 组糟糕的安全性意味着我们的用户的一切信息都会被公开在国际互联网上,也就意味着我们在安全性上的努力全部白费——除了在文档中写上一笔,期盼因此获得作业成绩的加分。好气啊!

 

花了这么多篇幅吐槽 API 组。我们自己得到的教训是:应该循序渐进。特别是在敏捷的语境下,不能一开始就想着搞出完美的设计“一步到位”,不能指望一开始就把所有细节都考虑周全。一开始最好是设计得简单些,keep it simple and stupid,在反复迭代中进行改进,边写边重构。

通过这个项目,团队管理上的经验也积累了不少。把一个团队带好,这是非常困难的,我一直觉得我在这方面没有缺少天赋,适合埋头干活,而不是做一个管理者。这回做组长,让我在这方面增加了一些经验,也增加了一些自信(笑)。具体的经验可以列一些,比如重要的事情不能只口头说——在微信群里说也算“口头”——要形成文档,形成书面的东西。

 

最后说回这个课程本身吧。除了做项目的锻炼之外,通过课堂讲授,我的理论水平也得到了提高——SC、CC、MCC、CDC 等度量测试覆盖的一堆词儿;系统的 actor、stakeholder,UML 状态图、顺序图、活动图,用户故事、用例建模,需求工程的那一套理论;接触了几种设计模式;关于团队、流程一些成熟经验……作为一门工科专业课,竟也有了一分管理学的味道。

建议就没什么了,各方面都挺好的。只有一条,那就是一组来搞 API、其他组使用的这种玩法,估计明年不会再搞了吧(逃)

 

这是《软件工程》课程系列博客的最后一篇。
相关文章:
学习构建之法(1):写个微信抢票
django 性能调优手记
“结对编程”初体验

“结对编程”初体验

本学期选修了清华大学软件学院刘强老师主讲的《软件工程》课程。近期完成了该课程的一项作业——体验结对编程(Pair programming)。本文谈谈个人体验。

我们实现了该课程的作业“紫荆之声——基于微信公众平台的票务管理系统”的一个功能单元:一个事件处理器 Handler,当用户在微信公众号点击“抢啥”菜单项时,返回近期可以抢票的活动列表。这是我们在该项目开发过程中编写的第一个 Handler。至于为什么这个看似简单的小任务花了30分钟之久,大概是因为我们事先毫无准备,两台笔记本搬过来,装上录屏软件就开始了,什么都还没配置呢( ̄(工) ̄)

总的来说,我扮演了驾驶员的角色,刘斌同学扮演了导航员的角色。我的手放在键盘上实际编写代码。同伴则负责进行审查、解答我提出的各种问题、跟我讨论实现上的细节,比如我们应该用请求体的什么参数来识别这是“抢啥”事件?这个地方写得对不对?是否有库函数完成这个操作?这个异常是怎么回事?返回给用户的活动列表应该怎么过滤、怎么排序?他利用另一台笔记本电脑,有时去查阅文档、有时搜索爆栈网、有时打个断点跑起来试试看。有时充当小黄鸭的角色。

相比两人分工各写各的,我感受到的好处主要有几点:不再有冲突合并的麻烦;一个人写另一个人就同时检查了,省去了一些调试查错的时间,也省去了代码审查的时间;沟通成本降低。缺点也有,比如总的工时数似乎并不会下降,而且约时间、找地点有额外的成本。

 

浅尝现代前端开发

“Web 前端技术实训课程”感想(一)

在苹果电脑早已全线标配 NVMe 固态硬盘的当下,我看到有些课程还在讲解磁带。教师自然会有一万种理由来辩解这并不是什么“不思进取”,但作为学生还是总觉得不痛快。

在这样的背景下,Web 前端技术实训课程不可不谓激动人心。该课程由清华大学软件学院刘强老师开设,在该校所谓的夏季小学期展开,历时两周半。邀请到来自知名互联网企业的工程师登台讲解,配合独具特色、实践性极强的“大作业”,有望接触到工业界最新潮流,实在是令人期待。

从今开始在这里分享参与该课程的感想,同时也是为了应对其作业——“在个人网站中发布一些个人日志”。

更新 2016-9-26:就这一篇,并没有后续- –