0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

为什么说软件开发过程是一个复杂过程

5RJg_mcuworld 来源:互联网 作者:佚名 2017-10-23 09:09 次阅读

问题的分类

最初在1999年被Dave Snowden开发出来的Cynefin框架尝试把世界上的问题划分到了5个域中(大类):

简单(Simple)问题,该域中的因果关系非常明显,解决这些问题的方法是 感知-分类-响应(Sense-Categorise-Respond),有对应的最佳实践

复合(Complicated)问题,该域中的因果关系需要分析,或者需要一些其他形式的调查和/或专业知识的应用,解决这些问题的方法是感知-分析-响应(Sense-Analyze-Respond),有对应的好的实践

复杂(Complex)问题,该域中的因果关系仅能够从回顾中发现,解决这些问题的方法是探索-感知-响应(Probe-Sense-Respond),我们能够感知涌现实践(emergent practice)

混乱(Chaotic)问题,该域中没有系统级别的因果关系,方法是行动-感知-响应(Act-Sense-Respond),我们能够发现新颖实践(novel practice)

失序(Disorder)问题,该域中没有因果关系,不可感知,其中的问题也无法被解决

显然,软件开发过程更多地是一个复杂(Complex)问题。在一个产品被开发出来之前,不确定性非常高,团队(包括业务人员和技术人员)对产品的知识也是最少的,而且需要大量的学习和尝试才可以明确下一步可能的方向。不幸的是,很多时候我们需要在一开始(不确定性最高的时候)就为项目做计划。这种从传统行业中非常适合的方法在软件开发领域不再适用,这也是敏捷开发、精益等方法论在软件开发中更加适合的原因。

正因为软件开发事实上是一个学习的过程,我们学习到的新知识反过来会帮助我们对问题的定义,从而带来变化。这里的变化可能来自两个方向:功能性非功能性。

功能性的变化指随着对业务的深入理解、或者已有业务规则为了匹配市场而产生的变化。比如支付方式由传统的货到付款变成了网银付款,又变成了微信支付、支付宝扫码等等。一个原始的电商平台仅仅提供基本的购物服务,但是后来可以根据已有数据产生推荐商品,从来带来更大的流量。这些变化需要体现在已有的代码中,而对代码的修改往往是牵一发而动全身。

非功能性的变化是指随着业务的发展,用户规模的增加,数据量的变化,安全认知的变化等产生的新的需求。比如100个用户的时候无需考虑性能问题,但是100万用户的时候,性能就变成了必须重视的问题。天气预报应用的数据安全性和网络银行的数据安全性要求也大不相同。

而在业务提出一个需求的时候,往往只是一个简化过的版本。

非功能性复杂性

这是一个经过设计师精确设计的界面,在它被设计出来之前,用户事实上无法准确的描述出它。设计过程中经历了很多的诸如:

  • 线框图

  • 颜色的确定

  • 交互的动画

  • 信息层次

往复多次之后,界面确定了。在没有仔细思考使用场景的时候,开发会误以为这个功能非常简单。但是如果你是一个有经验的开发者,很快会想到的一些问题是:

  • 在宽屏下如何展示

  • 在平板上如何展示

  • 手机上如何展示

  • 即使仅仅支持桌面版,跨浏览器要考虑吗?支持哪些版本?

  • 有些UI效果在低版本的浏览器上不工作,需要Shim技术

除此之外,依然有大量的其他细节需要考虑:

  • 性能要求是什么样的?

  • 安全性要考虑吗?

  • 在网络环境不好的时候,要不要fallback到基础视图?

  • 既然涉及发送邀请函,送达率如何保证

  • 与外部邮件服务提供商集成时的工作量

等等。这些隐含的信息需要被充分挖掘出来,然后开发者才能做一个合理的评估,而且这还只是开始。一旦进入开发阶段,很多之前没有考虑到的细节开始涌现:字体的选用,字号,字体颜色,元素间的间距等等,如何测试邮件是否发送成功,多个角色之间的conversation又会消耗很多时间。

需求的变化方向

作为程序员,有一天你被要求写一段代码,这段代码需要完成一件很简单的事:

  1. 打印”Hello, world”5次

很容易嘛,你想,然后顺手就写下了下面这几行代码:

print("Hello, world")
print("Hello, world")
print("Hello, world")
print("Hello, world")
print("Hello, world")

不过,拷贝粘贴看起来有点低端,你做了一个微小的改动:

for(var i = 0; i < 5; i++) {
 print("Hello, world")
}

看起来还不错,老板的需求又变成了打印”Goodbye, world”5次。既然是打印不同的消息,那何不把消息作为参数呢?

function printMessage(message) { for(i = 0; i < 5; i++) {
   print(message);
 }
}

printMessage("Hello, world")
printMessage("Goodbye, world")

有了这个函数,你可以打印任意消息5次了。老板又一次改变了需求:打印”Hello, world”13次(没人知道为什么是13)。既然次数也变化了,那么一个可能是将次数作为参数传入:

function printMessage(count, message) { for(i = 0; i < count; i++) {
   print(message);
 }
}

printMessage(13, "Hello, world");
printMessage(5, "Goodbye, world");

完美,这就是抽象的魅力。有了这个函数,你可以将任意消息打印任意次数。不过老板是永远无法满足的,就在这次需求变化之后的第二天,他的需求又变了:不但要将”Hello, world”打印到控制台,还要将其计入日志。

没办法,通过搜索JavaScript的文档,你发现了一个叫做高阶函数的东东:函数可以作为参数传入另一个参数!

function log(message) {
 system.log(message);
}

function doMessage(count, message, action) { for(i = 0; i < count; i++) {
   action(message);
 }
}

doMessage(5, "Hello, world", print);
doMessage(5, "Hello, world", log);

