Chinaunix首页 | 论坛 | 博客
  • 博客访问: 794629
  • 博文数量: 738
  • 博客积分: 7000
  • 博客等级: 少将
  • 技术积分: 5000
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-12 09:00
文章分类

全部博文(738)

文章存档

2011年(1)

2008年(737)

我的朋友

分类:

2008-09-12 09:06:30

    摘要:

    要判断一个代码是不是包含了“不合适的依赖”,共有四个方法:1.看代码:有没有互相依赖?2.认真想想:它真正需要的是什么?3.推测一下:它在以后的系统中可以重用吗?4.到要重用的时候就知道了:现在我要重用这个类,能不能重用?

如果现在有一个类Parent,里面有个属性的类型是Child,add的方法里面还有个参数的类型是Girl:

  class Parent{
        Child child;
        void add(Girl girl){
           ...
        }
     }




     因为上面Parent里面用到了Child跟Girl这两个类,我们就说,Parent引用了类Child跟类Girl。现在的问题是,如果Child这个类或者Girl这个类编译不过的话,那么Parent这个类也编译不了了。也就是说,Parent依赖于Child跟Girl。这章讲述的,就是因为一些类的依赖造成的无法重用的问题。

示例

  这是一个处理ZIP的程序。用户可以在主窗口中先输入要生成的目标zip的路径,比如c:\f.zip ,然后输入他想压缩到这个zip的源文件的路径,比如
c:\f2.doc和c:\f2.doc 。然后这个程序就会开始压缩f1.doc和f2.doc,生成f.zip文件。在压缩各个源文件的时候,主窗口下的状态栏都要显示相关的信息。比如,在压缩c:\f2.doc的时候,状态栏就显示"正在压缩 c:\f2.zip"。                                                                              

目前的代码就是                                                                            

    class ZipMainFrame extends Frame {
       StatusBar sb;
       void makeZip() {
           String zipFilePath;
           String srcFilePaths[];
           //根据UI上给zipFilePath和srcFilePaths赋值
           ...
           ZipEngine ze = new ZipEngine();
           ze.makeZip(zipFilePath, srcFilePaths, this);
       }
       void setStatusBarText(String statusText) {
           sb.setText(statusText);
       }
    }  
    
    class ZipEngine {
       void makeZip(String zipFilePath, String srcFilePaths[], ZipMainFrame f) {
           //在该路径上创建zip文件 
           ... 
           for (int i = 0; i < srcFilePaths.length; i++) { 
               //将srcFilePaths[i]的文件加到压缩包中
               ... 
               f.setStatusBarText("Zipping "+srcFilePaths[i]); 
           }
       }
    }

                                                                                              

  我们还有一个存货管理系统,里面有一些程序的数据文件,经常需要压缩起来备份。这些源数据文件都有固定的路径,所以就不需要用户特地去输入路径了。现在我们想直接把上面的这个ZipEngine类拿过来重用。这个存货管理系统也有一个主窗口,同样在压缩待备份文件时,状态栏上面也要显示目前正在压缩的文件名称。

  现在,问题来了。我们希望可以在不用修改代码的情况下直接重用ZipEngine这个类。但看了上面的代码以后我们发现:在调用makeZip这个方法时,还需要一个传递一个ZipMainFrame类型的参数进来。可是很明显我们现在的这个存货管理系统里面并没有ZipMainFrame这样的类。也就是说,现在ZipEngine这个类,在我们的这个存货管理系统中用不了了。

  再往远一点想,好像其他的系统,一般也不会有ZipMainFrame这个类。即使类名一样的,里面所做的功能也不一样。那其他的系统也重用不了这个ZipEngine类了。

“不合适的依赖”,让代码很难被重用

  因为ZipEngine引用了ZipMainFrame这个类,当我们想重用ZipEngine的时候,我们就需要将ZipMainFrame也加进来,调用ZipEngine的makeZip方法时,还要构造一个ZipMainFrame对象传给它。而在新的环境中,我们不可能有一个同样的ZipMainFrame,也不可能特地为了调用这个方法,随便创建一个ZipMainFrame对象给它。

  一般来说,如果一个类A引用了一个类B,当我们想要重用A这个类时,我们就还得将B这个类也加进我们的系统。如果B引用了C,那么B又将C也一起拉了进来。而如果B或者C在一个新的系统中没有意义,或者压根儿不应该存在的情况下,真正我们想要用的A这个类也用不了了。

  因此,“不合适的依赖”让代码很难被重用。

  为了可以重用ZipEngine,首先,我们得让ZipEngine不再引用ZipMainFrame。或者说,让ZipEngine不用依赖于ZipMainFrame。
  那怎么做呢?回答这个问题之前,我们先回答另一个问题:给你一段代码,你怎么判断这段代码是不是包含了“不合适的依赖”?“不合适”这个词定义的标准又是什么?


怎么判断是“不合适的依赖”

  方法1:
  一个简单的方法就是:我们先看一下这段代码里面有没有一些互相循环的引用。比如,ZipMainFrame引用了ZipEngine这个类,而ZipEngine又引用了ZipMainFrame。我们管这样的类叫“互相依赖”。互相依赖也是一种代码异味,我们就认定这样的代码,是“不合适的依赖”。
  这个方法很简单。不过,这种方法并不能包含全部情况,并不是所有有“不合适的依赖”的代码,都是这种互相依赖。

  方法2:
  另一个方法比较主观:在检查代码的时候,我们问自己:对于它已经引用的这些类,是它真正需要引用的吗?对于ZipEngine,它真的需要ZipMainFrame这个类吗?ZipEngine只是改变ZipMainFrame的状态栏上的信息。是不是只有引用了ZipMainFrame才能满足这样的需求,其他类行不行?有没有一个类可以取代ZipMainFrame呢?而实际上,ZipEngine并不是一定要引用ZipMainFrame的。它想引用的,其实只是一个可以显示信息的状态栏而已。
因此,我们就将代码改为:

    class ZipEngine {
void makeZip(String zipFilePath, String srcFilePaths[], StatusBar statusBar) {
           //在该路径上创建zip文件
           ... 
           for (int i = 0; i < srcFilePaths.length; i++) {
               //将srcFilePaths[i]的文件加到压缩包中
               ... 
               statusbar.setText("Zipping "+srcFilePaths[i]);
           }
       }
    }        

                                                                                      

  现在,ZipEngine只是引用了StatusBar,而不再是ZipMainFrame了。可是这样好吗?相对好一些!因为StatusBar比较通用(至少有StatusBar这个类的系统比ZipMainFrame多多了),这样的话,ZipEngine这个类的可重用性就大幅改观了。
  不过,这样的方法还是太主观了。没有一个既定的标准,可以判断ZipEngine到底需要的是什么样的东西。比如,我们就说,ZipEngine其实想要的也不是一个状态栏,它只是想调用一个可以显示一些信息的接口而已(而不是一个状态栏这么大的一个对象)。                                                                    

[1]   

【责编:Peng】

--------------------next---------------------

阅读(286) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~