Hard Code Logic -> Static Type -> Dynamic Type Data
在一篇介绍Design Pattern的文章中,我写过这样的看法:Design Pattern的目标就是分离代码中的 变化部分 和 不变部分,我们尽量把 变化部分 单独抽取出来,以便达到 不变部分 的 最大限度的重用。
最大限度的重用,也是软件开发技术追求的目标。
下面通过一个典型的例子,来分析软件开发技术在这个方向上的发展。
假设我们有这样一段代码:
do a lot of things before…
switch ( type ){
case A:
do something.
case B:
do something;
case C:
do something;
}
do a lot of things after…
我们看到, 这里的逻辑分支是硬编码的(The logic branches are hard coded.)
这意味着,每增加一个type, 就要增加一个硬编码的逻辑分支。
这也意味着,这段代码永远没有办法成为一个可以扩展的公用函数库,达到更好的重用。每次增加type,只能在源代码级别上进行扩展。我们一旦把这段代码的编译结果,打包起来成为公用函数库,这段代码就失去了任何扩展性。
解决这个问题的第一个手法是OO多态。
do a lot of things before…
instance.doSomething();
do a lot of things after…
这里的instance是一个interface,具体的实现类从外部注入进来。我们可以传入A, B, C等实现类,这样就实现了上面的switch(type) 的 case A, case B, case C。同样,我们可以传入D,E,F等实现。实现switch(type) 的 case D, case E, case F。这样就达到了逻辑分支的可扩展性。
这种OO多态手法的核心思路是把代码中的逻辑分支 类型化,把变化点分离出来;通过不同的类型实现,就可以实现不同的变化点逻辑。
某些情况下,人们还有更灵活的需求。那么引入了第二种手法,动态解释。
do a lot of things before…
invokeService( serviceScript );
do a lot of things after…
这个里面的serviceScript可以看作一个字符串。
有可能是这样的一条简单调用语句:”serviceA.doSomething()”.
也有可能是完整一段script: “{this.a = getServiceA(); a.doSomething(); a.doMore();}”
动态解释手法,非常灵活强大。一点不利的情况是,只有运行起来的时候,才知道serviceScript里面是否把 a.doSomething() 错误的写成 a.doesSomething()。
在一篇介绍Design Pattern的文章中,我写过这样的看法:Design Pattern的目标就是分离代码中的 变化部分 和 不变部分,我们尽量把 变化部分 单独抽取出来,以便达到 不变部分 的 最大限度的重用。
最大限度的重用,也是软件开发技术追求的目标。
下面通过一个典型的例子,来分析软件开发技术在这个方向上的发展。
假设我们有这样一段代码:
do a lot of things before…
switch ( type ){
case A:
do something.
case B:
do something;
case C:
do something;
}
do a lot of things after…
我们看到, 这里的逻辑分支是硬编码的(The logic branches are hard coded.)
这意味着,每增加一个type, 就要增加一个硬编码的逻辑分支。
这也意味着,这段代码永远没有办法成为一个可以扩展的公用函数库,达到更好的重用。每次增加type,只能在源代码级别上进行扩展。我们一旦把这段代码的编译结果,打包起来成为公用函数库,这段代码就失去了任何扩展性。
解决这个问题的第一个手法是OO多态。
do a lot of things before…
instance.doSomething();
do a lot of things after…
这里的instance是一个interface,具体的实现类从外部注入进来。我们可以传入A, B, C等实现类,这样就实现了上面的switch(type) 的 case A, case B, case C。同样,我们可以传入D,E,F等实现。实现switch(type) 的 case D, case E, case F。这样就达到了逻辑分支的可扩展性。
这种OO多态手法的核心思路是把代码中的逻辑分支 类型化,把变化点分离出来;通过不同的类型实现,就可以实现不同的变化点逻辑。
某些情况下,人们还有更灵活的需求。那么引入了第二种手法,动态解释。
do a lot of things before…
invokeService( serviceScript );
do a lot of things after…
这个里面的serviceScript可以看作一个字符串。
有可能是这样的一条简单调用语句:”serviceA.doSomething()”.
也有可能是完整一段script: “{this.a = getServiceA(); a.doSomething(); a.doMore();}”
动态解释手法,非常灵活强大。一点不利的情况是,只有运行起来的时候,才知道serviceScript里面是否把 a.doSomething() 错误的写成 a.doesSomething()。