09
Oct
2015

现代软件开发过程是艺术的创作过程

这个问题我思考了很久,从大学开始我一直对软件开发过程有浓厚的兴趣。那个时候IBM的RUP(Rational Unified Process)非常流行,在很长一段时间内,各类大公司的软件开发过程都被我视为圣经,它们强调开发要分“需求分析”、“用例分析”、“系统设计”、“详细设计”、“编码”或者再来个迭代什么的,也学了非常多工程方法,如"UML"、"SysML"、"ERD"、"BPMN""DFD" 等等等等。然而,回首我在阿里五年的工作——其中有业务部门,也有技术部门——我发现,这些看似高大上的东西,在实际过程中根本没有人在用!拿最常见的讨论来说,都是简单粗暴的方框箭头方式,完事后5分钟估计自己都搞不清楚画了些什么;技术文档或者PPT中,虽然有一些看似正规的图表,但其上面各类图定义的标准还差得远,只能说整洁,而近几年比较火的scrum在阿里也只能算个昙花一现;到现在我想没人能搞懂UML 10种图倒底有哪些。总的说来在过去十几年间,各类工程师都试图使用传统的工程思想来试图“规范”(其实这里我更想使用另一个词:约束),结果都失败了,有没有想过这倒底是为什么?

我想答案就在于,我们对软件工程的定义一开始就错了。我们认为软件工程就是传统工程学的沿续,因此就照搬工程界的方法学,从最开始的瀑布模型到最新的Scrum也没有本质的区别,他们都试图创造一种过程,认为只要把软件开发的各个节点都定义好,就像工厂里的流水线生产一样,照着做就可以万无一失,然而事实往往并非如此。主要有三方面的原因:

团队小规模化

现代软件开发团队越来越小,像阿里这种大企业,一般维护一个产品的也就1~2个人,甚至可能出现1/2,至1/4个人维护一个产品的情况,在这种模式下,套用传统工程学的密集劳动力的流水线思想,明显是不对的。


设计与编码(施工)不分离

软件开发是非常特殊的,设计师往往也会参与代码编写,这就意味着开发者需要更多的自由,而不是一味地将UML图翻译成代码,即使某个开发者不是设计师,其往往也渴求参数某一部分的设计,以获得成就感。


需求变化不定

在传统工程学领域,如果你想造一座桥,那么你需要连哪个绞链用什么大小的螺丝钉都设计得一清二楚。然而软件开发却并非如此,一来是软件开的需求在中途变更已或者个修改都已经是习以为常的事;二来,软件不像工程产品设计好了就不再变化了,相对来说,软件是个活物,在互联网时代下,其变化更迅速,很多情况下你甚至不知道明天会发生什么。

 

传统工程学需要将所有的零部件都详细设计清楚


 那么是不是意味着,软件开发就可以胡乱作为?那当然也不是,这里就要说到题目上了,在我看来工程学的上的软件开发应该更多的是一种艺术创作。在艺术的创作途中,艺术家自己构思结构,同时在落实的时候也是自己在实施。艺术家本身需要很大程度上的自由,这样才能创造出好的产品,关于软件开发过程,我觉得很必要参考一下素描的构图过程。在素描创作中,如果我们需要画一个苹果,那么我们一开始需要画一个能容下苹果的矩形,然后再粗加工,至细节修改,最终完成我们的作品。这个苹果在我们脑海里也是逐步出现的,如果我们发现哪里不对,我们就可以及时修正,就像一个生物的生长过程一样,这一点是与传统工程学截然不同的。我将这种开发思维称为不确定性开发。

 以艺术的思维画一个杯子

以工程学的思维画一个杯子

传统工程学与艺术创作最大的区别就在于确定与不确定性。艺术创作的本质就解定了一开始你并不是很清楚最后的作品是个什么样子,需要在创作过程中不停的打磨修订,追求的是创新与特立独行;而工程学则是一个依葫芦画瓢的过程,追求的是精度与标准。

那么艺术创作是不是就是可以随便乱来呢?也就是,就算音乐也是有五线谱的。举素描创作为例,具体来说,分这么四个步骤:

确立构图

根据透视原理推敲构图的安排,确立位置关系,大小关系。

形体结构

用长直线画出物体的形体结构(物体看不见部分也要轻轻画出),要求物体的形状、比例、结构关系准确。再画出各个明暗层次(高光、亮部、中间色、暗部,投影以及明暗交接线)的形状位置。

逐步深入塑造

通过对形体明暗的描绘(从整体到局部,从大到小)逐步深入塑造对象的体积感。对主要的、关键性的细节要精心刻划。

调整完成

深入刻划时难免忽视整体及局部间相互关系。这时要全面予以调整(主要指形体结构还包括色调、质感、空间、主次等等),做到有所取舍、突出主体。



