`
dingjob
  • 浏览: 180474 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

代码注意降低接口提供者和调用者的耦合度

阅读更多
描述: 写代码时,接口中尽量封装为对外透明,外面只管调用,不用关心
自己的状态。

比较下三段比较简单的代码:用于下单和删除时客户付费状态修改



1. updateCustomerPayingToExperience,updateCustomerExperienceToPaying 分开
if (ChanOrder.CONVERT_FEE_ORDER.equals(order.getIsConvertFee())) {
   this.updateCustomerPayingToExperience(order.getCustomerId());
    }
  }
 
if (ChanOrder.CONVERT_FEE_ORDER.equals(order.getIsConvertFee())) {
   this.updateCustomerExperienceToPaying(order.getCustomerId());
 }





2.第一次修改,两个方法合并,状态互转,只要都调这个方法就够了,调用接口处还是
要判断。

public void updateCustomerFeetype(CustomerDO customer) {
  
  String feeType = ChannelConstant.CHAN_CUSTOMER_FEE_TYPE_EXPERIENCE;
  // 获取客户当前付费状态,如果是试用客户,转化为付费客户。
  if (ChannelConstant.CHAN_CUSTOMER_FEE_TYPE_EXPERIENCE.equals(customer.getFeeType())) {
   feeType = ChannelConstant.CHAN_CUSTOMER_FEE_TYPE_PAYING;
  } 
  // 修改客户付费状态
  chanCustomerBOService.updateCustomerFeetype(customer.getCustomerId(), feeType);
 }


3.第二次修改,根据订单状态判断,任何地方调用都不会出错,接口出无需判断:
public void modifyCustomerFeeType(String customerId) {
  boolean hasFeeOrder = false;// 存在付费订单(包含试用转付费)
  boolean hasExperienceOrder = false;// 存在试用订单
  String customerFeeType;// 客户订单状态
 
  // 1.取得客户所有订单
  List<ChanOrder> orderList = channelOrderCommonDAO.getOrdersByCustomerId(customerId);
  for (ChanOrder order : orderList) {
   if(ChanOrder.ORDER_STATUS_ABOLISHED.equals(order.getStatus())){
    //作废订单不作为判断依据
    continue;
   }
   
   // 判断是否包含试用订单和付费订单
   if (ChanOrder.FEE_TYPE_YES.equals(order.getFeeType())) {
    hasFeeOrder = true;
   } else {
    hasExperienceOrder = true;
   }
  }
 
  // 2.仅当存在试用订单且不存在付费订单时,客户为试用客户
  if (hasExperienceOrder && !hasFeeOrder) {
   customerFeeType = CustomerDO.CUSTOMER_FEE_TYPE_FREE;
  } else {
   customerFeeType = CustomerDO.CUSTOMER_FEE_TYPE_PAID;
  }
  
  // 3.更新客户付费状态
  chanCustomerBOService.updateCustomerFeetype(customerId, customerFeeType);
 
 }


  总结下:
  降低耦合度是封装的要求,最近看了《代码大全》这本书关于接口的要求,颇有感触:
其中有这样一句话"不要对类的使用者做出任何假设,类的设计和实现应该符合在类的接口中所隐含的契约。它不应该对接口会被如何使用或不会被如何使用做出任何假设——除非在接口中有过明确说明"
  显然就是说要假设调用你的接口的人就是什么也不懂,随随便便就调用了,这种情况下不会出错。这也许就是对耦合度最朴素的解释。正常的流程就是这样,你提供了接口,就要对接口负责,我调用者不需要了解细节,对调用者完全是透明的。

  如下几段关于耦合的话也比较经典,不加修饰的摘抄一下:
让阅读代码比编写代码更方便,阅读代码的次数要比编写代码多得多,即使在开发的初期也是如此。因此,为了让编写代码更方便而降低代码的可读性是非常不经济的。尤其是在创建类的接口时,即使某个子程序与接口的抽象不很相配,有时人们也往往把这个子程序加到接口里,从而让正开发的这个类的某处调用代码能更方便地使用它。然而,这段子程序的添加正是代码走下坡路的开始,所以还是不要走出这一步为好。

留意过于紧密的耦合关系  “耦合(coupling)”是指两个类之间关联的紧密程度。通常,这种关联越松(loose)越好。根据这一概念可以得出以下一些指导建议:

■           尽可能地限制类和成员的可访问性。

■           避免友元类,因为它们之间是紧密耦合的。

■           在基类中把数据声明为private而不是protected,以降低派生类和基类之间耦合的程度。

■           避免在类的公开接口中暴露成员数据。

■           要对从语义上破坏封装性保持警惕。

■           察觉“Demeter(得墨忒耳)法则”(见本章第6.3节)

  合性与抽象和封装性有着非常密切的联系。紧密的耦合性总是发生在抽象不严谨或封装性遭到破坏的时候。如果一个类提供了一套不完整的服务,其他的子程序就可能要去直接读写该类的内部数据。这样一来就把类给拆开了,把它从一个黑盒子变成了一个玻璃盒子,从而事实上消除了类的封装性。

   同样关于,内聚性,这里也有比较好的诠释,搭车写一下:
内聚性要求接口类要实现抽象的一致性,方法要实现数据操作,存取等的一致性,我们写代码时,往往关注于快速实现和所谓的敏捷开发,而忘记了这个接口最初是用来干什么的,让接口变得臃肿不堪,难于维护,这实际上会让你后来的开发变得越来越不敏捷。因此良好的内聚性和接口的良好封装也应该成为我们的规范。

0
0
分享到:
评论

相关推荐

    PetShop最新源代码合集(5.0、4、3版本合集)

    插入订单的策略可以分为同步和异步,两者的插入策略明显不同,但对于调用者而言,插入订单的接口是完全一样的,所以PetShop 5.0中设计了IBLLStrategy模块。 虽然在IBLLStrategy模块中,仅仅是简单的IOrderStategy,...

    Spring面试题

    异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。 ☆ Spring ORM:Spring 框架插入了若干个 ORM 框架,...

    二十三种设计模式【PDF版】

    关于本站“设计模式” Java 提供了丰富的 API,同时又有强大的数据库系统作底层支持,那么我们的编程似乎变成了类似积木的简单"拼凑"和调用, 甚至有人提倡"蓝领程序员",这些都是对现代编程技术的不了解所至. 在...

    蚂蚁云客服机器人面试答案.docx

    总而言之,在传统的对象创建方式中,通常由调用者来创建被调用者的实例,而在Spring中创建被调用者的工作由Spring来完成,然后注入调用者,即所谓的依赖注入or控制反转。 注入方式有两种:依赖注入和设置注入; IoC...

    计算机二级公共基础知识

    例如,在图1-1中,根结点A和结点B的度为2,结点C的度为1,叶子结点D,E,F的度为0。所以,该树的度为2。 深度 定义一棵树的根结点所在的层次为1,其他结点所在的层次等于它的父结点所在的层次加1。树的最大层次称为...

    Java并发编程(学习笔记).xmind

    如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常,告诉调用者“我不能再接受任务了” keepAliveTime 保持存活时间,当线程数大于corePoolSize的空闲线程能...

    火炬博客系统5

    各个层可以单独开发,互相的耦合度很低,这在开发大项目的过程中尤其有优势,层与层之间通过调用接口完成所需要的逻辑单元应用,一切显得非常清晰简单。 Struts是目前最流行的Web框架,提供对开发MVC系统...

    火炬博客系统7

    各个层可以单独开发,互相的耦合度很低,这在开发大项目的过程中尤其有优势,层与层之间通过调用接口完成所需要的逻辑单元应用,一切显得非常清晰简单。 Struts是目前最流行的Web框架,提供对开发MVC系统...

    火炬博客系统6

    各个层可以单独开发,互相的耦合度很低,这在开发大项目的过程中尤其有优势,层与层之间通过调用接口完成所需要的逻辑单元应用,一切显得非常清晰简单。 Struts是目前最流行的Web框架,提供对开发MVC系统...

    软件工程-理论与实践(许家珆)习题答案

    还涉及到软件系统的目标、软件系统提供的服务、软件系统的约束和软件系统运行的环境。它还涉及到这些因素和系统的精确规格说明,以及系统进化之间的关系。 需求分析的基本任务包括: (1) 抽取需求 分析现行系统...

    ROS机器人操作系统入门 Tutorials CN版 20150726

    它是一个开源的元级操作系统(后操作系统),提供类似于操作系统的服务,包括硬件抽象描述、底层驱动程序管理、共用功能的执行、程序间消息传递、程序发行包管理,它也提供一些工具和库用于获取、建立、编写和执行多...

    《计算机操作系统》期末复习指导

    1、科普的观点 操作系统是计算机系统的管理和控制中心,它依照设计者制定的各种调度策略组织和管理计算机系统资源,使之能高效地运行。 2、功能的观点 操作系统是一个计算机资源管理系统,它负责计算机系统的全部...

    基于AT89S52 单片的频率计

    单片机最小系统板电路的组建,单片机程序下载接口和外围电路的接口。 单片机最小系统板的组建: ①单片机的起振电路作用与选择: 单片机的起振电路是有晶振和两个小电容组成的。 晶振的作用:它结合单片机内部的电路...

    c语言编写单片机技巧

    我是一名武汉大学电子科技大3的学生,学了电子线路、数字逻辑、汇编和接口、C语言,但是总是感觉很迷茫,觉好象什么都不会。怎么办? 答:大学过程是一个理论过程,实践的机会比较少,往往会造成理论与实践相...

    iPhone开发秘籍.part2.rar

    1.8.3 关于示例代码和内存管理的 注意事项.....18 1.9 构建Hello World 应用程序.....19 1.9.1 创建iPhone 项目.....19 1.9.2 运行主干.....20 1.9.3 定制iPhone 项目.....20 1.9.4 编辑标识信息.....21 1.9.5 使用...

    iPhone开发秘籍.part1.rar

    1.8.3 关于示例代码和内存管理的 注意事项.....18 1.9 构建Hello World 应用程序.....19 1.9.1 创建iPhone 项目.....19 1.9.2 运行主干.....20 1.9.3 定制iPhone 项目.....20 1.9.4 编辑标识信息.....21 1.9.5 使用...

    iPhone开发秘籍.part4.rar

    1.8.3 关于示例代码和内存管理的 注意事项.....18 1.9 构建Hello World 应用程序.....19 1.9.1 创建iPhone 项目.....19 1.9.2 运行主干.....20 1.9.3 定制iPhone 项目.....20 1.9.4 编辑标识信息.....21 1.9.5 使用...

    (更新)基于STM32的数字示波器设计(完整的设计资料)-电路方案

    是德科技(NYSE:KEYS)-原安捷伦电子测量事业部,是全球电子测量技术和市场的领导者,致力于推动无线通信、模块化和软件解决方案的持续创新,专注于为客户提供卓越的测量体验。是德科技提供的电子测量仪器、系统、...

Global site tag (gtag.js) - Google Analytics