Burndown chart
S型的燃尽图
在一次milestone开发过程中,开发者会持续编辑issue列表,每个issue都有自己的生命周期。燃尽图预期这些issues会被线性的消灭掉,所以从第一天直接到最后一天画个直线表示预期进度变化,然而实际开发会遇到各种困难,所以实际的进度变化曲线往往不是线性变化的,下面这篇文章给出了S型燃尽图:
https://sandofsky.com/blog/the-s-curve.html
三进制
计算机是基于二进制的,有一句经典的台词是:这个世界上有两种人,一种是懂10进制的,另一种是懂10进制的。但是在开发中,我们常常要接触三进制。程序开发中有一个Keep it simple, stupid的所谓KISS原则,就是说我们写程序,在没有必要的情况下,不要增加不必要的抽象层。例如很多初学者在刚接触了设计模式之后,就会在很简单的程序上不必要或者不正确的使用各种模式去写代码,但实际上那种程度的代码只需要把面向过程代码写好,做好函数这个级别的抽象即可。函数简洁但并不就简单,和通常的初学者相反,有经验的程序员更愿意用简洁的代码解决问题,而不会为了用上一堆所谓特性把代码写成花拳绣腿。一个函数需要考虑入口条件,出口条件,是否可重入,是否线程安全,所依赖的状态变化…等等。所以,有时如果你不放弃装饰,你就得放弃本质。
但是,程序从开发的第一天开始就被持续迭代。有一句话说:程序从被写下的第一天开始就开始腐烂的过程,这是说程序会因为需求的不断变化而需要不断的被重构,一开始几行的代码可能会膨胀,再压缩,再膨胀,再压缩。不同地方的代码会出现重复,各种各样的重复。于是,光有KISS是不够的,我们需要另外一个东西:Do Not Repeat Yourself,也就是所谓的DRY原则。怎样才能不自我重复呢?这就是所谓的三进制原则,同样一件事,重复做三次,就可以考虑批处理,计算机是最擅长做批量处理的事情,例如for循环,递归等。批处理的前提是结构的一致性,结构的一致为将他们装到容器里创造了可能。所以,为了批处理,我们常常需要在结构上做抽象。一致性可能是数据上的,也可能是行为上的,根据程序即数据的原理,数据的一致性可以用行为的一致性表示,所以我们可以只对行为的一致性考虑。在面向过程语言里,可能就是在函数这个级别考虑,在面向对象语言里,则更多可以在接口层体现。把共同的结构装到容器里的过程,就是组合的过程。
好了,三进制大概说到这里。
我们需要专职的TA么?
从我一开始进入程序员这个行业开始,我就也会被软件开发中的人员配置问题困扰。一个团队,是否要有专职的项目经理,美工,测试,产品设计,以及并不讨人喜欢的行政,人力资源?从程序员的角度来说,属于技术偏好型,能用技术解决的,绝不愿意通过增加一个人去解决,能用工具解决的,一定批量处理之。先进技术和工具,常常在效率上是数量级的压倒性优势。
回到小题,通过几年的过程,我想角色上很多时候这些角色都有其必要性,但是,一个角色要有多个人还是一个人甚至直接由工具取代,则是可以因团队而不同。怎样取舍和适应?我认为关键在于:是否有效率的解决问题,例如开发和测试,如果开发和测试两个人不能很好的协作,共同有效率解决问题,而一个两者皆做的更有效率,那么明显后者更好,反之则选择前者。
因此,角色分离,但人员可以合一。也就是人剑合一。
持续迭代
前面说燃尽图,软件开发,常常是一个长期过程。不是一锤子买卖,一个基础类库开发加一个上层产品开发就可能两年。但市场常常不等人,因此我们要紧凑的过程和质量,那么就需要持续迭代。持续迭代体现在一个milestone之内的每一天之间,需要每天跟踪昨天,今天,明天的进度,解决的issue,新产生的issue,代码的提交,测试的通过率,发布的版本,用户的反馈等等。持续迭代同时体现在milestone和milestone之间,粒度会更大一些。
一个理解持续迭代的地方是解bug,任何bug,我们都需要首先尝试去重现它,做二分排除定位,做单元测试刷豆子,搜集证据链,一步步掐头去尾缩小范围,最后解决。这也需要持续迭代。
持续迭代不仅在节奏上保持紧凑,而且把过程渐进展开,我们都知道软件开发的敌人是黑盒子,不能预期的时间和进度,所以持续迭代的过程,我们通过燃尽图,issue管理,bug跟踪,反复把过程dump出来,让进度可视化,促进软件开发的正面化学反应和收敛。
while(rest>e){ step(); }
充分必要
软件开发,涉及到很多需要推理的地方,例如每天的解bug,这里需要逻辑,也就需要充分必要。一个论点,它的论据是否是充分必要的,就是体现逻辑的地方。
其他地方,例如做案例分析,我们训练思辨和分析,我想也应当是基于逻辑的。例如做需求分析,也是应该以是否符合逻辑为核心,如果连自己都说服不了,泛泛而谈的形式化需求分析,多半是需要被重新做的。所以,原则应当是,写完自己读一遍,根据是否充分必要去复审,也许需要补充数据,真实的数据很重要,有数据就可以拿数据说话,一个断言在有数据支撑的情况下,更可能有效。但使用数据要避免单样本统计学家式的武断,同时也要不失管中窥豹的洞察力,这大概需要反复锻炼,反复成功或者失败。
工具
程序员是带工具属性的,工程上,每个小事情都可能有相关的工具可以利用,如果没有,我们就造工具。同样的管理源代码,我们有svn,git,当我们赤手空拳,我们合并别人的代码,可能会先临时拷贝自己新改动的代码到某个临时文件夹S,然后把别人的代码覆盖进来,完了再把S和其diff,再修改。用git,这个过程就是git stash,git pull,git stash pop,所以有时候只要想一下一个操作过程当自己没有工具是是怎么做的,可能工具也大概就是这么做的,只是变成了更有效率的命令。工具也是符合逻辑的。
两个团队A和B。A没做事,B不用工具做事,B比A强;A不用工具做事,B用工具做事,期待的是B比A更有效率的解决问题,否则B并不就比A强;如果两队都做事也都有效率使用工具,则可以开始比内容。所以把那些提高效率的工具都用到习以为常,瓶颈不卡在那些上面,我们就进入比拼真正的最终目标上。反复的训练和使用,可以达到这点。
重试
一个任务,耗时估计的靠谱度跟做过这件事的次数有关,一般来说做过两三次额估计就靠谱点。这也是有经验公式可用。如果它是一个普遍原理,我们可以利用它。从概率上来说,一个事情一次的成功率为a,那么,多次之后的成功率是可计算的,手机打字就不展开了。可以验证,重试可以增加成功率。所以,很多事第一次做,可以预估会有失败和错误,所以失败和犯错时冷静的保存数据,证据,记录,探测的这些点,都可以用来在重试时做可能的规避。不过很多人只尝试了一次,这就回到了经典论述:写100个helloworld不如对一个程序迭代100次。当然,我们要考虑到人是复杂的,喜新厌旧是常态,并不能一概而论。因为,每个人都是独立的个体,选择的自由正是这种平均值。重试要注意两次之间是否收敛,如果不收敛,则重试只会导致队列堆积,甚至引起雪崩,此时要检查更深的问题。
基本和到位
我常常做过一件事以后,发现很多事情并不需要各种奇葩的创新点子之类。做着做着就会看到,做好一件事最需要的并不是创新什么的,而是:概念界定之后的基本功。说概念界定,是因为很多人对自己的职业角色定位不清,就会导致做的事情不能抓住基本点。而一旦界定了角色边界,明确了基本点,那么工作就变成如何完美的把那些基本点做到位上面。例如,保持节奏,从不拖延,持续迭代,细节的完备,以及坚持不越界的做不应该自己做(你得让该做这件事的人去做,有原则对彼此都是一种轻松)。把基本功的细节做到位,就是一种职业素养,和专业主义。我想,这是重要的。我最怕角色不清,要么认为你应该什么都做,要么认为你什么都不要做,角色不清,系统的调度会混乱而没有效率。一个人可以做不同的事情,但最好在角色的语义上区分之。
因此,我也觉得很多事,其实能做到这些的人自己也都可以做好,未必得找别人。这和我经历过到处找控件来组装,到掌握组合控件的基本原理后不认为有魔法控件一样,省去了拿来主义。
提前量和惰性求值
当我们预估,我们会没有充裕的时间做完整的过程,我们可以打时间差。我们说对一个系统做性能优化,不外乎在时间和空间上做优化。如果一个系统或者一个过程要到达预期质量所要消耗的最低时间已经不可再压缩,并且预估到时间整体上将呈现下滑趋势,那么就应该在一开始时间还足够充裕的情况下打提前量,通过一开始的紧凑有序的节奏把大部分脚手架都搭建起来,那么越到后期越会从容和有条不紊,反之则会手忙脚乱。凡事预则立,不预则废。
相反的做法是,对事情做惰性求值,直到我们真正需要一个事情的结果时,才会去做这件事,惰性求值有时候能最大限度减少当前要做的事情。但是,惰性求值相当于一次异步投递任务到队列的过程,队列里等待被做的事情会堆积,当需要在限定时间内求某个事情的结果时,队列可能已经雪崩了。所以有队列的地方就要防雪崩,队列不能过长(根据优先级丢弃),保证你的队列可以在最低粒度时间片内被有序求值。如果你不想你必须要做的事情被丢弃,那么那些事情可以通过打时间差提前做掉,达到超出预期的效果。再说异步任务,异步任务都可能由于各种原因而不会有返回值,所以有异步就要有定时器,做超时监听,一旦超时,做对应的处理。
版本号
无论是10进制,还是10进制,亦或是点分10进制。它们都是版本号。我们的人生就是在年轮的版本之间迭代。认真对待每个版本,麻雀虽小,五脏俱全。每个版本开始,明确本次版本的目标,屏蔽其他,只指目标,当其达成,测试通过,打包,发布,写上:
版本 0.0.3
- 修订了xxx
- 移除了yyy
- 改进了zzz
- 新增了abc
版本和版本之间,贵在持续,节奏均匀。版本的发布日志,就是一个diff。两个集合,A和B的对称差,就是发版的日志。这让我想起,从写程序到现在,在各种场合写过两个数组,区间列表等的diff。很多时候,我们都在做diff,我常常从程序处理的过程得到一些概念,借以类比或者理解生活的事情,然而并不将其泛化,人太容易只看到类比事物之间共性的地方,而其实事物的复杂更在于那些不同的地方。手里有一把锤子,就到处找钉子的事情,永远都有。
拥塞控制
经典的生产者,消费者情景是这样的:
- 过程中会不断产生任务,加入任务队列,这是生产者
- 处理器会定时刷帧,每一帧都会检查当前的窗口,在窗口内的任务就会被执行
- 每个任务执行完都会更新系统的资源状态,这些状态用来更新窗口,超时的任务可能没执行完需要重新投递到队列里。
这样的过程,不断执行的任务,获取或者释放系统资源,而系统资源变化可以反馈到调度器的允许执行窗口,每一帧则从队列里取出窗口内的任务执行。
我们说,这是一个拥塞控制。不做拥塞控制的情况下,在执行的任务可能太少而没有充分利用系统资源,或者在执行的任务太多而把系统资源竞争到卡死,无论怎样,系统的资源利用率最饱和和任务的执行最多,是一个优化目标。所以,一个健壮的系统,有队列的情况下,要做拥塞控制。
拥赛控制的核心法则是:多还少补,在慢启动、拥赛避免、快速恢复3个阶段来回切换。
分段燃尽
从瀑布到敏捷,有的人说我是classical的,严格的瀑布有序经典;有的人说,我是删繁就简的,小步敏捷迭代,蚂蚁搬家。
就像我认为角色需要分开,人员可以合一。无论是学理上还是实践上,过程的不同阶段是存在的,但是具体实施上可能会压缩和合并。
Plan, Build,Test,基本的控制点在于这三者,侧重点各不相同。全局一次,还是反复多次,只是调度策略的不同。
假设过程是一条插值曲线,那么分段插值曲线比全局插值曲线有更好的局部性,学过数值分析的应该都知道全局插值曲线在控制点多了之后,插值多项式的次数高,会有振荡现象,就是由于局部性不好。
Burndown chart的更多相关文章
- Gitlab Burndown Chart
一.说明 通过调用gitlab api直接获取相应project的所有issues,然后对其进行统计以制作燃尽图 二.方法 1.生成 Personal access token Gitlab > ...
- 关于Agile Scrum的笔记
Roles: Scrum Master -- advisor but leader, 替Team消除障碍 Product Owner -- 定sprint的交付内容, 优先级 Team -- 干活的, ...
- Daily Scrum Meeting ——SeventhDay(Beta)12.15
一.Daily Scrum Meeting照片 二.Burndown Chart 想做的太多,冲刺仍在继续 三.项目进展(check-in) 1.完成了登录注册剩下的所有界面 2.更改通知详情和活动详 ...
- Daily Scrum Meeting ——SixthDay(Beta)12.14
一.Daily Scrum Meeting照片 二.Burndown Chart 三.项目进展(check-in) 1.完成注册界面中的学院.年级.身份选择. 2.补充参与者报名活动成功后按钮变为不可 ...
- Daily Scrum Meeting ——FifthDay(Beta)12.13
一.Daily Scrum Meeting照片 二.Burndown Chart 三.项目进展(check-in) 1.制作注册分流的头像 发布者头像 参与者头像 2.完成参与者上传头像的功能:通过本 ...
- Daily Scrum Meeting ——FourthDay(Beta)12.12
一.Daily Scrum Meeting照片 讨论界面优化详情 二.Burndown Chart 项目有条不紊地进行中... 1.新增6个界面修改计划 2.修复两个BUG 三.项目进展(check- ...
- Daily Scrum Meeting ——ThirdDay(Beta)12.11
一.Daily Scrum Meeting照片 二.Burndown Chart 三.项目进展(check-in) 1.欢迎界面的优化,从模糊到清楚 2.新增主界面背景 3.新增注册背景 4.参与者侧 ...
- Daily Scrum Meeting ——SecondDay(Beta)12.10
一.Daily Scrum Meeting照片 二.Burndown Chart 三.项目进展(check-in) 1. 修复两个Alpha版本所遗留的BUG 2. 着手修改参与者与发布者的侧滑框,改 ...
- [转] Agile Software Development 敏捷软件开发
原文作者:kkun 原文地址:http://www.cnblogs.com/kkun/archive/2011/07/06/agile_software_development.html 敏捷是什么 ...
随机推荐
- IIS和tomcat共用80端口
IIS和tomcat共用80端口 很多机器都需要同时使用tomcat和iis两个服务器以部署不同的网站,而解决共用80端口的问题也经常遇到,今天实际操作了一回,以下是具体步骤: 实现tomcat和ii ...
- Blocks的实现
相关结构体与函数 __block_impl 存储block对应类型信息(属于哪个Block大类,以及对应的回调函数指针FuncPtr struct __block_impl { void *isa; ...
- JAVA中的枚举小结
枚举 将一组有限集合创建为一种新的类型,集合里面的值可以作为程序组件使用: 枚举基本特性 以下代码是枚举的简单使用: 使用values方法返回enum实例的数组 使用ordinal方法返回每个enum ...
- 基于分布式、服务化的maven项目文件规划
引言 此文不是纯粹介绍maven概念,而是介绍一个具体的maven项目文件规划 这个规划可能适合于研发比较复杂的业务,这些业务有分布式和服务化的需要. 这个规划能够解决因为分布式和服务化要求而引起的项 ...
- BIEE11G常用函数及使用说明
BIEE常用函数使用手册 1.AGGREGATE AT 此函数根据指定的级别聚合列.使用AGGREGATE AT 可确保始终在关键字AT 之后指定的级别执行度量聚合,而无论WHERE 子句如何. 语法 ...
- CMPP3.0实现物联网卡通讯
当下物联网发展迅猛,物联网卡可以接受短信指令,实现千里之外尽可掌控.本人做过一个这类项目,把相关经验记录下来,分享给需要的人. 物联网卡通讯其实跟电话卡一样,可以使用CMPP协议.不过由于物联网卡位数 ...
- SQL Server 2012实施与管理实战指南(笔记)——Ch6连接的建立和问题排查
6.连接的建立和问题排查 会话的建立分成2个部分: 1.连接,即找到这个实例 2.认证,告诉sql server谁要连接 目录 6.连接的建立和问题排查 6.1协议选择和别名 6.1.1 服务器网络配 ...
- Druid 介绍及配置
1. Druid是什么? Druid是Java语言中最好的数据库连接池.Druid能够提供强大的监控和扩展功能. 2. 在哪里下载druid 正式版本下载:maven中央仓库: http://cent ...
- WIN32 API编程之 透明static
createwindow可以直接创建一个staitc,但这个static是不透明的,如果我们把窗口背景设置为GRAY_BRUSH,则static会很明显的有一个白色背景,一般来说这样肯定很难看. 可以 ...
- cal 命令
cal命令是linux里面查看日历的一个命令,效果如下: [root@localhost ~]# cal 十月 日 一 二 三 四 五 六 我们可以的很形象的从日历上看出今天是哪年,哪年的哪天,周几, ...