借用其原理,那么对于软件开发来说,也可以映射成四个步骤:



确立产品方向、意图

首先你需要思考你的产品诞生的目的是什么,是为了解决哪些群体的哪些痛点以及企图通过什么的方式来解决这些痛点。

技术方案推敲、设计

我们已经知道需要做什么,现在的问题便是怎么做,用什么语言、框架来实现我们的目的。现我们可以考虑一下我们的系统有几个模块并可以将一些基础、通用的东西代码化,如通信协议、存储访问、缓存等。

模块调整、编码

编码,将之前的设计具体化。在编码的途中我们可能发现问题,比较设计不合理,我们完全可以将这部分擦除掉,重新进行设计。

调整完成

对细节进行一些重构,对性能进行一些优化,风格进行一些调整、统一。


那么这种思想与现在游行的Scrum有什么不同?Scrum我认为只是将长途赛跑成了接力赛而已,这种方式将产品的需求按块进行划分成一个一个的Backlog,然后每次换代完成一些,这个过程被称为Sprint,完成以后进行测试、评估又开始下一个Sprint。这种过程仍然属于流水线似的生产。

Scrum开发模型


而我希望的应该是一种自顶向下,由模糊到精细并且高度自由开发过程,如下:

从左到右依次为“需求分析”、“系统分析”、“详细设计”与“代码编写”


这是一种由粗到细的过程,也是一种由抽象到具体的过程。有的同学可能会问了:“这不是我们熟悉的瀑布模型吗?先是需求分析,然后是模块拆解,再是接口设计,最后便是详细编码”。 对如果只从这里看的话,那确实与传统的软件工程没什么两样,但我说过,艺术创作是自顶向下的过程,上面介绍的只一个细化过程,在整个过程中,这只是垂直的一块。实际上,在开发中会有多个模块同时处于多个状态,而这些状态可能上面的任何一个。

实际开发中的状态

当然这些模块并不是随意布置的,而是从根据需求切分好的,比如我们要画一个魔方与一个水杯,那么我们就需要在画布上先一长方形与一个正方形。而这一过程上面所说的过程自身的迭代,所以整个软件开发就是一个不断将一画面变清晰的过程,从形状上来看便一个树型结构,如下图所示。

不确定开发思维流程示意图

当然我们随时可以对任何部分进行更改,但是低层的更改影响的分支就越多,例如我们如果觉得抽象层2右孩子的技术方案不对,那们我们就必须把抽象层3的两个孩子的”需求、模块设计、详细设计与代码编写“都重新做一遍。如果我们只是觉得抽象层3的代码编码不够优雅,那么我们就只需要对这个分支就行重构就可以了。在实际应用中,需求可能远比上例的要复杂许多,可能模块间的依赖构成的是一张图而不仅仅是颗树,不过只要我们只要按照依赖关系来处理,其实原理都是一样的。总之,我希望达到的就是一个产品,在开发者脑子里,一幅由模糊至清晰的图画。

那么现在还有一个问题:为什么我称之为艺术?艺术有一个特点就是无绝对。有个很好的故事,一次一个学童问他的老师:我怎样才能弹出正确的音符?老师回答说:不用弹出正确的音符,弹出应人愉悦的音符就可以了。传统工程学讲纠的是工艺,精度越高则表示技术越高,然而我们在开发工程类软件的时候,我们根本不需要去拿着笔跟纸去算时间复杂度与空间复杂度吧。大多数情况下,我们就是通过实际指标来衡量我们的软件性能的,如QPS、Load、GC次数之类的,衡量软件好不好用的就是用得着舒服。我这里并不是想向你介绍一种新的开发模式,而不确定性思维。是的,我想说的正是,不要在这些规范上浪费你的时间,没有一种方法是万能的,不管你使用流程图也好,还是UML时序图也要,万不要把自己的思维局限在一种图、一种过程或者一种规范中,大家用着舒不舒服才是终极证券标准。把每个开发者当成一个艺术家,让他们尽情的发挥自己的创造力,而不是使用各种标准来约束他们,让他们变成一个流水线工人。如果我们希望提高代码质量,我们应该做的是使用更多的工具,例如代码自动格式化工具、代码静态Bug检查工具、代码Review Board等。

总之,记住一句话,永远不要去“管理”一个开发者,而是去释放他的潜能,让他尽情的创作!

----------草稿-------------

首先现代软件开发越来越自由化,很多开源社区里

那时候,我视开源软件如粪土,认为他们都是小工作坊,完全没有办法与IBM、Microsoft这种看上去非常正

什么你们有多少人会画UML的全部10种图?这是为什么?

上一篇:2015 云栖大会 下一篇:童年的回忆 Revised 2

评论列表:

发表评论: