聊聊高焕堂老师的EIT架构

今年春节的时候,我在51CTO上选中了新的课程,就是高焕堂老师的EIT架构。由于自己对架构比较感兴趣,刚好又有这种题材的讲座,因此很愉快的学习了一下,感觉也有很多收获,在这里简单的记录一下

什么是EIT

实际上这个名词我也是偶然间得知的,就是自己在听高老师讲的jni系列课程的时候,反复的提到了EIT,当时一脸迷茫,什么是EIT呢?于是百度了一下。发现似乎并没有相关的介绍。在高老师的个人主页上找了半天也没有找到。刚好发现高老师讲的架构相关的课程,就是介绍EIT的讲座,好奇的就学起来了。

老实说刚开始听前几集讲座的时候,还是不太明白高老师要表达的意思。虽然老是提到EIT,EIT,但从始至终也没有说明什么是E,什么是I,什么是T。我也是看到了讲座中的一张图后,才大概明白了EIT的含义,也就是下面的图:

聊聊高焕堂老师的EIT架构_第1张图片
image.png

也就是说E&&I是在一个类中的,T是其子类,这是一个基本的形式
另一种扩展的形式是这样的

聊聊高焕堂老师的EIT架构_第2张图片
image.png

和上面的图稍微有些不同,接口层interface被抽象出来了
这个图已经给出了EIT的英文名称,即engine,interface和tire,但是这三者是什么关系呢?engine是引擎的意思,interface是接口,而tire是轮胎。一开始我没有明白高老师的含义,尤其是EIT的基本型而言,T是子类,怎么能说轮胎是引擎的子类呢?随着学习的逐渐深入,我终于明白,原来这里的EIT是按照扩展型中的图定义的,也就是一个汽车引擎,需要有四个轮胎构成,这里引擎并不直接依赖于具体的轮胎,而是依赖于接口interface,而tire实现了这个接口,于是在编码中就很有弹性了,即,我需要什么轮胎我就组装什么轮胎就可以了,甚至在运行的时候,我还可以换轮胎。这样的设计,显然代码会更有弹性。

设计模式

上面的两种形式,大概是高老师在设计模式的基础上,高度抽象而来。实际上上面的两个图,正是代表了设计模式中的两种经典的模型。

首先我想介绍一下设计模式中的精髓,也就是接口。为什么说接口很重要呢?因为接口可以让两个衔接的模块解耦,让双方互相不知道对方的存在,这在编码架构中,具有非常好的弹性。

设计模式有很多种,但最核心的就是五大原则了。在这五大原则中,我觉得最重要的,就是最后一个原则,就是开闭原则,即对扩展是开放的,对修改是封闭的。也就是说,如何判断我们写的架构好不好呢?其实很简单,如果追加一个类似的功能,可不可以?这就是扩展型。在扩展的同时是否必须需要破坏之前的代码?还是直接追加新的文件就可以了,以前的文件可以最大程度的保持不变?这就是封闭性。如果你写的架构,同时具备扩展型和封闭性,那么就真的是一个好的架构了。

举个例子,如果需要实现一个架构,小明每天骑车上班,我们应该如何设计呢?
我想最直观的设计就是下图了

聊聊高焕堂老师的EIT架构_第3张图片
image.png

这实在是太简单了,刚学会编程的人,大概也可以写的出来这个代码。
我们简单的写一下这个代码评估一下

class Person {
    void take(Bike* bike);
};

class Bike {

};

int main(int argc, char* argv) {
    Person* person = new Person();
    Bike* bike = new Bike();
    person->take(bike);
    return 0;
}

这真的不是很难。
该如何评估这个架子是否好呢?就用上面的两个法则,其一,检验是否有扩展性,比如现在提出一个新需求,小明坐公交上班,这个架构是否也同样适用?当然了可以适用,只需要添加一个Bus类,并且将Person类中take的参数,改为Bus* bus就可以了。其二,检验是否是封闭的,我们为了扩展新的需求,不得不修改已经写好的类中的代码,即改变了Person中方法的参数,这显然不满足封闭性。
特别的,如果我需要增加更多的交通工具,Person类就要不断的修改,显然,这个架构设计,smell bad。

为什么这两个特性都至关重要呢?扩展性就不必多说了,如果一个系统一点点扩展性都没有,显然不会是一个很好的系统。为什么我们需要保持封闭性呢?因为我们不封闭就意味着之前的代码需要修改,那之前的一些工作无疑就白做了。比如Person类测试已经充分验证,完全没有问题,可以给用户使用,但是为了扩展一个新的功能,我们不得不修改Person类,这样之前的测试结果又要重来一遍,谁知道你引入的新的代码,会不会引起新的bug呢~

进一步思考,为何我们的设计会破坏了开闭原则呢?就是因为我们让具体的东西Person,依赖于了具体的东西Bike了。也就是两个具体的东西耦合在了一起,因此Bike的改变必然会引起Person的改变。正确的做法,应该是依赖于抽象!因此我们要从交通工具中找到共通点,从而抽象出抽象的接口

