敏捷软件开发背景下的软件设计

待兔 等级 533 0 0

在目前大部分的软件开发组织中,敏捷开发已经成为毋庸置疑的标配。随着数位技术大神和布道师的宣扬和数量庞大的敏捷教练的身体力行式推广,商业环境和客户需求变更速度的日益加快,采用端到端交付周期更短的敏捷开发过程基本已经成为项目成功的必要条件。

软件设计的刚需被敏捷了吗?

工作流程的变更以及开发节奏的加快并不能绕开一个很核心的问题:写出容易维护方便扩展的代码的复杂程度本质上没有改变;软件的维护周期越长,迭代的版本越多,这个基本问题就越突出。要想顺利解决这一问题,只能依赖于系统具有相对良好的设计,使得添加新的功能不会轻易破坏原有的结构,出现问题的时候,不需要大范围地对系统做出变更。

传统的瀑布式方法希望通过借鉴成熟的建筑行业的做法,采用预先大规模的架构设计,对系统做好明确的分割;继而进行不同层次的设计,直到所有可以预见到的需求都得以满足,然后才开始进行的代码的编写和构建。这种方法生产出来的软件交付工期很长,适应性很差,除了少数特殊行业之外基本已经被市场所淘汰。

敏捷宣言提出了一些基本的原则来指导我们怎样用相对更"敏捷"的方式开发和交付我们的软件;通过多个不同的迭代,增量式的构建和持续交付系统来降低风险。然而软件本身的复杂性导致我们不能将客户的需求一对一的翻译成代码,像搭积木一样构建出来一个可以轻易维护的系统。因为新加入的需求很可能导致原有的代码结构无法适应新的需求;某些为了尽快完成需求而做出的关键的假设可能必须被打破导致添加新的需求会破环大量已有的功能。如何做出恰如其分的软件设计,既能满足现有的短期需求,又能平衡潜在的变更。

各种不同的敏捷实践方法论对如何管理用户的需求,如何增强不同角色的沟通,如何实施日常的开发和测试活动,如何验证需求保证已经交付的承诺不被变更所破坏,如何规划和平衡资源和进度等复杂问题都给出了丰富的可选实践供项目管理人员裁剪;对于如何做软件设计以及做多少软件设计并没有很详尽的描述。就连基本的是否需要软件设计,以及需要多少软件设计,怎样算作过度设计都语焉不详。

真的需要软件设计吗?

大部分情况下,对于这个基本的问题我想答案应该是肯定的,除非你是在做一个很小的个人项目。如果需要牵扯到多个人一块合作并且最终的产品需要维护比较长时间,那么起码某种程度的软件设计应该是不可或缺的。毕竟软件开发活动本身也是围绕着人展开的,既然需要多个不同知识背景,不同技能,不同角色的人一起来协作交付功能复杂多变的软件,那么必然需要一些设计保证参与其中的人有一致的理解。

敏捷运动的早期一个常见的误解就是,敏捷软件开发不需要软件设计,不需要软件架构,只需要采用极限编程,将人们聚集一个公共空间里,直接动手写代码就行了;复杂的设计文档都是浪费,都是可以避免掉的,代码就是最好的设计文档。这样的过程可能适合于几个能力超强的程序员聚在一起做的临时小项目,放到更广泛的商业环境则难以持续下去。人员的流动,特殊需求的变更,性能问题的修补会使一个一开始看起来极其简单的几个源代码文件组成的小项目演进成难以维护的“庞然大物”。

如果系统没有明确的分工和边界,没有相对清晰的职责分工和交互限制,软件的结构很容易陷入“大泥球”结构而不可维护,试想如果代码里的每一个包或者类都有可能和另外其它的任意一个类有交互关系,即使是一个绝对代码行数很小的项目也会变得无法继续添加新的功能。

哪些东西应该包含在软件设计中?

所谓的设计其实可以理解为关于如何组织软件各个部分(特性和行为分割)的一些决策,以及做出相应决策的一些原因。

敏捷场景下,重构的重要性以及早已经深入人心,因而容易经由重构来去掉“坏味”的部分就不宜放在设计中。因为一般为了重用的目的都会将设计决策写下来供后续使用;如此一来必然产生一些维护成本;而维护设计文档的开销一般比代码要大很多。因此容易通过重构而优化的部分,放在专门的软件设计中显得有些得不偿失了。毕竟敏捷软件开发的基本思路就是消除浪费,使得投入产出比最大化。

某些跟具体实现技术相关而和核心业务需求关系比较远的决策,大部分也不适宜包含在软件设计中。譬如期望某部分关键数据需要做持久化以保证系统异常重启的时候依然可以恢复。对于业务需求而言,这块数据需要持久化是重要的,但是如何做持久化,又可能是易变的,譬如今天是考虑用文件来做持久化就可以了,将来可能发现不够必须用关系数据库,或者甚至关系数据库可能也不是一个合适的选择,得要用键值对数据库。识别到可能变化的部分,并将不变的部分抽象出来,放入设计中可能就足够了。这样技能照顾到当前的需求,又能满足将来扩展的需要。至于具体是怎样实现的,看代码就足够了。

