编者按:开发项目的初衷很美好,功能需求你都理得特别清晰。可为什么在实际开发过程中,你的软件项目总是需要更改和调整?最终,添加的功能越来越多......要知道,看上去很理所当然的功能列表,实际做下去之后你就会发现事情没那么简单。本文编译自Medium上原题为《Your app is an onion: Why software projects spiral out of control》的文章。
最开始,你的想法很美好。你会雇佣一个开发者来实现自己的创业点子。但几乎每一周,项目似乎都需要进行调整。各种功能开始涌入,范围越铺越大。
就好像项目被赋予了生命,而它正在试图毁掉你的生活。
这一切究竟是怎么发生的?你雇佣的开发者不靠谱吗?还是你没能做好项目管理?抑或是创意自始至终就很糟糕吗?
这都有可能。但是有一个核心误区通常在一开始就注定了项目最终会失败。
我们假设自己的项目是由功能组合定义而成的,我们会将这些功能记在纸上。偶尔再添加一些功能,偶尔又会减掉一些。但你仍然能一眼看到项目的范围。
但是,这种假设是错误的。
你的项目并非存在于二维空间里,它不是一张纸。它有自己的深度。
软件的每一个功能都可以被一层一层得剥开。事实上,如果我倾向于做标题党的话,那我会直截了当得表示你的应用就是个洋葱。让我来解释下这到底是什么意思吧。我会告诉你,为什么你在将自己的应用一层一层剥下时,它会让你流泪不止。
我们来聊点具体的例子吧。给我推荐一个想法吧。
人们通常想看的书,附近的图书馆都没有。但其他地区的人可能会有。因此,这款应用可以让人们发送图书需求,而有这本书的人则会作出响应。每一笔交易,我们都会进行抽成。
这个想法,很有才吧!
我知道,难道不是吗?功能列表非常简洁明了:
现在是时候把产品说明书发给开发者,然后开始给公司考虑一个炫酷的名字了。kaBooki?lib.rari.ly?还是reddit?
欸?别急阿。让我们再稍微深思一下吧。更何况,已经有一个软件叫reddit了。
让我们带着下述这些问题来细究一下你的想法,看看想法最后究竟会发展成什么样子吧。
用户如何交易呢?他们是见面的时候一手交钱、一手交货还是说通过应用来付款呢?
恩,他们应该在应用上利用信用卡进行付款,这样我们才能抽成啊。
他们该如何发送图书需求呢?我的意思是,他们在应用上究竟要做些什么呢?是填写一个包含书名和作者信息的开放式表格吗?
哦......他们应该在应用上搜索图书,然后挑选自己感兴趣的。
好的,那么我们就需要建立一个图书数据库了。
我想应该是这样。
那实际上,究竟什么是图书需求呢?卖书的人能够看到所有的书籍需求列表吗?还是说我们需要像Uber或是Thumbtack那样发送通知告知这些卖书的人吗?
是的,我们需要给那些有书的人发送需求通知。
那么,卖书的人需要在软件里填写自己要卖的书目信息吗?
恩,是的。
那么书该如何完成交接呢?是用户自行交接,还是我们帮忙处理配送问题呢?
我们负责配送。
那你需要一个系统告诉你哪些书需要取货,然后要送往哪里。我想你的司机应该会想知道最短路线怎么走吧,对吗?
好吧,这样可不行。那不如这样吧?让用户相互之间邮寄图书。
那么,我们就这样将收货人的地址信息告知发货人?那我们如何解决运费问题呢?
实际上,你知道的。这些用户都需要靠得近一些。他们可以上门取货,顺便还能认识个新朋友,这样不好吗?
所以,我们需要匹配距离相隔较近的用户。那他们如何找到对方呢?应用是否还需要内嵌一个实时地图,这样才能安排见面呢?
好吧,这样也行。就这么做吧。
我们需要设定图书的价格吗?还是说买卖双方自行商定?
他们自己商定吧,然后确定一个价格。
他们如何确定呢?我们是否要在应用里嵌入一个聊天功能?
他们可以直接打电话进行联系啊。
好吧,那我们是否要发送短信来确认号码的有效性呢?如果......好了,说到这儿你就应该懂我的意思了。我们还可以这样无休止得谈下去。
别,别再就此问题继续聊下去了。
那不妨现在再来看看功能列表长什么样吧。
每一行列出来的内容都可以多次进行延伸。我们只不过刚刚把洋葱剥开了一层皮,结果就已经变成这样了。
现在,你可不要哭啊。
我们要弄清楚哪些原因不会导致功能爆炸。
这也并非是我们常说的功能蔓延。
功能蔓延指的是产品不断添加新的功能。如果你看一下我们最终的功能列表,你会发现每一条功能的存在都符合最初的想法设定。
而这也无关乎任何技术考量。
举个例子,什么是最适合的聊天系统架构呢?最容易整合的支付平台是什么呢?
我们在这儿不会就这个问题多加赘述。一个优秀的开发人员会把各式各样的技术方案都告知给你。但是他无法帮你决定软件需要什么功能。
这也无关什么市场考量。
人们需要这样一个产品吗?在用户数量很少的情况下,你该如何诱使早期用户报名呢?用户愿意为此项服务付费吗?
这类问题必须要和想法的验证、产品市场组合的确定以及定价策略息息相关。再重申一下,这些问题都非常重要。不过,这也并非是功能列表爆炸的原因。
这与全球变暖或是牙仙也没有任何联系。你是打算告诉我项目变成洋葱的原因吗?还是说你打算告诉我每一条非原因项吗?
你可真无趣。事情其实是这样的。
我们从根本意义上就曲解了复杂性的运作原理。
我们原本以为每一项功能的复杂程度就和我们一开始描述得一样。嘿,也许程序员是要花些功夫去写代码的,但是用商业术语中的几个词,你就可以轻松描述出产品的功能。比如说“用户用Y来做X这件事”。不是吗?
可这种观点是错误的。
你离得越近去看,它们就能呈现出更多的细节。
洋葱是分形吗?
不,我只是换了个隐喻而已。继续说吧。
关于功能,我们一开始是基于一个大的蓝图去进行描述的。但是,当开发人员在开发这款应用时候,抑或是用户或你本人使用这款应用时,其实它是在一个较小的规模下进行的。它是一步一步在软件内完成的。每一个步骤,你都会遇到一些问题。为了解决这些问题,你需要重新规划这一步骤、添加新的步骤或是添加全新的功能。
这就像是规划一条从你家到办公室的路线。看着地图,这段行程似乎就是两点连起来的一条直线。
但当你以更小的比例去看这条路线时,你会发现自己原先规划的那条直线并不符合城市道路网。你会遇到交通站、高地或者道路阻塞。基于你是步行、骑车还是驾车,你可能需要规划一条不同的路线。
开发软件也与之类似。当你离得越近去看,你就可以更为详细地意识到你的解决方案是什么样子的。
那可真是太棒了,一路上都是各种细节,这还都是我需要去考虑的。这是不是意味着我的产品永远都完不成了?
是也不是。之所以会显得复杂,原因在于我们在一开始对功能进行了描述,这通常是要实现的目标。之后,我们就会将其放大处理,一步步设计解决方案来实现目标。当我们将细节放大,我们就会发现事情变得愈加复杂了。
复杂本身不是问题。问题是我们选择发现复杂性的方式。我们将功能的规格说明书递交给开发人员。几周之后,我们会拿到应用的初始版本并且进行测试。这是我们第一次一步一步操作整个软件,然后我们就发现很多的漏洞。我们会将修改意见记录下来,然后将其发送给开发人员,让他开发第二版应用。
在整个过程的最后,经过反复几次的修改调整,我们得到了一个较好的解决方案。问题在于,开发周期实在是太长了。每一个环节都需要数周或数月时间来完成,
但是,要发现应用存在的内部复杂性,这又是必要之举。
反反复复和开发人员进行沟通来发现这种复杂性,耗时还烧钱。
我们希望这样做:
我们想要在写代码之前就能尽可能多得发现这种复杂性。我们想要剥下“洋葱”的皮来发现一个更可靠的功能清单,最好能以一种快速且便宜的方式。
我们并不想来回修改应用,而是想要反复修改软件规格书。
我们想要从这个流程:
变为这个流程:
为了高效做到这一点,我们需要两个东西。首先,我们需要一种方式来呈现功能列表,以便之后反复修改调整。第二,我们需要一种高效的方式来审视这份功能列表。
我们来聊聊该如何实现这两点吧。
我们不必再用商业术语来考虑这一点,而是要把自己当做是一个用户去思考功能需求。在这个层面上,我们就需要应对软件复杂性问题了。
首先,列出用户目标。用户使用你的app要做什么呢?
接下来,你需要规划用户流程。以用户的角色确认实现目标所需要的每一个步骤,记录下这些内容。
我们要建立一张用户使用应用的流程图。
有很多种方式可以实现这一点。你可以简单做一个所需步骤的略图。你可以针对用户看到的每一个界面进行版面设计。你还可以在纸上或是用软件画出流程图。
图中是一种版面设计。
不管你选择哪种方式,确保优先考虑速度问题。除非你是Photoshop领域的专家,否则还是放弃使用软件,拿起纸笔来干活吧。
确保略图中能呈现出每一个界面。举个例子,如果一个特定的步骤需要在屏幕上以多个界面呈现出来,那你就需要将该步骤分开。我们希望能梳理出更多的细节。
此过程应该能揭示出应用中存在的一些复杂性问题了。
现在,我们要开始从更深层面来挖掘了。
像我们之前问的那些问题未免太过宽泛了。这很难找到切入点。
首先,我列出了一些适用于大多数软件的常见问题。这些问题会被分为四大类,你可以将其当做是模板来提问自己的软件略图。
仔细观察略图中的每一个步骤,拿列表上的每一个问题问问自己。如果答案呈现出了新的步骤,就将其添加在你的软件略图里。
这些问题是用户在输入信息到产品中时候会碰到的。
· 用户会输入什么样的信息?
· 输入的是信息是开放式的还是交互式的?
· 开放式信息举例:输入自由格式文本内容、选择图片进行上传或录制视频。
· 交互举例:往搜索框输入文本来显示可选结果、在地图上选择地址、从预定义选项组合中进行选择。
· 是否有些输入的信息应该被当做是无效的呢?应用又将如何处理呢?
· 是否有无源输入呢?最常见的例子:通过GPS 进行用户定位。
· 产品需要获取新用户 (https://www.useronboard.com/)的什么信息呢?用户后续可以对信息进行修改吗?
如果之前那部分算作是信息输入,那么这部分应当是信息输出。
· 屏幕上哪些信息会被呈现给用户?
· 信息是以何种方式呈现的?比如说:文本、图片、地图、列表或图表。
· 这些信息需要以某种形式进行筛选吗?比如说:距上次使用时间、用户距离、相关性等。
· 产品是否可以主动和外界进行交流?比如说:邮件、推送通知、短信。
这部分问题是关于软件体验中各个部分之间的交互。
· 用户会彼此之间进行交互吗?比如说:短信、添加好友、点赞或是给其他用户内容加标签。
· 用户是否会和外界服务发生交互呢?比如说:付费服务、物流追踪、社交媒体账户登录。
· 产品是否会和外界服务发生交互呢?比如说:位置查找服务、天气应用程序接口、社交网络(“你的朋友XXX刚刚加入了!查看他们的信息!”)
这部分问题是关于企业家对于产品的需求。
· 你需要通过邮件或其他媒介发送提醒或介绍吗?
· 你需要为自己或员工提供专门的系统吗?比如:为配送人员提供导航软件,为厨房员工提供实时点餐管理接口。
· 你需要手动批准用户/内容的接口吗?
· 你需要一个内容管理系统吗?它可以让管理员轻松撤除内容或让用户账户失效。
还有很多很多的问题。
这就对了!这其实也是人们通常在开发应用早期会遗忘的一些问题。针对你的产品,还会衍生出更多的问题,你需要慢慢发现。
建立软件略图和审核软件的过程会告诉你——你漏掉了哪些内容。重复几次这一流程,之后你就可以更加自信地提供一份可靠的功能清单了。
你知道,我真的希望你有什么妙招能够修缮我的项目。可这听上去工作量好像很大的样子。
事实也确实如此。但是这是你在软件开发过程中必须要做的事情,不论在什么阶段。
记住我们之所以要这样做的原因。无论如何,你都需要发现软件功能中隐藏的复杂性问题。你所要做的仅仅是选择何时剥洋葱。
从本质上来说,你有两个选择:
1. 你可以发现用户目标、构建版图设计或流程图、质疑自己的假设,然后像我们说得那样将软件一层一层剥开。或者说,
2. 你可以让开发人员直接开始开发应用,然后根据开发的每一个版本暴露的问题进行修改,一周一次。在几个月之后,你就会发现这些问题,你本可以在一周之内就用纸笔想明白的。
这也是为什么软件项目常常会变得非常复杂,恨不得将你生吞活剥掉一般。
那么,赶快去发现自己所需要的功能吧。构建版图设计然后质疑自己的假设,用一种快速且省钱的方式发现大量的问题。
此举可以将你从压力和痛苦中拯救出来,帮助你将产品推向全世界,让它如繁花一般恣意盛开。
洋葱会盛开吗?你这比喻可真糟糕。
编译组出品。编辑:郝鹏程