头图

前言

聊聊大学期间学习的《软件工程导论》吧,长这个样子:

image.png

刚上这门课的时候,我上课是很认真的,我很努力的去听课去学习,但是我发现我对书上的这些UML方法、敏捷开发流程啊,有一点理解,但好像又悬浮在我周围。于是在学了一个月之后,我就开始翻起了我所感兴趣的书籍,有的时候是玩手机。课程结束之后,我感觉好像学到了一些东西,比如UML、软件工程开发模式(瀑布开发、敏捷)、ER、面向对象五个基本原则等。但是我感觉又是什么都没学到,随着这门课的结束,这些概念慢慢的从我的脑袋慢慢中淡去,随着编码的变多,我开始审视我的代码,以下问题出现在我的脑海:

  • 面向对象的五个基本原则该如何取舍,这五个基本原则是无条件要遵守的吗?
  • 该如何看待我们的软件?
  • 那些软件开发模式又是什么?
  • 该如何衡量一个软件工程师?
  • UML有那么重要吗?
  • 设计软件该如何设计?
  • 设计一个框架、一个库、一个应用型软件的不同在什么地方?

这也许就应该是软件工程回答的问题 ,但为什么我当时学习《软件工程导论》的没有这种感觉呢? 也许是当时的代码量比较少吧,我在上《软件工程导论》的时候,还没尝试构建过一个小型的项目,也许是教学方式的问题,这门课的授课方式还是那种老师在上面讲书上的概念,类似于语文课的模式,老师是经历过软件开发的,但是当时的我们没有合作开发过,也许对”软件”有一点理解了,但此时对于工程还没有体会。也许《软件工程导论》这门课本身就应该是在实践中学习(learning in doing)的课程。

我希望得到以上问题的答案,于是我打算重学软件工程,但是我并不想再用《软件工程导论》这门教材,我在豆瓣中发现了另一本软件工程的教材《构建之法》,我大致试看了几章,觉得这本书能回答上面我提出的问题,于是我就买了下来,仔细读了一下发现还有意外收获,现将读书笔记分享给诸君,希望对诸君会有所帮助。

该如何衡量一个软件工程师?

今年我换了工作,也经历将近十几场面试,我是一名Java后端工程师,所以面试的主要技术点如下:

  • 集合: LinkedList ArrayList CopyOnWriteList HashMap ConcurrentHashMap
  • 框架: Spring Spring MVC Spring Cloud Spring Boot MyBatis
  • 数据结构与算法: 排序算法、二叉树
  • 计算机网络: UDP、TCP、HTTP、HTTPS、WebSocket
  • 数据库: 索引、SQL优化、事务、事务的隔离级别
  • JVM: 垃圾回收算法、垃圾回收器
  • 多线程: 线程池 CountDownLatch 锁

面试的基本流程一般是: 笔试->技术面(可能是几面)->HR面。面试官面试的方法大多都是问答题模式,有的是看了我的博客和期望薪资问的特别细节往偏了问,而有的则是想到哪问到哪,也有一些让我感觉比较有意思的面试,逐层深入。面试之后我就在思考这么一个问题,这样的方式面试是对的吗?这样就能够衡量一个软件工程师吗? 我之前加过一些技术群,看到了一些应届生的面大厂的情况,大厂似乎也是这么个面试方法,问答题。大厂是能够引领技术风潮的,我在跟他们交流的时候,似乎普遍认为搞搞分布式、算法和数据结构、设计模式、源码,这些是最能衡量一个软件工程师。这也形成了一个循环圈,大厂面这些技术点,然后各个技术视频讲如何答。那这些是对的吗? 这样的方式似乎从我毕业开始面试就是这样,问了之前经验比较丰富的同时,似乎三年前的面试也是这样,从来如此,便对么。

那我问我自己如果让你去面试呢? 你会如何面试一个人,你会如何问呢? 或者更进一步如何衡量一个软件工程师呢?

问: 你的职业是软件工程师吗?

答: 是

问: 你觉得你的”职业”到哪一程度?

答: 嗯,我在一个能发工资的地方上班,靠我的软件技术挣钱,所以我相当的职业。

问: 像职业篮球队员那样职业?

答: 差不多吧。

问: 职业篮球队员都有很详细的记录说明,例如,下面的表格说明了NBA职业篮球远动员的赛场表现:

image.png

图表显示了队员出场次数、首发、时间、投篮、命中率等。作为一个职业软件工程师,你有类似的数据说明你所有的职业活动和成绩么?

答: 嗯…… 没有。。唯一的数据是我的”上场时间”还是挺长的,而且经常打加时赛—加班。

要用图表来衡量一个软件工程师似乎有点困难,软件工程师从事的工作似乎更为复杂一点,那如何衡量一个软件工程师呢?

