本篇旨在讲述如何以面向对象的思维编程
以下订单为例,客户通过web,填写联系人信息、所购买服务(就是几个checkbox,买几个服务,就勾选几个checkbox,价格基于所选择的服务来计算)、网上支付;点了“提交”按钮后,会进行如下操作:保存到数据库、信用卡支付、生成订单pdf、发送邮件通知客户。
一般代码类似如下:
public class OrderController { OrderDAL dal = new OrderDAL();
public Guid PlaceOrder(OrderInfo orderInfo) { //验证函数,略
Guid orderId=Guid.Empty; bool saveOk = false; using(TransactionScope ts=newTransactionScope()) { orderId = dal.InsertOrder(orderInfo); if (!orderId.Equals(Guid.Empty)) if(PaymentService.Pay(orderInfo.Price)) saveOk = true;
if(saveOk) ts.Complete(); }
if (saveOk) { GenerateNewOrderPdf(orderInfo); SendEmail2Client(orderInfo); }
return orderId; }
private void SendEmail2Client(OrderInfoorderInfo) { throw new NotImplementedException(); }
private void GenerateNewOrderPdf(OrderInfoorderInfo) { throw new NotImplementedException(); } } |
|
上面这段代码就是Martin folwer所说的”事务脚本模式”,即:一个业务方法写在一个函数里,一大块从头到尾写完。
如果想以面向对象方式来写,该如何写呢?答案是(我目前个人认为…哈哈):画出序列图,再进行编码。
因为使用序列图能够帮助找到各个对象、以及各对象间的通信方法,如下:
![](https://images.cnblogs.com/cnblogs_com/aarond/sequence.jpg)
这个图貌似比较复杂,因此只有当系统比较复杂时(业务逻辑)才会选择用面向对象的方式来拆分各个对象,好处有:
1. 各个对象其实就是关注点分离,因此维护方便
a. 比如验证那里,修改起来非常有针对性,很容易定位要修改哪个类
b. 计算价格那里也是,很容易定位到需要修改的地方
2. 单元测试时,可以单独测试各个类,而不用给PlaceOrder写无数的测试函数(分而治之)
a. 如果是“事务脚本型”,给这个PlaceOrder写单元测试 && 代码覆盖率要>=70%,光验证那块就需要很多
b. OOP的代码可以分别给各个class编写单元测试,且代码覆盖率>=70%比较容易能做到