面向对象编程,我们口口声声喊了快十年,但为什么程序员还不使用面向对象编程?是知识、经验不够?非也。笔者想用一句牢骚话作为开篇:拆任务都拆成面向过程的了,还怎么叫程序员去面向对象开发。
让我们改进一点点:
- 留两个小时给程序员理解需求。
- 采用面向对象的方式去拆任务。
让我们思考一下下:
- 面向过程在一定程度上比面向对象有性能上的优势,那么,两者如何均衡?使我们既不为了面向对象而忽视性能,也不为了追求性能而忽视面向对象。
何为留两个小时给程序员理解需求?
在具体工作中,团队由于受到各种外围因素影响,常会发生以下两种情况
- FS Review和Plan meeting相隔较久,导致程序员对需求已经模糊。
- 面向过程的拆分方式,导致程序员只关心自己做的需求。
模糊的,片面的需求,阻碍了我们开展面向对象编程。所以,我们需要留两个小时给程序员理解需求。
如何采用面向对象的方式去拆任务?
银行借贷系统,用户输入50万,20年还清,点击借款按钮后,屏幕显示用户在240期内每期要还多少钱。
面向过程拆分方式:
1.前台-画界面
2.后台-新增用户
3.后台-计算利息
4.后台-计算总额(本金+利息)
5.后台-计算每期还款金额
6.后台-打印
我们会在DAO层编写四个函数AddBorrower,CalcRate,CalcTotal,CalcAmount。Model层新建一个对象叫Loan(反模式-面条代码症状:对象常常被按照处理过程命名)
。Service层编写两个函数Loan,Print,供aspx页面去调用。
面向对象拆分方式:
1.前台-画界面
2.借款者对象
3.银行对象
4.实现借款者对象行为-新增用户
5.实现银行对象行为-计算利息
6.实现银行对象行为-计算总额
7.实现银行对象行为-计算每期还款金额
8.实现银行对象行为-打印
我们会在Model层新建两个对象Borrower,Bank,并去实现它们的属性和行为。DAO层仅仅作为数据提供层。Service层依旧编写两个函数Loan,Print,供aspx页面去调用
为何采用面向对象的方式去拆任务?
继续上例,我们允许各个银行的贷款利率在央行基准利率的指导下上下浮动5%,比如央行基准利率为15%,中国银行为14%,建设银行为17%,民生银行依旧采用央行基准利率。
面向过程拆分方式:
1.前台-画界面,增加下拉框,选择中国银行或建设银行或民生银行
2.后台-修改计算利息
代码如下:修改计算利息函数
public
class
Bank
{
//一些属性
//一些方法
public
decimal
CalcRate()
{
if(中国银行)
{
//用14%计算
}
else
if(建设银行)
{
//用17%计算
}
else
{
//用央行基准利率15%计算
}
}
}
大胆试想一下,随着sprint的不断深入,需求新增或变更,或修复Bug,该函数会被多人多次修改,由于编程风格、习惯的不同,很容易出现无法解释其合理性的变量和代码碎片(反模式-岩浆流),最后,软件迅速达到回报最小点,维护现有代码集的成本比从头开始开发新方案的成本更高。
面向对象拆分方式:
1.前台-画界面,增加下拉框,选择中国银行或建设银行或民生银行
2.新增两个对象,中国银行,建设银行
3.实现中国银行行为-计算利息
4.实现建设银行行为-计算利息
重构
//银行基类
public
class
Bank
{
//一些属性
//一些方法
public
decimal
CalcRate()
{
//用央行基准利率15%计算
}
}
//中国银行
public
class
BankOfChina : Bank
{
public
override
decimal
CalcRate()
{
//用14%计算
}
}
//建设银行
public
class
CCB : Bank
{
public
override
decimal
CalcRate()
{
//用17%计算
}
}
简要描述下好处吧
- 运用设计模式去架构程序
- 避免了程序员采用惰性模式开发
- 使得函数对扩展开放,对修改关闭
最后,笔者想说
学习,架构,重构。三者环环相扣,互不分离。不去学习,就没有足够的知识去架构和重构,代码永远只停留在面向过程的水平上。而架构和重构又互为因果,有了架构,才能重构;有了重构,为了更好的架构。
最后,有的人想问,我们项目原先的代码已经是面向过程,如何在其基础上进行面向对象的架构和重构?为此,笔者送出关键一句话:调整程序结构以使(短期内)添加新功能更容易。更多内容请见另外一篇博文《如何重构你的程序-安全重构法》,相信你会满意的。 |