您的位置:首页 > 其它

软件工程开发之道:了解能力和复杂度是前提

devcloud 2020-09-04 17:15 357 查看 https://blog.csdn.net/devcloud

小引

在本文中我们将探讨如下问题:

1. 软件工程需要哪些能力以及如何保障这些能力?

2. 哪些地方我们需要注意复杂度的问题?

3.  考试的目的是什么?

4.  莫要让规范束缚了我们的手脚,成为技术的奴隶。

5.  要让人的能力发挥到极致,良好的心境是必须要有的。

6.  专注于自己擅长的事情。那么,在软件工程当中,这样的理念应该如何贯彻呢?

7. 为什么我们需要对代码和设计进行重构?如何做?

8.  如何保证软件开发的质量呢?

能力

能力是成败的关键,这一节我们会探讨一下软件工程需要哪些能力以及如何保障这些能力。

所谓软件工程能力实际上就是解决具体问题的能力,也就是把实际中的问题转化项目代码的能力

说一下人员能力的提升这一块儿。一个项目中一定要有一个灵魂式的人物。尽管我们说现在的软件工程开发是一个团队的合作成果,但是这个团队中必须要有一个大脑,不能有多个大脑。

这个怎么理解呢?对于小的团队来说,假设有10个人的团队,那我们就说组长就是这个团队的灵魂。组长需要带领大家进行调研工作,最后作出结论进行取舍。这地方可以理解为架构设计方向的制定

这一步看清楚以后,接下来就需要把这些活儿分配给各个成员组长需要紧密跟进项目的进展,比如说遇到难题了,组长需要跟成员一起去解决掉,而不是交给成员去单独攻克。

如果没有难题,成员单独解决了,那么组长需要把解决方案理解透彻,把好关,同时好好学习

对于组长的要求是假设整个团队10个人,只剩下组长一个人,他也应该有能力把这个项目维护下来

上面是对组长的要求,这里第1位的是学习能力,就是对于未知领域的热爱和领悟能力。

接下来说组员。组员第一要务就是把分配下来的任务好好完成。

这里面需要理解力和执行力的培养。这个需要一段时间的磨合,整个团队才能够形成强大的战斗力。

再一个是主观能动性的培养。如果任务完成了,就应该主动去寻找新的任务去做,有活的时候好好干,没活的时候找活抢着干。

培养主观能动性需要驱动力,一般来说有这么几个: 

第一,是自我价值实现的欲望,首先是天生我才必有用的自信,也就是每个人都想做些事情,寻找自身的价值,并把自身价值融入到团队的工作当中。

第二是外在的奖励,这些奖励可以包含物质上的,名誉上的等等。也就是杰出的工作得到了认可。

上面是对于组员的要求,这里处于第1位的是执行力,就是得到指令以后快速完成任务的能力。

现在说一下工程方法这一块。比较流行的算是敏捷方法论。在敏捷方法论中一般有两种方向一种是开发团队驱动,一种是项目经理驱动。不管采用哪一种方向,这种方法论的一个基本要求就是能够在短期内有看得见的输出,并且有持续的输出

这种方法论用的舒服了的话会给整个团队带来很强的成就感和昂扬的斗志,从而激励团队成员把工作当做一种乐趣。在现实的应用中敏捷方法论可能会被形式化,比如每天大家都站在那里花几分钟的时间讲几句话。如果是这样子的话,就走偏了。 为了避免形式化,应该以输出为导向。及时向其他团队成员更新自己的状态。

现在说一下算法和逻辑部分。对于软件技术,我认为大多时候是把它当做一个工程技术来运用的,也就是拿着这个工具去解决实际的用户需求的。在技术运用的过程中,我们会不断地使用各种各样的算法和逻辑来随机应变的处理我们的业务流程。对于具体的算法和逻辑,完全是case by case的。我们先不深入探讨个例。我们要探讨一个非常重要的概念,就是复杂度的问题

我与很多程序员共事过,尤其是高级程序员,发现很多人都有一个习惯,喜欢把简单的问题复杂化。美其名曰要考虑周全,要考虑周到。这里说一个很简单的例子,比如说我们拿到一个项目,这个项目的需求是拯救地球

很多程序员上来就会陷入到思考如何拯救星球的迷雾中。这个思路的第一要务就是要先区分有多少种星球,然后对这么多的星球进行分门别类。然后在项目运行时判断某个输入参数来指定是地球以后,再进入到思考如何拯救地球的任务当中去。 

如果你问为什么要把这个问题思考的这么复杂,因为我的需求只是拯救地球而已。一个非常高大上的理由就是他想做一个通用的项目,以后可以支持更多的星球,从而方便扩展。

基于这种思路去做项目,项目会越做越复杂,团队会越来越庞大,成本自然也就急剧的上升

亚马逊在这个方面是吃过很多苦头的。在早期的项目中,有些程序员设计项目过于复杂,导致这些人升职离开项目以后,其他人根本无法接手维护这个项目,即使再去找原来的设计者,他们也无能为力了。因为复杂度太高了。