我认为可以从以下几个方向去衡量,或者软件工程师可以考虑从以下几个方面去成长:

  1. 积累软件开发相关的知识,提升技术技能(如对具体技术的掌握,动手能力)。
  2. 积累问题领域的知识和经验(例如: 对游戏、医疗和金融行业的了解)

    第一点和第二点在简历上大多都可以看得到,也可以比较容易的检测出来,随着经验的增长,一个工程师可以掌握更广泛、更深入的技术和问题领域的知识。

  3. 对通用的软件设计思想和软件工程思想的理解

    这一方面就比较虚,什么是好的软件设计思想? 什么是好的软件工程思想? 一个工程师开了博客,转发了很多别人的文章,折算有思想吗? 另一个工程师坚持做任何设计都要画UML图,这算有思想吗?

  4. 提升职业技能(区别于技术技能)
    职业技能包括: 自我管理的能力,表达和交流的能力,与人合作的能力,按质按量完成任务的执行力,这些能力在IT行业和其他行业都很重要。
  5. 实际成果
    绝大部分软件工程师的工作成果都是可以公开的,你参与的产品用户评价如何?市场占有率如何? 对用户有多大的价值。 你在其中起了什么作用?行胜于言,这些实际工作成果,是最重要的评价标准。

我目前粗浅的看法是绝大多数软件工程都会选择第一个方面去成长,剩余几个方面大多没人会想,也很少会有人去想到。

该如何看待软件工程

该如何看待软件

几乎所有的程序员都知道: 程序 = 数据结构 + 算法。那这里我们自然提出了一个问题软件是什么? 软件对应的英文是software,是可以运行在计算机及电子设备中的指令和数据的有序结合。软件有各种分类方法,一般我们将软件分为下面几种:

  • 系统软件: 操作系统、设备驱动程序、工具软件等
  • 应用软件: 用户使用它们来完成工作,从管理核电厂到写文章,或者是通信、游戏、浏览网页、播放视频等。
  • 恶意软件: 软件病毒等。

那么我用Java写了一个HelloWorld , 像下面这样:

image.png

这个算是一个程序吗?算是。算一个应用程序吗?勉强算是,它的用户似乎只有我,应用场景就只有输出Hello World保保平安。那他算是一个软件吗? 似乎并不算是,回忆一下《软件工程导论》中介绍的软件,参与者和面向的用户都比较多,而且相对来说生命周期比较长。像我上面写的那个程序似乎运行结果出来之后,他的生命周期就结束了。因为它的作用仅仅是给我贴图用的。那么当一个程序有了许多用户之后呢?这些用户都对这个程序有着不同的需求,我们考虑的似乎就要很多了,我们不仅要保证满足需求,而且要保证服务质量。这让我想起小孩子在沙滩上会用沙子搭建小的城堡,那这些小孩子用沙子搭的小房子算的上是建筑物吗? 并不算是,因为这些小房子没人可以住进去。那么我们要搭建起供人所居住的房子呢? 我们就应该用工程的角度去考量了,因为这要考虑的东西很多,比如工期(预计多长时间完成)、建筑面积、建筑风格,房子的使用寿命。

我们将建房子类比到开发软件,也是同样的,当这个软件一开始的设计初衷是面向一定量的用户的时候,写程序就不可能那么松散随意,我们也要考虑工期,软件架构,软件的使用寿命。那么我们可以将软件这个概念往前推广和拓展一下,即软件 = 程序 + 软件工程。为什么是软件工程呢? 因为软件工程不同于土木工程,比如一栋已经建筑完成的二十层高楼,快完工的时候,没人会提出在这二十楼层下面加一个地下室,但是软件开发领域你会常常看到这样的改动需求。

该如何看待工程

工程是常用在日常出现的频率是很高的,生物工程、土木工程等等,那什么是工程?

工程: 创造性地应用科学原理,设计和实现建筑、机器、装置或生产过程;或者是在实践中使用一个或多个上述实体;或者是实现这些实体的过程。

从远古到现在,人们互相协作建成了不少工程奇迹,其中有些现在还能看到(例如希腊雅典的帕萨特神庙、古罗马帝国的罗马水道、中国的长城等),封面选的图片是阅江楼,一座六百年后才完成的设计,关于阅江楼的介绍可以参看文末的参考资料。

我们想象这些工程在设计和建造的过程中一定牵扯了大量的计划、计算、各类角色的协作,以及成百上千的人、动物、机械经年累月的劳作。这些因素在后来出现的各种”工程”(如化学工程、土木工程、软件工程)中依然存在。

写到这里,我突然想起了在大学的时候,班里组织过的一次项目比赛,就是用自己的所学写一个项目,我们当时刚学完Servlet、JDBC、HTML、CSS 、JavaScript、JQuery,我们当时自然自信满满,跟有的同学在讨论,有的同学信心满满的表示Java不就是CRUD(增删改查)嘛,我们找个后台模板,写写CRUD就行。当时基本上所有的同学都这么想吧,于是找了个后台模板,节省在前端页面的工作时间,没有什么设计目标,很简单的分配。有些同学在数据库上花了一段时间,用ER图画了又画,但最终大同小异,最终做出来的软件都是为了应付作业而已。我当时参与的项目组是这样的,我的项目组长打算做一个美妆社区,项目组有个同学想用原型图画一下软件应该是什么样,但是后来有同学反应我们做的项目还太小,杀鸡焉用牛刀,具体的分工就是这个页面相关的表、后台设计都划分到一个人身上,但最终目标是什么呢? 我们似乎也没有一个明确的共识,协作也是随意的划分了一下。当时做的软件就像是一间压根就没打算给人住的茅草屋,一阵风吹来,这间房子就塌了。

但是如果是真的是面向用户呢,就是你做的软件是要有人用的呢? 我们就需要设计目标,协作,开发流程。软件在某种程度上像是房屋,但有点不同,一栋楼建完之后结构上已经基本不可能有太大的变化了,但是软件不一样,软件又很像一座城市,在规划城市发展的时候,我们不可能一蹴而就,把城市建设搞得太超前,城市总是随着经济的发展,人口的增多,扩路、规划新城区(对应软件的用户量变多之后的代码重构)。

从建筑的角度来说,没有人会认为建房子只有搬砖、和水泥,这似乎对应到服务端就是增删改查,我们是在用这些构建一个工程,在构建的过程中,我们考虑的点有: 安全性、易用性、性能。这也就是考虑问题要考虑全面,不要做盲人摸象,只看到一部分便觉得那是一个整体。

该如何去看待软件工程?

到了这里我们已经讨论过了软件、工程,大致得到了一个推论: 软件 = 程序 + 软件工程,那什么是软件工程:

软件工程是把系统的、有序的、可量化的方法应用到软件的开发、运营和维护的过程。

软件工程包括下列领域: 软件需求分析、软件设计、软件构建、软件测试和软件维护。

软件工程和下列的学科相关: 计算机科学、计算机工程、管理学、数学、项目管理学、质量管理、软件人体工学、系统工程、工业设计和用户体验设计。

上面的公式是一个相对来说有点狭隘而简单的公式,广义的软件工程也包括用户体验、用户界面设计等。

我们上面提到过程序 = 数据结构 + 算法,那是不是可以把这个等式带入到上面等式中呢?

软件 = 程序 + 软件工程 = 数据结构 + 算法 + 软件工程。

这样带入是不可以的,事实上,上面的加号我们可以理解为和,一个好的软件,即使功能和同类软件区别不大,但却会让人感觉非常好用。这就是软件的用户体验(User Experience)。用户体验和数据结构、算法并没有直接的关系(如果你非要说我写的SQL让响应速度很慢,这样用户体验也很差,你也看到很多建筑质量非常好,但是也被评为失败的建筑),但是很多非常成功的软件就赢在这个方面。

对于程序 = 数据结构 + 算法这句名言,几乎所有的程序员都知道,但是在实际的学习和工作中,也有不少人产生了疑问:

  • 我用C语言实现了二叉树的遍历算法。在这里,二叉树是数据结构,遍历的实现细节是算法,C程序是结果。但是这个程序有什么用处呢? 在Java和其他一些语言中,似乎没有指针,那我可以不必了解二叉树吗?
  • 我成了一名职业程序员,但是我发现所有的算法别人都已经实现了,我只要调用就可以。似乎我们公司的软件与数据结构、算法的关系不大。那我当初辛辛苦苦学习的数据结构和算法有用吗? 如何区分一个好的程序员和不好的程序员呢?
  • 我上班后,发现以前同事写的程序真垃圾,根本看不懂,无法维护。我要推翻重写! 后来一个老员工笑嘻嘻地告诉我,我们现在看到的程序,就是去年的新员工推到重写之后的结果,大家反映还没有以前的版本好用呢。

我这里想有的重构只是将原先别人的代码风格换成自己的风格而已。到这里我们似乎可以得出这么一个结论,程序(算法、数据结构)是基本功,但是在算法和数据结构之上,软件工程决定了代码的质量;商业模式影响了一个软件企业的成败。

写在最后

本文主要是《构建之法现代人软件工程》的读书笔记,以我的方式将《构建之法》讲述的东西组合了一下,是一篇读书笔记。
封面的图片是阅江楼,当时在写这篇笔记的时候,觉得软件工程和土木工程有点像,于是就想想找一些美丽而又成功的建筑图片,但是我又想一栋高楼建完之后,还会大规模的调整结构吗?应该是不会的,这是相当危险的举动,但是一个软件在面对不同的用户量,是会慢慢的调整内部的结构的,这是软件工程相对于其他工程的不同点。

参考资料


北冥有只鱼
147 声望35 粉丝