KiddLee

态度决定一切!我博客,留住生活中的精彩
数据加载中……
面向对象分析设计学习与探索(三):收集需求(Gathering Requirement)
        相信每一个人都希望让客户满意。而且现在已经知道写一个好的软件的第一步就是确定软件所作的是客户想让它做的。但是你如何确定什么是客户想要的?如何确定客户知道他们真正想要什么?

        的确!在做项目项目的时候,我们常常被不确定的需求变化所困扰,当然如果说在开发时期要求需求一点不变化是不可能的,但是有些需求变化是致命的,会导致工作量成倍的上升,甚至是项目的失败。现在有个场景,我们看看如何做才能很好的挖掘用户的想法(这是编写成功软件的第一步)。

        情景:有一个用户要给自己的小狗修一个Dog Door,以至于他们不用再睡觉后听到狗叫,然后起床给它开门。当然,这个Dog Door 并不是简单的一个塑料片,他们希望通过一个遥控器按钮使这个Dog Door打开或者关上。

                

        从需求上看,好像很简单。我们只需要一个Dog Door和一个可以控制们的遥控器,让我们从Dog Door开始,首先要有一个DogDoor的类型,当然这个类型中有一些功能,如:开门、关门。
    public class DogDoor
    
{
        
private Boolean _isOpen;

        
public Boolean IsOpen
        
{
            
get return _isOpen; }
        }


        
public DogDoor()
        
{
            _isOpen 
= false;
        }


        
public void Open()
        
{
            _isOpen 
= true;
            Console.WriteLine(
"The dog door is opened.");
        }


        
public void Close()
        
{
            _isOpen 
= false;
            Console.WriteLine(
"The dog door is closed");
        }

    }


        然后在完成遥控器的代码:
    public class Remote
    
{
        
private DogDoor _door;

        
public Remote(DogDoor door)
        
{
            
this._door = door;
        }


        
public void pressButton()
        
{
            
if (_door.IsOpen)
            
{
                _door.Close();
            }

            
else
            
{
                _door.Open();
            }

        }

    }



        最后我们来测试一下: 
    class Test
    
{
        
static void Main(string[] args)
        
{
            DogDoor door 
= new DogDoor();
            Remote remote 
= new Remote(door);
            Console.WriteLine(
"The dog is barking, he wanna ");
            remote.pressButton();
            Console.WriteLine(
"The dog is outside and ");
            remote.pressButton();
            Console.WriteLine(
"The dog is barking, he wanna inside");
            remote.pressButton();
            Console.WriteLine(
"The dog is inside");
            remote.pressButton();
            Console.Read();
        }

    }


                 

        好了,现在可以交给客户使用了。可是不久,客户就发现了问题。

                

 

客户忘记了用遥控器把门关上,结果很多小动物就进来了。看来这个们没有按照客户希望的工作。很显然,这个简单的软件并不符合客户的要求(当然这种意见他们原来并没有提出来)。现在我们回过头来重新审查我们对这个需求的理解,已确定我们的软件是客户想要的。现在一个问题产生了:什么是需求?
    是系统为了工作正常而必须做的工作细节


                

        当需要收集需求时,我们最应该做的是:让客户说话。注意什么是系统需要做的,然后列出什么是系统将要做的。
        首先来听听他们说些什么

                

         根据他们所说的现在建立一个需求清单

    1、 Dog door打开的时候至少12英寸高
    2、 按遥控器上的按钮,当门关上的时候,门打开;否则,门关上
    3、 一旦门打开了,在一定的时间后如果没有关闭的话,他将自动关闭

                

    这只是一个简单的需求清单,我们需要将他细化,以准确的指出当小狗要出去时都发生了什么!

            

        细化之后觉得这个清单中的第六步还是有些问题。在Fido(那只要出去的小狗)近来之前,门一直是开着的。这样的话,它近来之前就不必再叫了。现在我们在来修改一下。

                
 

书上教给我们一个不错的办法,对于有问题的步骤,或者是描述不足的部分使用小号修改,不必把后面删掉重新排号。


         现在这个清单已经很精确了,实际上,用了这就是根据需求清单写出的用例(use case)
        用例描述了你的系统为完成用户需求中的一个细节所需要做的事情。

                

        那么如何写好一个用例呢?
        通常一个用例由三部分组成:Clear Value,Start and Stop,External Initiator
        1、 Clear Value:很抱歉的是我不太明确应该怎么翻译,我觉得是一个明确的目标或者价值。每一个用例都要有一个Clear Value。如果说用例没能帮助客户达到他们的目标,那么用例就没有用了
        2、 Start and Stop:开始和结束。每一个用例都要定义一个起始点和一个结束点。一个进程开始后,在一个条件下,进程结束。在上面的用例中,Fido开始叫,这个进程就开始了。当Fido进门后,门自动关上,这个进程就结束了。
        3、 External Initialtor:我管它叫外部触发者。它必须是系统之外的人或物。在上面的用例中就是那个要出去的小狗。
                

        我们有了需求清单和用例,现在我们要做的是回到需求,确定覆盖了系统必须做的所有事情。(将对应的需求填入用例,N/A是not applicable)

                

        这个方法不错,可以需求清单和用例很好的对应,在我们编写相应程序时不会因为不明确而漏掉什么。
        现在有了需求和用例,我们可以开始编码了。首先要修改Remote类型,使其在打开门一段时间之后自动把门关上,代码如下:
    public class Remote
    
{
        
private DogDoor _door;

        Timer time;
        TimerCallback callback;

        
public Remote(DogDoor door)
        
{
            
this._door = door;
        }


        
public void pressButton()
        
{
            
if (_door.IsOpen)
            
{
                _door.Close();
            }

            
else
            
{
                _door.Open();
                callback 
= new TimerCallback(_door.Close);
                time 
= new Timer(callback,_door,1000,0);
            }

        }

   }


        注意,这个地方的变化造成了一些修改,当然程序有很多种写法,这里就不再探讨这个问题了,造成修改的地方是:DogDoor类型中加入一个Close的重载方法:
     public void Close(object source)
     {
            Close();
     }

        最后我们需要修改原来的测试代码,去掉开门后按按钮的动作,让门自动关闭,在测试代码中用线程休眠来表示Fido已经出去,测试代码如下:

        static void Main(string[] args)
        
{
            DogDoor door 
= new DogDoor();
            Remote remote 
= new Remote(door);
            Console.WriteLine(
"The dog is barking, he wanna ");
            remote.pressButton();
            Console.WriteLine(
"The dog is outside and ");
            Thread.Sleep(
10000);
            
//remote.pressButton();
            Console.WriteLine("The dog is barking, he wanna inside");
            remote.pressButton();
            Console.WriteLine(
"The dog is inside");
            
//remote.pressButton();
            Console.Read();
         }


        测试结果还可以:

                

        现在客户感觉满意了,我们也初战告捷了。


                

0
0
(请您对文章做出评价)
« 上一篇:面向对象分析设计学习与探索(二):好的应用程序设计(Well-designed apps rock)
» 下一篇:面向对象分析设计学习与探索(四):需求变化(Requirements Change)

posted on 2007-08-27 13:59 KiddLee 阅读(2576) 评论(25)  编辑 收藏 网摘 所属分类: OOA&D学习与探索系列

评论

#1楼 2007-08-27 14:44 咳[未注册用户]

沙发一下,回来慢慢研究
    回复  引用    

#2楼 2007-08-27 15:25 idzi[未注册用户]

哈哈 不错……不过有一个问题是关于线程的……如果Fido出去正好在关门之时进来不是正好夹到它吗?个人感觉这里用线程还是有些问题的
    回复  引用    

#3楼[楼主] 2007-08-27 15:42 KiddLee      

@idzi
恩呢,你说得很对,对于这个故事的需求,我们应该再加上对于一些异常的处理,这个门应该像地铁的门一样(我就被夹住过)。不过这些程序只是为了模拟说明一个问题。
当然,在这本书后面的章节讲道了程序是要在现实世界中使用,到时候会写一些这方面的东西
谢谢关注
    回复  引用  查看    

#4楼 2007-08-27 15:55 sekihin      

再次支持一下
    回复  引用  查看    

#5楼 2007-08-27 18:49 Allen Zhang

垃圾文章
    回复  引用    

#6楼 2007-08-27 19:47 Kevin Cheng      

呵呵,代码我就没有看了,但这篇文章对于用例的撰写是非常贴切实际的。
这种文章风格好像dummy系列的书呵呵。
    回复  引用  查看    

#7楼[楼主] 2007-08-27 20:54 KiddLee      

谢谢大家的关注
    回复  引用  查看    

#8楼[楼主] 2007-08-27 21:07 KiddLee      

@Allen Zhang
首先感谢你花时间看我这篇"垃圾文章"
有什么不足希望提出来,但不希望这样一个简单的词语把一切都概括了:)
    回复  引用  查看    

#9楼 2007-08-27 21:35 金色海洋(jyk)      

我还是习惯地二章那样的例子,和程序很接近,这个例子就比较抽象了。
    回复  引用  查看    

#10楼[楼主] 2007-08-28 07:54 KiddLee      

@金色海洋(jyk)
第二章是一个概述,包含了整个OOA&D的过程.而从这章开始.就要把这个过程将细.这章的重点在于第二章中讲的"Make sure your software does what customer wants it to do",主要集中在需求收集上,如何收集需求.

谢谢你的建议,后面的文章中我会注意我的方式:)

谢谢关注
    回复  引用  查看    

#11楼 2007-08-28 07:56 sekihin      

@Allen Zhang
其实LZ很辛苦的,又截图,又写代码。
为什么还有人冷言冷语,认为别人写的不好,你可以写出更好的把别人比下去。
讥讽,并不能促进彼此的进步。
    回复  引用  查看    

#12楼 2007-08-28 08:45 老毕[未注册用户]

楼主辛苦啊
截图+代码+翻译,的确不容易
希望楼主坚持
    回复  引用    

#13楼 2007-08-28 09:13 阿风dd      

写的不错,请继续,会有更多的人关注你的!
    回复  引用  查看    

#14楼 2007-08-28 09:23 shen126[未注册用户]

请问楼主的图片是从那里借来的啊?
    回复  引用    

#15楼[楼主] 2007-08-28 10:03 KiddLee      

谢谢大家支持,我会继续努力的
@shen126
这本书在网上有电子版,图从上面截下来的
    回复  引用  查看    

#16楼 2007-08-28 10:41 shen126[未注册用户]

能告诉我书名吗,谢谢!
    回复  引用    

#17楼[楼主] 2007-08-28 11:17 KiddLee      

@shen126
Head First Object-Oriented Design and Analysis
    回复  引用  查看    

#18楼 2007-08-28 11:22 shen126[未注册用户]

Thanks!
    回复  引用    

#19楼 2007-08-28 12:28 源码工作室      

继续,我会一直看完你的这个系列
    回复  引用  查看    

#20楼 2007-08-28 12:53 金色海洋(jyk)      

获取客户的需求!
我就遇到了一个具体的问题。客户不是一个人提需求,而是七八个人各提个的,但是每一个人体的需求又不是独立的,都是相互关联的。我是把每个需求都实现了,但是放在一起就不好玩了,关连到一起就对应不上了,郁闷。
    回复  引用  查看    

#21楼 2007-08-29 11:07 mirs      

关注.....
    回复  引用  查看    

#22楼 2007-08-29 15:11 风焰庄主      

不错的Blog
    回复  引用  查看    

#23楼 2007-08-30 09:08 球球      

英文的影印版虽然传闻印刷质量比较差,但是没办法.........总不能去弄原版书,所以还是准备下订单-_-!
    回复  引用  查看    

#24楼 2007-09-06 17:08 小陈步旅      

关注中,对于别人写的文章,不管是否对你有帮助,不管对否,起码那是他想用他的热心来帮助别人,并无恶意,所以不要冷言冷语
    回复  引用  查看    

#25楼 2007-10-29 11:02 侯昆[未注册用户]

文章相当不错,一个形象化的例子说明了软件工程一章的内容,同时也在代码中诠释了对象,方法,响应,和程序的后期修改过程, 这是一个渗透智慧例子.仁者见仁,大家尽可发表意见,好与不好还是说明一下,不要发没素质的话,

另用:
怎么正确显示rft格式(如下) 的中文

{\rtf1\ansi\ansicpg936\deff0{\fonttbl{\f0\fnil\fcharset134 \´cb\´ce\´cc\´e5;}{\f1\froman\fcharset2 Symbol;}}
{\colortbl ;\red0\green0\blue0;}
{\*\generatorMsftedit .41.15.1507;}\viewkind4\uc1\pard\cf1\lang2052\b\f0\fs32\´c4\´d0\´a3\´ac45\´cb\´ea\´a3\´ac\´b8\´a1\´d6\´d7\´a1\´a2\´c4\´f2\´c9\´d93\´d6\´dc\´a3\´ac\´bd\´fc5\´cc\´ec\´c0\´b4\´b6\´f1\´d0\´c4\´a1\´a2\´c5\´bb\´cd\´c2\´a1\´a2\´c6\´f8\´bc\´b1\´a1\´a3\´d1\´aa\´c7\´e5\´bc\´a1\´f4\´fb450\f1 m\f0 mol/L\´a3\´ac\´c4\´f2\´cb\´d8\´b5\´aa30mmol/L\´a1\´a3\´c7\´eb\´d6\´b8\´b3\´f6\´d0\´c4\´c7\´b0\´c7\´f8\´c4\´da\´cc\´fd\´b5\´bd\´b5\´c4\´d0\´c4\´d2\´f4\´d0\´d4\´d6\´ca\´a3\´bf\par\cf0\fs24\par}

我用了如下代码
loginQuery = "Select * from Item where ItemID= ? ";
con = cbtConnect.getconn();
loginStmt = con.prepareStatement(loginQuery);
loginStmt.setString(1,String.valueOf(itemId));
ResultSet rs = loginStmt.executeQuery();
if(rs.next()){
questionarr[0]=rs.getString("Question");
}
。。。。
JEditorPane jEditorPane1 = new JEditorPane();
RTFEditorKit kit = new javax.swing.text.rtf.RTFEditorKit();
jEditorPane1.setEditorKit(kit);
jEditorPane1.setContentType("txt/rtf ");
jEditorPane1.setText(questionarr[0]);

但显示的中文是如下错误码?

ÄУ¬45Ë꣬¸¡Öס¢ÄòÉÙ3ÖÜ£¬½ü5ÌìÀ´¶ñÐÄ¡¢Å»Í¡¢Æø¼±¡£ÑªÇ弡ôû450mmol/L£¬ÄòËØµª30mmol/L¡£ÇëÖ¸³öÐÄÇ°ÇøÄÚÌýµ½µÄÐÄÒôÐÔÖÊ£¿

正确应是:
男,45岁,浮肿、尿少3周,近5天来恶心、呕吐、气急。血清肌酐450mol/L,尿素氮30mmol/L。请指出心前区内听到的心音性质?
高手能help吗??
    回复  引用