书店会员销售系统(一)

书店会员销售系统(一)
                     ―― OO Refactoring and Design Pattern
本节目的:
   
1.         有一场景引入一个问题,学习测试驱动的编程方法,实现基本功能。
书店中的一幕:
      营业员:“请问你有会员卡吗?”
       顾客: “有的。”
       顾客掏出钱包,拿出会员卡递给营业员,营业员输入会员卡号后开始计书的金额,期间有一本书的条形码扫描不出来,营业员手动输入。
       营业员:“一共是 126 元。”
       顾客递给营业员 130 元。
       营业员:“收你 130 元,找你 3 元。”
    顾客: “你算错了吧?”
    营业员:“噢,不好意思,再给你1元。”(肯定在想哪件漂亮的衣服)
       顾客:   “我想问一下,我会员卡上的积分是多少了?”
       营业员: “你总共消费累计 2700 元,积分为 250 点。”
      顾客:     “那我现在享受几折优惠了?”
       营业员: “你现在可以享受 8.5 折优惠。”
       顾客:       “噢,我知道了,谢谢你。”
 
    顾客提着书离开收银台。
         我想这一场景大家可能都亲身经历过,当然不一定在书店。这就涉及到小店会员销售系统,如果要你编写这么一个系统,你会如何做呢?
       我想你第一个想到的可能是数据库。是的,会员销售系统会记录很多的信息,肯定是要用到数据库的,但后面的叙述我会尽可能地去避免,为了简单而已。
       我们先来分析一下问题。在上面的场景中涉及到一些对象:顾客、营业员、会员卡、书。顾客有顾客的信息,营业员有营业员的信息,会员卡记录了顾客的 ID 号,书的价格,在这里我先忽略书的价格,而是计算一次消费的金额,饭要一口一口地吃,还有营业员我们也可以先不涉及。

    我们要实现的功能是:根据不同的会员,对其消费的金额进行打折,并累计消费点数,第一版UML图如下:

     
     
XP
的原则是先写测试用例,然后使测试用例通过调试,得出正确的结果,我在这里也就按部就班的这么做。

因为篇幅的原因,所有出错处理都不考虑。
       编译一下,很多错误,主要是CCalculateCMember三个类没有创建,那接下来的工作当然是创建它们。
 
  会员类:

int  main( int  argc,  char *  argv[])
{
       
char szMemberID[MAX_PATH];
       strcpy(szMemberID,
"00000001");
       
float fConsumeSum = 120.0;
       
int      nPoint  = 0;

        CCalculate      
*pCalc = new CCalculate();
       CMember              
*pMember = new CMember(szMemberID,1000.0,75);
       nPoint 
= pMember->GetPoint();
       nPoint 
+= pCalc->CalculatePoint(fConsumeSum);

        fConsumeSum 
= pCalc->CalcMoney(fConsumeSum,pMember);

        pMember
->SetPoint(nPoint);
        assert(nPoint 
== 87);
        assert(fConsumeSum 
== 120.0);

        printf(
"Point = %d/n",nPoint);
        printf(
"ConsumeSum = %f/n",fConsumeSum);
        delete pCalc;
        delete pMember;
        
return 0;
}



      

class  CMember  
{
public:
    CMember(
char *pszID,float fSum,int nPoint);
    
~CMember();
    
int GetPoint();
    
void SetPoint(int nPoint);
    
float GetRebate();
private:
    
char    m_szID[MAX_PATH];
    
float   m_fSum;
    
int     m_nPoint;
}
;
 
CMember::CMember(
char   * pszID, float  fSum, int  nPoint)
{
    
if(pszID)
        strcpy(m_szID,pszID);
    m_fSum 
= fSum;
    m_nPoint 
= nPoint;
}

 
int  CMember::GetPoint()
{
    
return m_nPoint;
}

 
void  CMember::SetPoint( int  nPoint)
{
    m_nPoint 
= nPoint;
}

 
float  CMember::GetRebate()
{
    
if(m_nPoint<=100)
        
return 10;
    
else if(m_nPoint>100 && m_nPoint <200)
        
return 9.5;
    
else if(m_nPoint>=200 && m_nPoint <400)
        
return 9;
    
else if(m_nPoint>=400 && m_nPoint <600)
        
return 8.5;
    
else
        
return 8.0;
}



计算类:

然后在编译程序,在测试用例中,我们希望的结果是:
    Point = 87
    ConsumeSum = 120.000000
    可运行的结果却是出现assert异常,仔细一查,输出结果为:
    Point = 87
    ConsumeSum = 1200.000000

class  CCalculate  
{
public:
    CCalculate();
    
~CCalculate();
    
int CalculatePoint(float fSum);
    
float CalcMoney(float fSum,CMember  *pMember);
}
;

int  CCalculate::CalculatePoint( float  fSum)
{
    
int nPoint = (int)(fSum/10);
    
return nPoint;
}

 
float  CCalculate::CalcMoney( float  fSum,CMember   * pMember)
{
    
float fRebateSum = 0.0;
    fRebateSum 
= fSum * pMember->GetRebate();
    
return fRebateSum;
}


   

    原来在折扣上没有除10,修改代码:

测试通过,一个基本功能的程序就编写成功了。当然一组测试用例远远是不够的,我这里也就不多写了。人还是人,错误是很难避免的,通过测试用例,能排除一大部分的问题,也为以后的程序改进提供的保障。
    也许会有人说,这样的设计太烂了。可如果需求不改变的话,至此就已经足够了。这不是本节的用意。

float  CCalculate::CalcMoney( float  fSum,CMember   * pMember)
{
    
float fRebateSum = 0.0;
    fRebateSum 
= fSum * pMember->GetRebate()/10;
    
return fRebateSum;
}


   

http://goodcandle.cnblogs.com/archive/2006/03/09/346471.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值