需求的概念抽象化,和软件的静态模型可以作为设计的中心之一,必须详细考虑并归档维护。之所以要对需求进行抽象化处理,是因为用户的期望可能是模糊不清的,甚至是“朝令夕改”的。敏捷方法强调持续交付就是为了使用户早期得到反馈,及时修正他们的需求,更好的管理客户的期望,避免开发出不符合客户真正预期的产品,浪费开发资源不说也浪费了客户的投资。软件的静态模型是关于大的软件职责的拆分和交互边界,这一部分不仅是当前进一步开发的基本依据,日后万一需要重构也是很重要的参考,值得花力气仔细讨论达成一致,减少日后维护成本。

软件的部署和核心模块的交互在有这方面的变更的时候(新加入模块或者服务等)也需要仔细考虑并作为软件设计的关键活动。模块的边界是粗粒度的系统耦合的地方,一些关键的交互流程也适宜详细讨论并放在软件设计文档中。

系统核心的模块/类以及之间的交互,如果有发生变更,也需要第一时间考虑清楚并放置在设计过程中产生合适的产出,便于沟通和交流。如果模块的粒度足够大(譬如估计有很多的代码),那么哪些部分是对外交互的接口也应该提早考虑清楚,并提取出来以便后续写代码以及代码评审的时候对照,确保设计被正确遵守。

什么时候应该停止继续设计?

敏捷语义下,任何的浪费都是可耻的,代价巨大的设计工作自然也不例外。知道何时还需要仔细讨论搞清楚,何时应该停止变得尤其困难,甚至需要一些接近于艺术化的方法,需要经过大量的实践经验累积和反思才能做到不偏不倚。

如果发现所讨论的问题可能代码实现很容易就能完成,如果考虑不完备,那么修改代码的代价非常小,那么就可以立即停止了;因为设计的目的是为了更好的写代码,更好的维护既有的代码。因此只有重构代码的代价远远大于预先仔细设计付出的代价是,才应该花费力气去做这些烧脑的工作。发现代码实现已经很容易没什么问题的时候,就放手去写代码或者重构代码吧。这种情况往往发生在我们想去“设计”一些内部实现细节,而这些细节对模块的边界以及待修改模块和核心部分耦合很小的情况。

如果是在构建一个新的模块,而这个模块和已有的系统有形形色色的复杂联系(耦合),那么如果这个模块和已有的系统的各个部分的交互已经比较清楚,而且其内部实现估计工作量也很小的时候,那么就可以放心将剩下的工作交给聪明的程序员去继续了。将一些细微的工作也放入设计中,只会使设计文档变得庞大而又难以维护。毕竟可工作的代码比完美的文档更重要,虽然后者也很有价值。

如果对于是否应该继续设计有分歧,可以和其它准备实现的程序员坐在一起讨论(其实任何时候都应该如此,如果团队规模比较小而且时间允许),看将要写代码的程序员是否觉得足够清楚,返工的风险是否足够得小。如果对于一些核心的模块或者类的职责还有不同的认识,或者程序员不知道某些改动是应该新创建一个子包,还是应该在已有的摸个包中修改来实现,那么很可能有些关键的部分没有设计清楚。

决定何时应该适可而止也和你的程序员团队的实际水平和能力密切相关。一群天才程序员可能需要极少的设计来达成基本的共识就可以产出高质量易维护的代码,而水平平庸的程序员团队则需要更多设计上的预先讨论沟通以达成基本共识,减少返工。

工具

软件工程的一个关键要素就是工具。软件设计自然也离不开合适的工具,尤其是软件设计又是对需求进行抽象的结晶;选择合适的工具可以增进协作和沟通,使得设计输出是有实际指导作用的而不仅仅是纯粹的文档工作。

轻量级的文档工具往往使维护和修改变得更加容易,因为设计输出本身也是一个迭代的过程;便于多人评审和协作显得尤其重要。目前主流的方式基本都是基于Markdown和Plantuml的;前者可以用来存放文本,后者则可以用文本的格式来描述UML图。

收藏
评论区

相关推荐

下载二维码至钉盘
后端生成二维码的普通文件流,前端接收后在img标签中渲染 将二维码下载至钉盘通过接口获取后端返回mediaId字段,采用“dingtalkjsapi”插件中的方法下载 注意:dingTalkFun中,除了corId和mediaId必传外,文件名name也是必须要传的!!! <template <div class"onlineSign"
30分钟带你了解Web工程师必知的Docker知识
前言 笔者之前和朋友一直在讨论web技术方向的话题,也一直想了解web运维方面的知识,所以特意请教了一下我的朋友老胡,他对web运维和后端技术有非常多的实战经验,所以在本
头条研发-SRE运维研发实习生视频面试(一, 二面)
(about:blank%E4%B8%80%E9%9D%A230min "一面 (30min)")一面 (30min) 江湖规矩自我介绍, 很罕见的没有用算法题起手, 直接就问很具体的问题, 点个赞 <3 (htt
运维监控系统——Zabbix简介
前言对于运维人员来说,监控是非常重要的,因为如果想要保证线上业务整体能够稳定运行,那么我们则需要实时关注与其相关的各项指标是否正常,而一个业务系统的背后,往往存在着很多的服务器、网络设备等硬件资源,如果我们想要能够更加方便的、集中的监
运维安全-信息安全
本文转自 ,如有侵权,请联系删除。
运维,关于监控的那些事,你有必要了解一下
作者 | 乔克 来源 | 运维开发故事监控是整个运维以及产品整个生命周期最重要的一环,它旨在事前能够及时预警发现故障,事中能够结合监控数据定位问题,事后能够提供数据用于分析问题。一、监控的目的监控贯穿应用的整个生命周期。即从程序设计、开发、部署、下线。其主要的服务对象有: 技术 业务 技术通过监控系统可以了解技术的环
谷歌SRE理论读书札记:SLI、SLO与SLA
趁着这被人扫地出门,无地可去的日子,多学习学习别人的理论知识。 书籍名 《Site Reliability Engineering》网络运维工程,编者Betsy Beyer, Chris Jones, Jennifer Petoff, Niall Richard Murphy第二部分 规则(Principles)
数据库运维做些什么?
一. 数据库生命周期 结合软件生命周期、项目的开展,数据库的生命周期大致可分为这么几个阶段。 (https://imghelloworld.osscnbeijing.aliyuncs.com/8552b8c2942bb8ce23
DevOps简介
DevOps 是一个完整的面向IT运维的工作流,以 IT 自动化以及持续集成(CI)、持续部署(CD)为基础,来优化程式开发、测试、系统运维等所有环节。DevOps的概念DevOps一词的来自于Development和Operations的组合,突出重视软件开发人员和运维人员的沟通合作,通过自动化流程来使得软件构建、测试、发布更加快捷、频繁和可靠。
DevOps概述
DevOps概述DevOps(Development和Operations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营(运维)、质量保障(测试)(QA)部门之间的沟通、协作与整合。随着业务复杂化和人员的增加,开发人员和运维人员逐渐演化成两个独立的部门,他们工作地点分离,工具链不同,业务目标也有差异,这使
DevOps与CICD的区别 及 docker、k8s的CICD思路
1\. DevOps简介DevOps 就是开发(Development)、测试(QA)、运维(Operations)这三个领域的合并。image.png为什么要合并这三个领域?主要是开发和运维的脱节。DevOps是一种思想、一组最佳实践、以及一种文化。DevOps落地实施,从组织架构、设计人员、流程、人员分工、人员技能到工具,变化
一份DevOps工程师职责清单,待你查阅
如果一个组织的开发人员和运维人员是独立工作的模式,实施DevOps就需要对组织进行大的调整。因为,只有具备合适的组织人员,文化和工具来才能成功实施DevOps。根据显示,实施DevOps的最常见的障碍之一是员工缺乏技能。什么是DevOps工程师?DevOps工程师是一位IT专家,应该对开发和运维工作都有广泛的了解,包括编码,基础
运维大佬嘲笑我,这个你都不知道?
大家好,我是阿沐,一个喜欢分享技术而且爱好写散文的程序员。今天来给大家介绍一下info命令查看redis具体的详细信息讲解!起因是:前几年我在老家郑州实习面试(那个时候还没有毕业)的时候遇到面试官提问;面试官来于百度总部的工程师6年java开发经验+3年多的PHP开发经验,我在他的面前基本就是弟弟中的弟弟,虽然勉强通过入职了,但是却被运维无情地嘲笑,就因为组
JAVA回调机制(CallBack)之小红是怎样买到房子的??
JAVA回调机制CallBack 序言最近学习java,接触到了回调机制(CallBack)。初识时感觉比较混乱,而且在网上搜索到的相关的讲解,要么一言带过,要么说的比较单纯的像是给CallBack做了一个定义。当然了,我在理解了回调之后,再去看网上的各种讲解,确实没什么问题。但是,对于初学的我来说,缺了一个循序渐进的过程。此处,将我对回调机制的个人理解,按
做运维的如何利用自己手里的资源增加收入,发财记得感谢我。
现在很多做技术开发的人 都会找兼职给外面接点活赚点零花钱,目前这个市场还是狼多肉少,很难接到赚钱的单子。不妨多找一些方法,我这给大家介绍一个好渠道。如果在公司做运维工作有维护服务器资源的不管是阿里云腾讯云,只要你能登陆账号就可以 公司采购完的订单是可以关联给代理商的,以阿里云为例,在控制台企业合作伙伴项目进去以后你能看到最近购买的订单,每一个订单后面都是有一