这下厉害了,我们可以对任意消息,做任意次的任意动作!再回过头来看看那个最开始的需求:

  1. 打印”Hello, world”5次

稍微分割一下这句话:打印,”Hello, world”,5次,可以看到,这三个元素最后都变成了可以变化的点,软件开发很多时候正是如此,需求可能在任意可能变化的方向上变化。这也是各种软件开发原则尝试解决的问题:如何写出更容易扩展,更容易响应变化的代码来。

小结

软件的复杂性来自于大量的不确定性,而这个不确定性事实上是无法避免的,而且每个软件都是独一无二的。另一方面,软件的需求会以各种方式来变化,而且往往会以开发者没有预料到的方向。比如上面这个小例子中看到的,最后的需求可能会变成将消息以短信的方式发送给手机号以185开头的用户手机上。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 算法
    +关注

    关注

    23

    文章

    4586

    浏览量

    92457
  • 软件工程师
    +关注

    关注

    8

    文章

    217

    浏览量

    21112
  • 智能硬件
    +关注

    关注

    205

    文章

    2325

    浏览量

    107373

原文标题:软件开发为什么很难?

文章出处:【微信号:mcuworld,微信公众号:嵌入式资讯精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    自己做的TAS5825板子软件开发过程中怎么接到PPC3上去调试呢?

    我们打算做一个TAS5825的板子,PPC3软件已经申请下来了,有问题是我们自己做的TAS5825板子软件开发过程中怎么接到PPC3上去调试呢?
    发表于 10-15 08:15

    直播软件开发过程中,如何选择流媒体协议?

    `在直播软件开发过程中,我们可能会遇到些困惑。像是对于流媒体协议的选择,如HTTP-FLV、WebRTC,RTMP,HLS及其它私有协议等,到底哪个比较合适?哪种协议可以用在PC平台上?哪种协议在
    发表于 08-21 14:34

    嵌入式软件开发过程

    在嵌入式软件开发过程中,般来说,花在测试和花在编码的时间比为3:1(实际上可能更多)。这个比例随着你的编程和测试水平的提高而不断下降,但不论怎样,软件测试对般人来讲很重要。很多年前
    发表于 10-27 07:28

    嵌入式软件开发过程中的模块化

    对很多人来,嵌入式软件开发过程中模块化(Modularization)是海市蜃楼、是书面词汇、是
    发表于 12-20 07:22

    嵌入式软件开发过程之程序代码分层

    在嵌入式软件开发过程中,在程序架构的搭建完成之后,为了提高项目代码的可读性和可维护性等,应对程序代码分层
    发表于 12-21 06:13

    嵌入式系统的开发过程

    并行交互进行,这样嵌入式软件开发已经成为项很复杂的工程。   嵌入式系统的开发过程如下:
    发表于 12-22 08:15

    利用RealView MDK仿真功能的CAN总线的软件开发过

     RealView MDK具有强大的仿真功能,能仿真很多ARM芯片内部外设。文章以RealView MDK为开发环境,叙述了CAN总线的软件开发过程,并给出了仿真结果。   0 引言
    发表于 07-16 10:57 2094次阅读
    利用RealView MDK仿真功能的CAN总线的<b class='flag-5'>软件开发过</b>

    KnowleSys软件开发过程指南

    软件项目的成败并非在于完全的技术层面的考虑上,而是取决于项目本身是否被小心规划,谨慎执行。绝大部分软件项目都可以以种几乎保证成功的决定性的方式进行。本开发过程
    发表于 04-13 22:50 10次下载
    KnowleSys<b class='flag-5'>软件开发过程</b>指南

    嵌入式软件开发过程中基于功能点的缺陷度量李冰

    嵌入式软件开发过程中基于功能点的缺陷度量_李冰
    发表于 03-14 08:00 0次下载

    GitHub开源软件开发过程影响因素分析

    通过分析GitHub开源软件开发过程,提出了问题解决速度、问题增加速度等影响因素,并对这些影响因素间的相关性进行了分析.经过实验证明了有些影响因素之间存在定的相关性.同时,根据实验的结果还给出了针对GitHub开源
    发表于 12-28 11:48 0次下载
    GitHub开源<b class='flag-5'>软件开发过程</b>影响因素分析

    软件开发过程中需要的十三类文档

    软件项目开发过程中,应该按软件开发要求撰写十三类文档,文档编制要求具有针对性、精确性、清晰性、完整性、灵活性、可追溯性!
    发表于 09-15 09:03 5969次阅读

    软件开发工程师工作中最艰巨的任务是什么

    软件开发过程中最艰巨的任务是什么?达内软件开发部的工程师们发现他们大部分人认为在软件开发过程中最艰巨的任务其实不是代码。
    的头像 发表于 05-06 14:32 2997次阅读

    简述Geant4 的软件开发过程

    Geant4 的软件开发过程 Gabriele Cosmo(欧洲核子研究中心,瑞士日内瓦)用于 Geant4 协作。 摘要: 自其最早的研发 [1] 以来,Geant4 仿真工具包已经遵循决定项目
    的头像 发表于 08-26 16:22 5095次阅读

    编程与软件工程

    过程为中心的软件工程过程方法论主要有瀑布式与统一软件开发过程。这种软件开发过程需要产生大量的正式文档,通过严格的流程管理控制
    的头像 发表于 09-22 10:56 3391次阅读

    参数——汽车软件开发中最大的挑战之

    汽车软件的应用通常是在软件用于多个型号和迭代的车辆时完成的。参数为开发提供了必要的灵活性,通过巧妙地调整软件来补偿系统变量,从而使软件可重用
    的头像 发表于 02-14 15:30 638次阅读
    参数——汽车<b class='flag-5'>软件开发</b>中最大的挑战之<b class='flag-5'>一</b>