实践篇(4)—需求看板解析

    经过QPG团队的努力,我们马上将推出共享软件――需求看板V1.0

   下面是系统的目前的主界面:
face.jpg


 
  我这里简单介绍一下这个共享软件的特点和核心代码思路:

一)    产品特点

a)       图形化界面,操作十分简单,不需要帮助手册,一般只用鼠标的两个键就可以操作;

b)      目标管理而非任务管理(今后在工作包看板里实现)

c)      客观、真实反映项目的进度;

d)      区分不同需求的价值点,自动汇总项目的总价值点,辅助项目经理防止需求蔓延。

e)       目前是C/S架构,今后将推出B/S

 

二)    设计思路点评

2.1) 基本概念

  我们经过对常见项目的总结,建议通常用三层来表达系统的需求:

 

需求类型

节点特征

备注

项目需求

没有父节点

项目根节点

需求

有父有子

子系统、模块节点

规格

有父无子

对应FDD中的特征,是可以验证和测试的叶子节点

  状态――需求的推进状况;

  完成率――0~100%

    价值点――衡量一个规格或者价值的贡献度

              对于规格,可以设定(1~10)

              对于需求,系统将自动汇总

2.2) 核心逻辑

  对于一个规格,我们通过状态的变化来映射其完成百分比,下表是一种可能的设定方法:

顺序号

状态

累计完成率(%)

1

纳入开发

0%

2

需求评审

20%

3

设计评审

30%

4

单元测试通过

60%

5

集成测试通过

80%

6

验收测试通过

100%

 对于包含规格或者子需求的需求,则是查看其所有规格的有效完成率来计算自身的完成率的。

 

2.3) 核心逻辑代码实现

a) 算法接口定义

 1 ExpandedBlockStart.gif ContractedBlock.gif namespace  KanBan.Data  dot.gif {
 2InBlock.gif    
 3InBlock.gifusing System;
 4InBlock.gifusing System.Collections;
 5InBlock.gifusing System.Xml.Serialization;
 6InBlock.gif
 7ExpandedSubBlockStart.gifContractedSubBlock.gifpublic enum RequimentState : int dot.gif{New=0,Going=1,Finished=2 }
 8InBlock.gif
 9ExpandedSubBlockStart.gifContractedSubBlock.gifpublic interface IRequimentRule dot.gif{
10InBlock.gif    int getFinishPercent(RequimentState rs);
11ExpandedSubBlockEnd.gif}

12ExpandedBlockEnd.gif}

13 None.gif


b)一个缺省的实现:

 1 None.gif namespace  KanBan.BizRule
 2 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 3InBlock.gif    using System;
 4InBlock.gif    using System.Collections;
 5InBlock.gif    using KanBan.Data;
 6InBlock.gif    
 7ExpandedSubBlockStart.gifContractedSubBlock.gif    public class DefaultRule:IRequimentRuledot.gif{
 8InBlock.gif        private System.Collections.IDictionary _map;
 9InBlock.gif        public DefaultRule()
10ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
11InBlock.gif            _map = new Hashtable();
12InBlock.gif            _map.Add(RequimentState.New, 0);
13InBlock.gif            _map.Add(RequimentState.Going, 50);
14InBlock.gif            _map.Add(RequimentState.Finished, 100);
15ExpandedSubBlockEnd.gif      }

16ContractedSubBlock.gifExpandedSubBlockStart.gif        IRequimentRule#region IRequimentRule
17InBlock.gif        public int getFinishPercent(KanBan.Data.RequimentState rs)
18ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
19InBlock.gif            return (int)_map[rs];
20ExpandedSubBlockEnd.gif        }

21ExpandedSubBlockEnd.gif        #endregion

22ExpandedSubBlockEnd.gif    }

23ExpandedBlockEnd.gif}

24 None.gif

c) 需求服务的关键部分代码:

 