关于流程和工具。这两个方面可以合在一起说。流程需要简洁高效,直击要害解决问题。工具也是一样的。虽然每个人的喜好有些不同,有的人喜欢界面,有的人喜欢命令行,这个都没关系,那就选能够给自己带来最高工作效率的那种工具和流程

在嵌入式驱动开发领域里面,有些公司是用普通文本编辑器来写代码的,代码审查是用比较软件的方式手工合入代码的。虽然驱动式开发中的代码量不是应该特别多,比如说一个driver,如果代码量很大的话,可能就存在设计上的问题了。即使代码量很小的情况下也应该使用比较先进的工具来处理, 比如代码编辑可以使用vs code, eclipse, qt creator等等,代码审查可以使用平台工具如github, gitlab, bitbucket, gerrit,等,代码查看可以使用git工具( fork, git extensions)等等。

以上只是用一个例子来阐释避免使用非常原始的工具,既容易出错又效率低下。

复杂度

现在来谈一谈复杂度的问题,软件开发中的复杂度当然是越低越好。一般谈到复杂度,我们可能想到了各种逻辑上的复杂度,设计上的复杂度,实际上在软件过程中复杂度涉及到方方面面,我们来看一下,具体有哪些方面我们需要注意复杂度的问题。

第一是命名规则。先举个例子,我定一个变量叫word。有的人喜欢把它写成wd。这个就增加了这个变量定义的复杂度,你从wd很难明白,这个变量是word的意思。

不管是变量的命名还是函数的命名,我们都希望看到名字,我们应该能够理解这个变量或者函数大体是关联到什么样子的事情。

所以谨慎的使用缩写是避免命名规则复杂度提高的重要前提。

第二是程序逻辑的复杂度线性顺序执行的复杂度为1, 出现分支以后要乘以分支的个数分支可以是条件判断也可以是循环。所以尽可能的避免分支的出现是降低程序逻辑复杂度的重要手段。

如果程序分支不可避免,要尽可能的把程序分支放到最高的逻辑层。这样做的目的是为了避免在下层处理的时候出现发散式的分支。发散式的分支会急剧的增加程序的复杂度。

复杂度越高,程序越难维护,复杂度超过一定程度,人类程序员是无法处理的。

第三是架构设计的复杂度。架构设计涉及到模块设计和系统设计。要尽可能的把一些公用的模块或者子系统抽取出来,比如安全相关的,日志相关的,工具相关的等等,这些公用的功能可能会被所有其他的业务模块或系统所调用。

在调用这些公用功能的时候,越简单越好,并且调用者不需要关心具体的内部实现,只需要知道如何使用就可以了。

这样做的目的是让程序员专注到业务代码的设计上来

第四是系统部署的复杂度。系统部署包含几个不同的阶段如开发阶段,测试阶段和生产阶段。不管是哪个阶段,部署的步骤越少越不容易出错。有些系统天然的需要很多指令的配置,如果是这样的情况,需要编写一个批处理的文件来简化外部使用者的部署步骤,把多个步骤变成一步

与部署相关联的还有集成部分。如果能够实现自动化或者从模板中创建那是非常好的状态。

第五是测试的复杂度。测试分白盒测试和黑盒测试。白盒测试的复杂度直接关联着代码层级的复杂度,代码层级的复杂度越高,当然白盒测试的复杂度也就越高

白盒测试需要注意的一个重要问题是不要使白盒测试这部分的代码脱离实际业务代码的设计。也就是说白盒测试它的依附对象就是我们实际的业务代码,从架构设计上说是一个附属层,不要试图在这里使用什么软件设计艺术或者所谓的编程艺术。

这种代码的风格就是简单直接,复杂度线性化

黑盒测试的复杂度来自于业务需求分析。要有非常清晰的文档说明,需要对测试步骤和预期结果写的非常清楚。

第六是技术的复杂度。技术的发展趋势一般是越发展越简单,功能越强大。那么在设计和开发的过程中,要避免使用老旧的技术。关于技术框架的选择,要提前做好调研。前端选什么框架,要不要选择某些UI库,后端选什么框架,要不要选择某些程序库,原则上是为了简化我们的学习过程,提高开发效率,增强整个项目的可维护性。需要具体问题具体分析。

第七是队伍结构的复杂度队伍构成一定要短小精悍,人多不一定好办事。像亚马逊提倡的是两张披萨团队,意思是说整个团队两张pizza就能吃饱。大体估算就是10人左右的一个队伍。当然这只是一个参考指标。

整个队伍的目标一定要明确。所有的人都向着那个目标迈进,分工可以不同,但是目标一定要一致。

目标+分工是队伍成功运作的关键。具体来说就是把目标分成多个任务,每个任务里又可以分成小任务,那所有的人都去做对应的任务,自己让自己忙起来,而不是别人让你忙起来

(未完待续……)

标签: