Head.First.Object-Oriented.Design.and.Analysis《深入浅出面向对象的分析与设计》读书笔记(四)...

 

  

 

  

 用真实世界检验你的软件-分析

 

 引用

     

      是时候毕业了,时候去真实世界检验自己的软件了。

     

      上个版本的狗门很是成功,卖的很疯狂。但是越是卖的还要,抱怨就会越多。下面就是一个用户的意见。

      “我非常喜欢你的系统,那个语音识别器。但是在我安装了之后,每次邻居家的狗叫的话,门也会自动打开。但是这不是我想要的效果。”

 正文

     

      你的软件有了一个上下文。到目前为止,我们是在一个真空,没有结合软件运行环境的情况下开发软件。换句话说,我们把软件想象为:运行在完美的世界,在我们预期的情况下运行。每个人都很轻松,周围没有很多条狗。

      但是我们的软件终究要运行在真实的世界,而不是一个完美的世界。在真实的世界中,可能会运行错误。周围也会有很多的狗,猫之类的动物。

      使得你的软件在真实世界不被搞糟的关键在于分析:在你把软件放到真实世界之前,找出潜在的问题,并且解决这些问题。

      1、确定(识别)问题

      第一步是找到潜在的问题。我们已经知道,就是邻居家有很多只狗。

      使用遥控器没有问题,因为是人工干预。人是可以识别自己家的狗叫的。但是语音识别器好像就差了点,它一听到狗叫就会打开门。意味着,任何一只狗叫都可以打开门。

      2、设计一个解决方案

      使我们的use case出了问题,在识别器听到狗叫之后没有识别是否是自己家的狗,就打开了门。应该在听到声音之后,需要if判断一下,然后再打开门。

      还需要识别器有存储主人家的狗叫声,才可以在收到狗叫之后进行比较。这时候,你就会发现,需要添加一个use case,就是存储狗叫。用例比较简单,就是:

      1)主人家的狗叫

      2)识别器存储主人家的狗叫声

      用例增加之后,就需要我们修改代码。修改的方式有很多种,先看第一种:

      在DogDoor中添加一个string类型的字段,用来存储叫声;添加一个方法来设置叫声;添加方法来获取叫声。

 

ExpandedBlockStart.gif 代码
<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> --> using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

namespace  BeautyCode.Common.ConApp.Head.First.OO.Design
{
    
public   class  DogDoor
    {
        
private   bool  _open;
        
private   string  _allowBark;
        
public   void  SetAllowBark( string  bark)
        {
            _allowBark 
=  bark;
        }
        
public   string  GetAllowBark()
        {
            
return  _allowBark;
        }
        
public  DogDoor()
        {
            _open 
=   false ;
        }
        
public   void  Open()
        {
            Console.WriteLine(
" the dog door opens " );
            
this ._open  =   true ;

            System.Threading.Thread.Sleep(
5000 );
            Close();
        }
        
public   void  Close()
        {
            Console.WriteLine(
" the dog door closes " );
            
this ._open  =   false ;
        }
        
public   bool  IsOpen()
        {
            
return  _open;
        }
    }
}

 

      另外一种做法就是比较面向对象的程序员写的,新建一个类,定义叫声类

 

ExpandedBlockStart.gif 代码
<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> --> using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

namespace  BeautyCode.Common.ConApp.Head.First.OO.Design
{
    
public   class  Bark
    {
        
private   string  _sound;
        
public  Bark( string  sound)
        {
            _sound 
=  sound;
        }
        
public   string  GetSound()
        {
            
return  _sound;
        }
        
public   override   bool  Equals( object  obj)
        {
            
if  (obj  is  Bark)
            {
                Bark bark 
=  obj  as  Bark;
                
if  (bark._sound.Equals( this ._sound))
                    
return   true ;
                
else
                    
return   false ;
            }
            
return   false ;
        }
    }
}

 

 

 

      DogDoor类中的叫声字段的类型则变成了新建的Bark类

 

ExpandedBlockStart.gif 代码
<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> --> using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

