【软工】个人博客作业——软件与软件工程
【软工】个人博客作业
项目 | 内容 |
---|---|
课程:北航2020春软件工程 | 博客园班级博客 |
作业:阅读《构建之法》, 回答关于软件和软工的问题 | 个人博客作业 |
个人课程目标 | 系统学习软件工程,训练软件开发能力 |
这个作业在哪个具体方面帮助我实现目标 | 阅读教材,对软件、软件工程、软件产业有整体认识 |
看完《构建之法》后仍然不懂的问题
1. 软件的“生命周期”?
原书第一章中写道:
软件团队要从需求分析开始,……,展开后续工作,如设计(软件架构)、实现(数据结构和算法)、测试,到最后发布软件。……,修复各种各样的问题,这叫软件维护,或者服务运营。这一系列过程就是软件的生命周期。
看起来软件生命周期的定义应该为一个序列,包含需求分析、软件设计、实现、测试、运行和维护等。
然而在第五章关于流程等部分又提到了瀑布模型、瀑布模型的各种变体、统一流程(RUP)等。在瀑布模型中,各步骤是可以进行回溯的;在RUP中,需求分析、设计、实现、测试、部署工作流又渗透到了初始、细化、构造、交付四阶段中。
这看起来有些矛盾——我们当然可以概略地说软件的生命过程中包含了需求分析、设计、实现、测试、部署这些阶段,但将其按第一章讲成是一个线性过程、或按RUP来说各个步骤在时间上有并行重叠,似乎都不是定数。
因此我认为对软件的生命周期的定义是不确定的。首先无论是按哪种模型,似乎这些步骤都不是一个重复的Cycle。其次具体的软件流程是按照需求和产品特点不断调整的,没有一个固定的、通用的流程。
我认为应当将软件的“生命周期”粗略地定义为RUP的四阶段——初始阶段、细化阶段、构造阶段和交付阶段。在每个阶段里的具体步骤是不定的。例如按照第一章讲述的类似“序列”的流程中,四个阶段内部的工作流是单向串联的;按照瀑布模型来看,工作流是双向串联的;按照RUP来看,工作流是并行的但参与程度不同。
综上,我认为软件的生命周期是不固定的,且不能被称为“周期”。如果偏要给定一个整体的流程,我认为按照RUP四阶段的粗划分比较合理。
2. Personal Software Process 与单元测试
在原书第二章介绍个人开发流程(PSP)时写道,Development由以下部分组成:
分析需求、生成设计文档、设计复审、代码规范、具体设计、具体编码、代码复审、测试
这里的测试我想是包含了单元测试和回归测试。就回归测试而言,将其写到流程的最后是有道理的——编码完成后进行测试,测试未通过的进行修复,修复后需要进行回归测试以保证其他部分没有退化。但我对单元测试的最早出现位置有质疑。我认为单元测试不仅在编码完成后进行,而且应该伴随着具体编码甚至具体设计时就应该开展。
书里又写道:
在写技术模块的规格说明书的时候,要越详细越好,最好各项要求都可以表示为一个单元测试用例。……单元测试必须由最熟悉代码的人(程序的作者)来写。
这里我们知道,单元测试的测试用例可以依照规格文档来构造。那么其实在完成最初的架构和模块设计、在具体编码之前,大部分单元测试的目标对象和测试用例就已经可以得出。我认为,应当在规格设计后先写好单元测试用例和模块接口,每个模块具体编码完成后尽可能早的进行单元测试,而不应该等到全部编码完成、复审后再测试。到那时候,就算是程序的作者可能也记不得具体模块的情况了。
而对结对编程而言,熟悉程序的人有两个了,就可以在Driver写代码的同时,Navigator对着设计文档和Driver写的代码设计测试用例、帮跑单元测试,同样也是在编码的同时,这样效率更高且与函数/类规格更贴切,在写代码时发现的特殊处理需要测试也可以加在已有的测试上。
3. 代码设计规范中的参数检查、assert和规格
书中第四章介绍代码规范时提到,
在Debug版本中,所有的参数都要验证其正确性。在正式版本中,对从外部(用户或别的模块)传递过来的参数,要验证其正确性。
如何验证正确性?那就要用assert。当你觉得某事肯定如何时,就可以用断言。……
“所有的参数都要验证其正确性”是一件难以实现的工作。最基本的,对于Python这种动态类型语言,甚至需要验证参数的类型!虽然Python在版本更新中引入了类型说明注释:
def add(x:int, y:int) -> int:
return x+y
但是这仅仅是一个注释,程序在运行时不会进行任何检查。难道我们需要对这些参数一个个地isinstance()
?
而参数的正确性也是难以规定的。考虑如下的对图进行操作的函数(假定节点用整数编号代指):
def functionAboutGraph(nodeList, edgeList):
pass
所谓参数的正确性恐怕有如下几个层级:
nodeList
和edgeList
都是List。前者的元素是int
,后者是(int, int)
。- 在
edgeList
中出现的所有边的顶点,都应属于nodeList
。 - 无重点、无重边等其他可能由函数规格说明书制定的规则。
- ……
首先,这些验证若全部使用assert进行验证,可能比函数功能本身更费时(计算上的)和费心(程序员角度)。
其次,如何定义正确?正确性的验证应当到什么层次?哪些应当嵌在代码里做运行时检查(万无一失的),哪些应当放在单元测试里进行测试(抽样检查的)?
这些问题我没有答案。不过我有时会使用assert检查一些“显然的”(如何定义显然?)正确性要求,比如
somePtr != nullptr; // NullPointer?
if (myContainer.count(element) && myContainer[element] == 123); // Existence?
4. NABCD模型
在竞争环境下,NABCD模型中,NAC对产品是否成功的影响似乎过小,BD对产品的影响似乎过大:
我们要在竞争性的环境中实践软件工程,那就要做实用并且创新的项目。……大家可以参考NABCD模型。
N:需求,你的创意满足了用户的什么需求?
A:做法,看看你有什么独特的招数,不光是技术上的,也可以是商业模式上的。
B:好处,会带来什么好处?要花费什么才能得到好处?得到的好处超过迁移成本?
C:竞争,用户需求 vs 我们产品 vs 别人产品
D:推广,如何把产品交到用户手中?
以我使用过的两个软件产品举例。
- Grammarly:英文写作助手,能提供拼写与语法、流畅性、是否吸引人、达意程度、易读性、词汇选择等方面的评分、分析和建议。这款产品的优胜之处在于,它高度满足了用户的爽点(超过了需求的范畴,可以称为Benefits)。用户只需要输入一段文字就可以在几秒钟内得到词和短语级别的各方面的修改建议。无脑的用户只需要点击每项警告,点击应用建议的写法,就可以目睹着自己的分数chuachua地上涨。另一个方面,Grammarly在YouTube大量投入了质量相当高的广告,且直接点击就可以使用,非常简单,在推广(我认为原词Delivery更达意,不是推广好而是易得)上做到了很高的水平。
- 微信:我认为这款产品的成功原因在于Delivery,但不是由于微信本身,而是由于自己与腾讯全家桶的数十款软件高度绑定,微信正在野心勃勃地发展为“下一代互联网的入口”,微信成为了一个“产品矩阵“中的领头羊。微信本身没有满足用户的许多需求,也没有什么特殊的招数,现在更缺少竞品。如果剥离腾讯系的其他app,微信恐怕难以敌过挑剔的用户和追赶的竞品。
在需求大家都能基本满足、做法的先进性用户难以直接感知、产品趋同化的现在,是否满足用户不计成本也要用到的爽点和优秀的营销与推广仿佛决定了一款软件的前途(而不是质量)。这说明NABCD模型是否过时?且NABCD的核心变成了B与D后,是否不再是一个软件工程概念而变成了一个营销与商业发展概念?
5. 团队的创新能力
创新的迷思之七:成功的团队更能创新?
很多成功的企业进入了“创新者的困境”。当成功的企业步入中年,它们当年发迹的市场成熟了,当年赖以成功的创新技术成了主流的成熟技术,又叫“维持性的技术”,在成熟的市场和维持性的技术环境中,技术的创新并不是影响企业成败的主要因素……那些没有成功包袱的小公司反而能把颠覆性的创新带到市场,挑战成熟企业的霸主地位。
关于这个Myth的论述我本人非常赞同。就以百度和字节跳动为例,百度在当年也是靠硬实力和创新技术起家的,等到搜索业务成为霸主后,就渐渐缺少产品上的创新动力,而是将其他的产品依赖搜索业务的流量和用户,靠吃老本带起来其他的产品。而字节跳动作为新兴企业,在创业之初没有成功的包袱,专注于以推荐系统为基础的新鲜内容流式App,取得了蓬勃的发展。
然而作为热爱创新的从业者,是应该加入百度式的稳定却缺乏创新渐渐老去的企业,还是应该加入字节跳动式的不断创新正在高速发展的新兴企业?我曾听说不少应届生更愿意去应聘字节跳动,但大多是因为更现代的产品和管理模式,即公司本身的“新”,而并不一定是因为公司的“创新”。那我不禁想问,对程序员的职业价值自我实现而言,企业是否创新(不是个人是否创新)是否是一个重要的因素?
“软件”与“软件工程”
-
“软件”这一词汇是由 John Tukey在他1958年的论文《具体数学教学》中最早提到的。参考:维基百科
In 2000, Fred Shapiro, a librarian at the Yale Law School, published a letter revealing that Tukey's 1958 paper "The Teaching of Concrete Mathematics" contained the earliest known usage of the term "software" found in a search of JSTOR's electronic archives, predating the OED's citation by two years.
-
“软件工程”这一词汇是由 Margaret Hamilton 作为MIT的某实验室的软件工程部主管,在为阿波罗飞船设计导航系统时发明的。参考:IEEE Computer Society
Indeed, Margaret Hamilton, renowned mathematician and computer science pioneer, is credited with having coined the term software engineering while developing the guidance and navigation system for the Apollo spacecraft as head of the Software Engineering Division of the MIT Instrumentation Laboratory.
软件工程发展过程中有趣的冷知识和故事
Windows XP中自带的三维弹球游戏其实不是由微软开发,而是由Maxis与Cinematronics开发和发行,但被微软引入自家操作系统。在微软版游戏中,原厂商的名称被通过更换颜色而有意隐藏起来,并且阉割了回放功能、游戏音乐和更高的分辨率。
其实三维弹球游戏中不止有Windows游戏中看到的一张球台,而是共有3张“弹珠台”,分别名为“太空军校生”(最出名的那一款)、“Skulduggery”以及“Dragon's Keep”。
当时绝大部分的同类型的电脑游戏都是采用二维画面渲染。而Full Tilt! Pinball则是采用三维预渲染绘图技术,来“构造”三张不同的“弹珠台”,有别于其它模式类似的电脑游戏,在同类游戏中尚属首次。
源程序版本管理软件和项目管理软件
-
Microsoft TFS (Azure DevOps Server) 参考:Wikipedia 参考:博客
- 优点:不仅支持版本控制,还支持项目管理,包括敏捷开发和瀑布模型开发,覆盖了整个软件生命周期
- 缺点:较为复杂,能应用起来的团队、公司的数量少,大多只用了极小一部分功能
-
Git 参考:Wikipedia
- 优点:支持分布式开发,高效处理大型工程,支持非线性开发
- 缺点:初学者难以学习,三阶段的概念复杂且易混淆
-
GitHub 参考:Wikipedia 参考:博客
- 优点:基于git,不仅支持git的各项功能,还拥有对文档、issue、wikis、个人主页、Gist等的支持,成为了一个交流的平台
- 缺点:可能不是捕捉创意过程和记录创意点子的最佳工具;非常适用于代码跟踪,但是却不是最好的设计跟踪工具
-
Bugzilla 参考:Wikipedia
- 优点:轻量化,高速高效,开源,容易在各种数据库、工具和操作系统下使用
- 缺点:只能支持缺陷追踪和测试
-
Trac 参考:维基百科
- 优点:有网页界面,能把bug数据库、版本控制系统和wiki结合起来,支持Git、Mercurial等多种版本控制系统
- 缺点:功能较为简单
-
- 优点:高性能、可扩展性、分散性、完全分布式合作开发、能同时高效地处理纯文本和二进制文件,以及分支和合并功能,以此同时保持系统的简洁性
- 缺点:功能比git简陋,没有命名空间,一旦和很多个版本库交流容易导致混淆
Wikipedia 通过统计Alexa Rank来对源代码管理软件进行排名。对于表格中没有的软件,我们也可以通过找到其官网,查询Alexa指数来进行相对排序。
选择两个源程序/项目管理软件进行实践
Git
(图中commit有本人账户信息)
git作为最常用的源程序版本控制软件,被内嵌到了Visual Studio, VS Code, Intellij系列, Apple XCode等IDE中。
且能通过IDE的图形化界面直观地看到commit和branch的变化,且能方便地进行文件比较等操作,比起控制台git对用户更友好。
GitHub
(图中右上角为本人帐户)
GitHub不仅作为一个git的网页版平台,更支持issue、pr等功能。
以issues为例,用户可以将产品的bug和使用中的疑问发布到issues上,对开发者进行直接的反馈。
此外,开发者还可以直接从用户口中听到对产品的要求、建议、疑问等,能将GitHub作为一个产品发布页,更直接地了解用户的需求,以改进自己的产品。参与讨论的用户还可以订阅issue帖子以获取最新资讯。