前面我们构建了项目的黑盒模型和概念模型。
本篇是《如何高效阅读源码》专题的第六篇,我们正式进入到代码,找出项目中的核心模块。
本节内容如下:
-
为什么要找核心模块?
-
定位核心模块的方法
-
具体定位流程
为什么要找核心模块?
相信大家都知道二八法则。二八法则又称为巴莱多定律,是19世纪末20世纪初意大利经济学家巴莱多发现的。他认为,在任何一组东西中,最重要的只占其中的一小部分,约20%,其余80%尽管是多数,却是次要的。
二八法则适用于很多场景,当然也适用于项目代码。前面已经说了,项目是为了解决一个或几个问题的,解决这些问题的代码/模块就是核心代码/模块,而辅助解决问题的代码/模块则是非核心代码/模块。根据二八法则,核心代码/模块占总代码量的20%,重要性却占80%!
另外像Spring项目发展到今天已然是个庞然大物了,想要完整的读完Spring源码现在已经是个不可能完成的任务了,但是它的核心功能从项目创建之初一直到现在就基本没变过:IOC和AOP!
同样现在的Linux内核是一个更大的庞然大物,但是从0.0.1版本到现在的5.*版本,功能模块也基本没多少变化,就是操作系统相关的模块。
所以我们只要理解核心模块,也就理解了这个项目80%的逻辑!要理解核心功能,我们首先需要找到核心模块。但是,怎么找呢?
如何定位核心模块?
一个设计良好的项目,模块之间的依赖关系是明确的,且非核心模块会依赖核心模块。为什么呢?有如下几个原因:
-
核心模块相对非核心模块来说比较稳定。因为它主要解决的是确定的问题,只要解决了问题,那它基本就不会变化了。
-
非核心模块则相对不稳定,因为可能会有各种额外需求的变动。
-
如果核心模块依赖了非核心模块,则会导致相对稳定的核心模块也变得不稳定了
所以我们可以通过模块之间的依赖关系来确定核心模块!
具体该怎么做呢?我们通过JUnit4来演示定位核心模块的流程。
具体操作流程
首先来看JUnit4的源码结构:
从名字我们大致可以猜到哪些是核心包(你读源码的时候就能够体会到取一个好的名字是一件多么重要的事情了!):
-
junit.framework
-
junit.runner
-
org.junit.runner
-
org.junit.runners
这四个包应该是比较重要的。
但是这只是我们的猜测,有没有办法来确认呢?当然有。
假设大家使用的都是IDEA,那么可以在junit包上右击,选择Diagrams,会得到junit包的包结构图,然后将org.junit里的包都拖进入,可以得到下图:
从上图中就可以看到各个包之间的一个继承关系!对上面的关系进行裁剪,我们可以得到一个大致的核心包,我们从下往上看:
-
matchers和function包和其它包之间没有继承关系,我们可以先忽略
-
tests包里都是测试,也可以忽略
-
samples包里是示例,同样忽略
-
extensions包是扩展包,因为我们要找的是核心包,所以此包可以忽略
-
validator包看名字是验证用的,也非核心逻辑,且和runner包之间是通过注解产生关联的,忽略。
-
在前面看文档的时候,我们了解到rules是用于改变测试行为的,也是一种扩展,所以也不是核心逻辑,且和runner包之间是通过注解产生关联的,忽略。(阅读文档可以提高我们定位核心模块的效率)
-
internal包目前看不出来作用,看名字是内部使用的包,但是和runner包之间只是通过注解产生关联的,暂时忽略。
剔除掉这些包后,我们最终得到如下核心包:
-
org.junit.runner
-
org.junit.runners
-
junit.framework
-
junit.runner
-
junit.textui
从依赖关系来看:
-
org.junit.runner和junit.framework都被两个包依赖了,所以这两个包是最核心的两个包。但是junit.framework依赖了org.junit.runner,故org.junit.runner是最核心的包,junit.framework包次之。
-
junit.runner被一个包依赖,优先级低于前两个包
-
junit.textui和org.junit.runners包没有被任何包依赖,所以这两个包的优先级最低
如果我们了解到JUnit4为了兼容JUnit3,所以保留了junit包,那么我们可以在org.junit.runner和junit.framework之间画上一条边界线,如下图所示:
至此,我们就完成了对JUnit核心模块的定位:
-
Junit4的核心包是org.junit.runner和org.junit.runners,且org.junit.runner包是更核心的包,org.junit.runners包次之。
-
junit.framework,junit.runner和junit.textui则是JUnit3的核心包,且junit.framework包是最核心的包。
总结
本文首先阐述了为什么要找核心模块,然后通过模块间的依赖关系来演示定位核心模块的方法。
下文将深入到核心模块内部,找出核心类,构建出抽象模型。