namespace  BeautyCode.Common.ConApp.Head.First.OO.Design
{
     
public   class  DogDoor2
    {
        
private   bool  _open;
        
private  Bark _allowBark;
        
public   void  SetAllowBark(Bark bark)
        {
            _allowBark 
=  bark;
        }
        
public  Bark GetAllowBark()
        {
            
return  _allowBark;
        }
        
public  DogDoor2()
        {
            _open 
=   false ;
        }
        
public   void  Open()
        {
            Console.WriteLine(
" the dog door opens " );
            
this ._open  =   true ;

            System.Threading.Thread.Sleep(
5000 );
            Close();
        }
        
public   void  Close()
        {
            Console.WriteLine(
" the dog door closes " );
            
this ._open  =   false ;
        }
        
public   bool  IsOpen()
        {
            
return  _open;
        }
    }
}

 

      相应的识别器类中的代码就应该修改为

      识别器1

ExpandedBlockStart.gif 代码
<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> -->    public   void  Recognize( string  bark)
        {
            Console.WriteLine(
" Bark Recognizer: heard a  " + bark );
            
if  (_door.GetAllowBark().Equals(bark))

                _door.Open();
            
else
                Console.WriteLine(
" this dog is not allow " );
        }

 

 

 

      识别器2

 

ExpandedBlockStart.gif 代码
<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> -->   public   void  Recognize(Bark  bark)
        {
            Console.WriteLine(
" Bark Recognizer: heard a  "   +  bark);
            
if  (_door2.GetAllowBark().Equals(bark))

                _door.Open();
            
else
                Console.WriteLine(
" this dog is not allow " );
        }

 

 

      识别器2明显好于识别器1,因为在2中将声音比较的任务委托给了bark类来处理,识别器本身不处理,只是根据处理的结果来做出决定。这样就松散了耦合,解耦了识别器类和叫声类。因为其他叫声也很容可以添加进来,否则每一种叫声都必须配备专用的识别器了。

      在分析的时候,需要注意需求或者是用例中的名词和动词。名称经常会需要转换成类,或者是类的一个属性。动词则经常会是一个方法。

      继续上面的分析。

      狗一般不是叫一声,有可能要叫很多声,只要一个声音匹配成功,就应该打开门。识别器需要存储多个狗叫声。

     

ExpandedBlockStart.gif 代码
<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> --> using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

namespace  BeautyCode.Common.ConApp.Head.First.OO.Design
{
    
public   class  DogDoor3
    {
        
private   bool  _open;
        
private  List < Bark >  _allowBark;
        
public   void  SetAllowBark(Bark bark)
        {
            _allowBark.Add( bark);
        }
        
public  List < Bark >  GetAllowBark()
        {
            
return  _allowBark;
        }
        
public  DogDoor3()
        {
            _open 
=   false ;
        }
        
public   void  Open()
        {
            Console.WriteLine(
" the dog door opens " );
            
this ._open  =   true ;

            System.Threading.Thread.Sleep(
5000 );
            Close();
        }
        
public   void  Close()
        {
            Console.WriteLine(
" the dog door closes " );
            
this ._open  =   false ;
        }
        
public   bool  IsOpen()
        {
            
return  _open;
        }
    }
}

 

       这时候识别器就需要修改一下了

 

ExpandedBlockStart.gif 代码
<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> --> using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

namespace  BeautyCode.Common.ConApp.Head.First.OO.Design
{
    
public   class  BarkRecognizer
    {

        
private  DogDoor3 _door3;
        
public  BarkRecognizer(DogDoor3 door)
        {
            _door3 
=  door;
        }
        

        
public   void  Recognize3(Bark bark)
        {
            Console.WriteLine(
" Bark Recognizer: heard a  "   +  bark);
            
foreach  (Bark b  in  _door3.GetAllowBark())
            {
                
if  (b.Equals(bark))
                {
                    _door.Open();
                    
return ;
                }

            }

            Console.WriteLine(
" this dog is not allow " );
        }
    }
}

 

     

     

  结论
      要注意requirements和use case中的名词,它们通常就是一个类或者是类中的一个属性;其中的动词通常会是一个类的方法。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值