聊聊高焕堂老师的EIT架构_第4张图片
image.png

好了,这样一来,Person这个具体的东西,依赖于Traffic这个接口,那么Bike的改变就不会引起Person的改变了
简单的代码如下

class Traffic;

class Person {
    void take(Traffic* trafic);
};

class Traffic {

};

class Bike : public Traffic {

};

class Bus : public Traffic {

};

int main(int argc, char* argv[]) {
    Person* person = new Person();
    Traffic* traffic = new Bike();
    person->take(traffic);
}

这样的设计,显然比刚才的设计就改良了不少,如果你还想扩展新的交通工具,只要做相应的子类就可以了,这个扩展,也不会引起Person类的修改,完全符合设计模式的原则,真的很不错。

说到这里,我们其实就描述了一个设计模式:策略模式。什么是策略模式呢?我们去上班实际上是一种策略,也就是这里的traffic接口,而具体的策略,比如是骑自行车,还是做公交车之类的由子类决定。

EIT与设计模式

介绍完设计模式,特别是策略模式,我们可以在EIT中找到策略模式的影子。E可以看做是Person,I可以看做是Traffic接口,而Bike以及Bus,就是具体的T。所以扩展的EIT模式,就可以看做是设计模式中的策略模式。

对于标准的EIT模型,设计模式中也有与其相对应的一种,即模板模式。模板模式的应用场景是这样的,做一件事,可能分为几个步骤,但是在做具体的步骤的时候,不同的用户做法不同,我们将这些具体的步骤做成接口,让用户在实现子类中实现。比如,我们在排序的时候需要知道如何判断两个数的大小,这个具体的算法,由用户决定,因此做成接口。用户在准备排序时,只需要提供如何判断两个数大小的方法就可以,至于如何排好序,基类就已经实现好了,用户不需要知道。

因此从这里看来,EIT的基本形式和扩展形式,实际上就对应了设计模式中的两种经典的模式模板模式以及策略模式。让我们继续挖掘一下这两个形式。基本形式是E&&I做在了一起,即在一个类中,而T继承了I,这就是一个典型的继承关系,也就是is-a的关系。而扩展形式是E有一个接口I,T实现了接口I,这就是一个has-a的关系。这两种关系各有利弊。设计模式中的建议,是让我们尽量多用组合的方式,即has-a的关系,而少用继承的关系,即用组合来替代继承。这样做的好处时,组合关系在运行时是可以替换的。比如小明骑车上班,在中间突然想换公交车了,这也是完全可以的。

内容与形式

我们说EIT有两种形式,基本形式和扩展形式,什么是形式呢?形式就是一种套路。高老师的意思是我们需要编码的任何内容都可以放在这个形式中。你看,这里就提到了内容和形式。我们需要编码的,就是内容,EIT就是形式,也就是,我们需要编码的任何东西,都可以以EIT的形式呈现。

比如刚才提到的小明骑车上班,就是内容,我们刚才用策略模式实现,即EIT的扩展型实现,就是一种形式。也就是我们用EIT的形式,实现了小明骑车上班的内容。

那么,真的所有复杂的代码架构,都可以通过EIT的形式展示吗?实际上是可以的,但绝不仅仅是一种形式,复杂代码架构,是由EIT这种简单的形式组合而成。

事实上,这里蕴含的思想非常重要:任何复杂的东西都是由简单的东西堆砌而成。所以在拿到一个复杂的架构的时候,我们需要将他首先拆解成几个简单东西的组合,有的时候简单的东西还需要继续拆解。而拆解到最后的功能或者功能组,也就是内容,都可以通过EIT这种形式展示出来,最后,我们将这些EIT的形式组合到一起,ok,复杂的架构就开发出来了。

我觉得这种思想也体现了软件架构设计的重要思路。
因此拿到一个需求,我们首先需要将需求分解,再提取出接口,分的好,接口设计的好,架构就越好。

强龙不压地头蛇

高老师进一步提出了强龙不压地头蛇的思想。什么是强龙?强龙做的就是E&&I,什么是地头蛇?地头蛇做的就是T
说的直观一点,强龙就是做框架设计的,而地头蛇,就是做定制化开发的。

比如Android,谷歌的程序员们,就是强龙,他们负责做框架的开发,他们将功能与任务进行分解,并且流出了必要的接口I,比如Activity中流出了接口OnCreate,OnDestroy等等。而我们这些程序开发者,就是要实现强龙们为我们设计好的接口,做定制化的开发。这样,就产生了形形色色的不同的Android应用。

因此架构师们的核心工作就是,将系统进行拆解,设计出接口I,接口的设计,体现了一个架构师的能力,接口设计的好,地头蛇们开发的就会非常开心。

尾声

好了,对于高老师的这套架构讲座,就暂时总结到这里了。
我觉得自己的收获还是很大的。高老师提出的EIT的思路确实很有借鉴意义。

你可能感兴趣的:(聊聊高焕堂老师的EIT架构)