ExpandedBlockStart.gif ContractedBlock.gif public   virtual  IList getSpecifications(Requiment req)  dot.gif {
InBlock.gif    IList tops 
= new ArrayList();
InBlock.gif    
if(req.NextLevelRequiments==null||req.NextLevelRequiments.Count == 0return tops;
InBlock.gif    IList items
=req.NextLevelRequiments;
InBlock.gif            
ExpandedSubBlockStart.gifContractedSubBlock.gif    
foreach(Requiment sr in items) dot.gif{
InBlock.gif      
if (sr.IsSpecification)
InBlock.gif            tops.Add(sr);
ExpandedSubBlockStart.gifContractedSubBlock.gif        
else dot.gif{
InBlock.gif            IList temp 
= getSpecifications(sr);
InBlock.gif            
foreach (object f in temp) tops.Add(f);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif    
return tops;
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   virtual   int  getFinishPercent(Requiment req)  dot.gif {
InBlock.gif    
if(req.NextLevelRequiments==null||req.NextLevelRequiments.Count == 0
InBlock.gif        
return _logic.getFinishPercent(req.State);
InBlock.gif    IList tops 
= getSpecifications(req);
InBlock.gif    
int sum = 0;
ExpandedSubBlockStart.gifContractedSubBlock.gif    
foreach (Requiment part in tops) dot.gif{
InBlock.gif     
int k = (int)getFinishPercent(part);
InBlock.gif     sum 
+= k;
InBlock.gif     Console.WriteLine(
"特征[{0}]完成:{1}%", part.Name, k);
ExpandedSubBlockEnd.gif}

InBlock.gif    Console.WriteLine(
"{0} Finish:{1}%", req.Name, sum / tops.Count);
InBlock.gif    
return  (int)(sum / tops.Count + 0.499M);
ExpandedBlockEnd.gif}

None.gif

d) 集成起来!

    如果客户有特殊的需求,那我们也可以很简单的开发一个逻辑dll,在配置文件中配置一下就可以了,类似下面这样:

None.gif <? xml version="1.0" encoding="utf-8"  ?>  
None.gif
< configuration >  
None.gif   
< components >
None.gif
None.gif      
< component  id ="myrule"  service ="KanBan.Data.IRequimentRule, KanBan.Data"  
None.gif            type
="KanBan.BizRule.MyRule, KanBan.BizRule2" >
None.gif      
</ component >
None.gif
None.gif      
< component  id ="reqdao"  type ="KanBan.DAS.RequimentDAO, DAS" >
None.gif      
</ component >
None.gif
None.gif      
< component  id ="rs"  type ="KanBan.BizRule.RequimentService, KanBan.BizRule" >
None.gif         
< parameters >
None.gif                
< logic > ${myrule } </ logic >
None.gif         
</ parameters >
None.gif      
</ component >
None.gif      
< component  id ="rf"  type ="KanBan.Facade.RequimentFacade, KanBan.Facade" >
None.gif      
</ component >
None.gif  
</ components >
None.gif
</ configuration >
None.gif
None.gif

 

2.3) 数据处理

  我们不会重复去发明轮子,开始我们用了castle ActiveRecord组件,发现在有递归的情况bug不少,后来就转回Nhibernate, 下面是需求的映射配置文件:

 

None.gif <? xml version="1.0" encoding="utf-8"  ?>
None.gif
< hibernate-mapping  xmlns ="urn:nhibernate-mapping-2.0" >
None.gif    
< class  name ="KanBan.Data.Requiment, KanBan.Data"  table ="Requiments" >
None.gif        
< id  name ="ID"  column ="ID"  unsaved-value ="0" >
None.gif            
< generator  class ="native"   />
None.gif        
</ id >
None.gif        
< property  name ="Name"  not-null ="true"  length ="100"   />
None.gif        
< property  name ="Code"  not-null ="true"  unique ="true"  length ="20" />
None.gif    
< property  name ="Catalog"  not-null ="false"  length ="40"   />
None.gif    
< property  name ="Priority"  not-null ="false"  length ="20"   />
None.gif    
< property  name ="Important"  not-null ="false"  length ="20"   />
None.gif    
< property  name ="Description"  not-null ="false"  length ="250"   />
None.gif    
< property  name ="ValuePoint"  not-null ="true"   />
None.gif    
< property  name ="State"  not-null ="true"   />
None.gif        
None.gif        
< many-to-one  name ="Parent"  column ="p_ID"   />         
None.gif        
< bag  name ="NextLevelRequiments"  inverse ="false"  lazy ="true"  cascade ="all"  order-by ="Code"   >
None.gif            
< key  column ="p_ID"   />
None.gif            
< one-to-many  class ="KanBan.Data.Requiment, KanBan.Data"   />
None.gif        
</ bag >
None.gif    
</ class >
None.gif
</ hibernate-mapping >
None.gif
None.gif

 

Alex 2005.12

转载于:https://www.cnblogs.com/QPG2006/archive/2005/12/27/kanban.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值