美文网首页
程序员修炼之道28~解耦

程序员修炼之道28~解耦

作者: DZQANN | 来源:发表于2022-02-18 00:23 被阅读0次

    解耦是一个很宽泛的事情,几乎出现在系统中的方方面面。解耦的主要目的还是为了应对变化,在一个类或其它结构有变动的时候减少对其它内容的影响。解耦可以有很多个层面

    方法层

    方法层的依赖可以理解为,一个方法A调用了方法B。为了应对不断出现的变化,在方法层面我们首先要做到的是方法的是:

    1. 方法内容要短小。短小的方法总是会更满足"一个方法只做一件事"的要求,做到了这件事,变化其实也只是增加了新的短小方法或者方法间使用的重新排列组合。

    2. 方法的接受参数要用最小范围。举个简单的例子,一个write(File)函数,作用是向File中书写内容。但是实际上这个方法的参数被要求成了XMLFile,这就阻碍了很多人使用这个方法。(这个例子不是很贴切,领悟一下精髓就好)。

    3. 不要用太多的"."

      这本书中也提到了一个叫"得墨忒耳法则"的东西。这个名字这么奇怪是因为这个人的英文名叫"Demeter"。他就是说不要出现a().b().c().d()这样的链式调用。因为这样的链式调用以为着依赖到了更多的内容,本身只依赖了a(),链式调用依赖了a、b、c、d。原则上a方法后面的内容要封到a里面去。这样的要求其实我感觉有些苛刻。时机的开发中这样的链式调用是因为我们的对象A里面包含了对象B,对象B里面包含了对象C。所有的方法只不过是简单的get方法。而我们的系统是贫血模型,这些类本身就是数据的搬运工,本身也没有业务能力。

    类层

    类层其实是说的最多的一个层面,设计原则、设计模式都是在这个层面被讨论的。这一章说了这么几件事

    1. 只管命令不要询问

      这个里面讲的就是,调用类的方法应该直接拿到我们想要的结果,不应该依赖类里面的数据结构。书上的例子就很好

      想要个给客户customer里面的id为指定id的order打折,可以这么写:

      public void applyDiscount(Customer customer, String orderId, BigDecimal discount) {
       customer.findOrder(orderId)
               .getTotals()
               .applyDiscount(discount);
      }
      

      这么写的弊端就是这里暴露了order有一个totals内容,而这与实际的业务没有关系。所以applyDiscount应该作为totals对象的方法,变成这样:

      public void applyDiscount(Customer customer, String orderId, BigDecimal discount) {
       customer.findOrder(orderId)
               .applyDiscount(discount);
      }
      
    2. 不要链式调用

      其实就是上面一点的延伸

    3. 避免全局数据

      这一点可能是我的理解有问题,我不是很认同。原则上来讲,抽象到最后会发现有一些方法都是在操纵一样的内容。这时候就可以把这些方法抽象到一个类里面去,他们操纵的共同的内容就作为这个类的全局变量,所有的方法都在操作这些全局变量,就是高内聚了。

      比如这段代码:

      public boolean updateCheckAllMatch(Map a, Map b, Set c) {
       a.update(b);
       c.removeAll(b.keySet());
       return a.size() == 0;
      }
      

      就可以拆分成这样:

      public class A {
       Set c;
       Map a;
       
       public void update(b) {
           a.update(b);
           c.removeAll(b.keySet());
       }
       
       public boolean allMatched() {
           return c.size() == 0;
       }
      }
      

    线程层级

    其实就是多线程了,特意放出来这里是因为在Clean Code中读到了一句话,多线程其实也是一种解耦,它是把业务处理逻辑和业务处理时间做了解耦。

    系统层级

    系统层级我能想到的有两个方面吧

    1. 项目间的依赖

      每一个系统肯定会或多或少依赖一些第三方库。Clean Code中说对这种依赖,原则上来说我们不能直接使用第三方库的API,我们应该对这些API进行封装,这样在做依赖升级的时候,可以有效的测试升级带来的变化,以及方便应对改动。实际上这个要求也很难做到。

    2. 系统的初始化和系统的运行要解耦

      其实这就是很多框架在做的事,有一张图我搬过来了,箭头代表着依赖的方向。可以看到application只依赖创建好的配置类,而对配置类的创建完全隔离

    突然想到小波老师在给我们培训面向对象编程的时候,对于"高内聚低耦合"举了一个事迹生活中的例子。一家互联网公司有3个团队,项目经理团队、开发团队、测试团队。公司有3个项目A、B、C,每一个团队里多有几个特定的人专门负责其中的一个项目。尴尬的是项目经理团队的办公楼和其它团队的办公地点隔了很远,每次想要当面一起开会讨论总是要花费很多的路程。后来公司调整了结构,按照项目划分团队,每一个团队里都是指定负责该项目的项目经理、开发、测试,沟通效率得到了很大的提高。

    相关文章

      网友评论

          本文标题:程序员修炼之道28~解耦

          本文链接:https://www.haomeiwen.com/subject/cbuulrtx.html