我们内部每周都有读书会,最近在读《clean code》,基本上是20分钟左右。总体原则是大家轮流来讲。 我自己也领了其中一章,第八章。这一张特别不巧,书少了3页。整个一章少了一半的内容。于是我自己发挥了一下,希望大家能有所收获。
从接口到类、工程、系统、框架。在做设计的时候关于边界的基本思路是一致的。就是需要在普适性和集中性中做一个权衡。权衡的结果直接就影响着边界。
边界的目的是要保证:易于理解,难以被误用。
边界划分的典型例子:spring
spring框架是一个分层架构,由7个定义良好的模块组成。每个模块都可以单独存在,或者与其他一个或多个模块联合实现。
明确的职责是整洁边界的基础。拿Spring的核心容器举例。从上面图中可以看出,核心模块是spring框架中最底层核心的模块,提供了最基本的IoC思想和一些核心工具。想明确边界先要明确概念和职责。
IoC
IoC是Inversion of Control的缩写,多数书籍翻译成“控制反转”。是1996年,Michael Mattson在一篇有关探讨面向对象框架的文章中首先提出来的。简单来说就是把复杂系统分解成相互合作的对象,这些对象类通过封装以后,内部实现对外部是透明的,从而降低了解决问题的复杂度。
IoC的别名:依赖注入(DI)
2004年,Martin Fowler讨论了既然IoC是控制反转,那么到底是哪些方面的控制被反转了呢?经过详细地分析和论证后,他得出了答案:“获得依赖对象的过程被反转了”。控制被反转之后,获得依赖对象的过程由自身管理变为了由IoC容器主动注入。于是他给“控制反转”取了一个更合适的名字叫做“依赖注入(Dependency Injection)”。他的这个答案,实际上给出了实现Ioc的方法:注入。所谓依赖注入,就是由IoC容器在运行期间,动态地将某种依赖关系注入到对象之中。所以,依赖注入和控制反转是从不同的角度来描述同一件事情,就是指通过引入IoC容器,利用依赖关系注入的方式,实现对象之间的解耦。
到现在spring core的核心边界已经可以确立了。那么再进一步从实现上来剖析边界。
IoC中最基本的技术就是反射。通俗来讲就是根据给出的类名来动态的声称对象。这种方式可以让对象在生成时才决定到底是哪一种对象。
IoC容器的工作模式可以看做升级版的工厂模式。然后利用编程语言 的反射编程,根据配置文件中给出的类名生成相应的对象。从实现来看,IoC是把以前在工厂方法里写死的对象生成代码,改变为由配置文件来定义,也就是把工厂和对象生成这两者独立开,目的就是提高灵活性和可维护性。
好,现在技术实现的主要思想也清晰了。这样在代码分层上会有一个大体的思路,超出边界的设计不会太多了。下面就来具体看看代码。
spring core的工程下面,分为6个package,分别是asm,cglib,core,lang,objenesis和util。
ASM是一个全功能Java字节码操作与分析框架。可以用来修改已有的class文件或者直接以二进制形式动态生成class。它提供了通用转换与分析算法,自己组合复杂转换与代码分析工具。
CGLIB是一个强大的、高性能的代码生成库。主要通过对字节码的操作,为对象引入简介级别,以控制对象的访问。
objenesis本身也是一个强大的java库,主要是用在创建对象上面。它可以不用调用构造函数就创建对象。专门用于实例化一些特殊java对象,如私有构造方法,带参数的构造等不能通过class.newInstance()实例化的。
前三个都是反射的实现方式。
lang大家都很熟悉了,是language的缩写,定义了使用的语言,这里具体指JVM。
core包里具体实现了IoC。
util包提供了核心工具,基本上就是对象的生成工具,因为IoC的核心作用就是生成对象。
代码大体框架的边界也定义出来了。下一步看接口。时间关系看最简单的lang包的。
四个注解接口
public @interface UsesSunHttpServer { }
public @interface UsesJava7 { }
public @interface UsesJava8 { }
public @interface UsesSunMisc { }
从接口定义就可以看到这是非常符合这个包的职责的。
再往下具体实现类我就不讲了,主要给大家提供一种思路,整洁的边界是怎样定义出来的。先要从大局上想清楚,然后是一个整体的设计,虽然应用程序的代码天然封装好了设计模式,但是这种理念需要有,这会非常利于写出整洁的代码。代码层次天然表达了设计思路,有人说代码即注释,我看来代码即设计。好的代码会像好的设计文档一样让人读着舒服。
另外,我选用spring框架代码来说明代码整洁之道,主旨在于我个人觉得要写好代码,持续的去了解自己使用的框架、底层源码是一个应该形成的习惯与基本功。因为只有去不断的反思这些东西做了什么才能更好的用好它。我自己亲身感受的学习思路是先学其所长,然后再自成一派。而写好代码又和写好文章非常类似。我最喜欢举得学好之后自成一派的例子就是古龙,总在开场让人惊艳一把。