??xml version="1.0" encoding="utf-8" standalone="yes"?>四虎影视成人,在线精品视频视频中文字幕,中文字幕在线观看亚洲http://www.aygfsteel.com/iNeo/category/5353.htmlzh-cnWed, 28 Feb 2007 08:20:27 GMTWed, 28 Feb 2007 08:20:27 GMT60Eclipse的数据库插ghttp://www.aygfsteel.com/iNeo/archive/2006/03/30/38228.html只牵q只?/dc:creator>只牵q只?/author>Thu, 30 Mar 2006 04:42:00 GMThttp://www.aygfsteel.com/iNeo/archive/2006/03/30/38228.htmlhttp://www.aygfsteel.com/iNeo/comments/38228.htmlhttp://www.aygfsteel.com/iNeo/archive/2006/03/30/38228.html#Feedback0http://www.aygfsteel.com/iNeo/comments/commentRss/38228.htmlhttp://www.aygfsteel.com/iNeo/services/trackbacks/38228.html 今天上午升 Eclipse ?/span> 3.1.2 版本Q完了之后就x个数据库的插Ӟ但花了近 2 个小时后得出的结论是Q还没有支持 3.1.x 版本的数据库插gQ郁L(fng)不行。看?/span> eclipse3.1.12 的发行日期—?/span> 2005.12.26 Q咳Q去q?/span> 12 月䆾出的Q想不到到现在还没有支持的版本。当然也可能是我没找到。如果哪位兄台能l个支持 3.1.x 版本的数据库插gQ将不甚感激Q?/span>

虽然没找到正主,但还是找C一?/span> Eclipse3.0.x 版本可用的版本,以共来参考?/span>

SQLExplorer
SQLExplorer 可以通过JDBC讉K几乎M一U数据库。同时也支持?span lang="EN-US">Hibernateq样的工兯问数据库。现在的版本?span lang="EN-US">SQLExporer 2.2.4 released?span lang="EN-US">

下栽地址Q?span lang="EN-US">http://sourceforge.net/projects/eclipsesql

JFaceDBC

是一个很好的 SQL 控制?/span> , 支持各类L数据库。现在的版本?/span> JFaceDbc 3.0

下栽地址Q?span lang="EN-US">http://sourceforge.net/projects/jfacedbc

Quantum
Quantum 是一个数据库讉K插g.它当前支持的数据库有:Postgres,MySQL,Adabas,DB2,Oracle与有JDBC驱动的数据库.它可以显C?span lang="EN-US">,视图q提供一个语法可高亮昄?span lang="EN-US">SQL~辑?/span>

com.quantum.feature_3.0.1.bin.dist

下栽地址Q?span lang="EN-US">http://sourceforge.net/project/showfiles.php?group_id=7746&package_id=57047



]]>
M人都可以重构[来自IBM]http://www.aygfsteel.com/iNeo/archive/2006/01/17/28305.html只牵q只?/dc:creator>只牵q只?/author>Tue, 17 Jan 2006 07:28:00 GMThttp://www.aygfsteel.com/iNeo/archive/2006/01/17/28305.htmlhttp://www.aygfsteel.com/iNeo/comments/28305.htmlhttp://www.aygfsteel.com/iNeo/archive/2006/01/17/28305.html#Feedback0http://www.aygfsteel.com/iNeo/comments/commentRss/28305.htmlhttp://www.aygfsteel.com/iNeo/services/trackbacks/28305.html

M人都可以重构

使用 Eclipse 自动重构Ҏ(gu)的Ҏ(gu)与原?/P>
 

 

未显C需?JavaScript 的文档选项


Ҏ(gu)늚评h(hun)

 


U别: 初

David Gallardo, 独立软gN和作?BR>

2003 q?11 ?10 ?/P>

Eclipse 提供了一l强大的自动重构QrefactoringQ功能,q些功能I插在其他功能当中,使?zhn)能够重命?Java元素Q移动类和包Q从具体的类中创建接口,嵌套的cd成顶U类Q以及从旧方法的代码片断中析取出新的Ҏ(gu)。?zhn)熟(zhn)?Eclipse 的重构工具之后,掌握了一U提高生产率的好Ҏ(gu)。本文综览Eclipse 的重构特性,q过例子阐明了用这些特性的Ҏ(gu)与原因?/BLOCKQUOTE>

Z么重?

重构是指在不改变E序功能的前提下改变其结构。重构是一功能强大的技术,但是执行h需要倍加心才行。主要的危险在于可能在不l意中引入一些错误,其是在q行手工重构的时候更是如此。这U危险引发了寚w构技术的普遍批评Q当代码不会(x)崩溃的时候ؓ(f)什么要修改它呢Q?

(zhn)需要进行代码重构的原因可能有以下几个:(x)传说中的W一个原因是Q需要承ؓ(f)某个古老品而开发的q代久远的代码,或者突然碰到这些代码。最初的开发团队已l不在了。我们必d建增加了新特性的新版本YӞ但是q些代码已经无法理解了。新的开发队伍夜以日地工作Q破译代码然后映代码,l过大量的规划与设计之后Qh们将q些代码分割成碎片。历l重重磨难之后,所有这些东襉K按照新版本的要求归位了。这是英雄般的重构故事,几乎没有在经历了q些之后zȝ讲述q样的故事?/P>

q有一U现实一些的情况是项目中加入了新的需求,需要对设计q行修改。至于是因ؓ(f)在最初的规划q程中失察,q是׃采用了P代式的开发过E(比如敏捷开发,或者是试驱动的开发)而在开发过E中有意引入需求,q两者ƈ没有实质性的区别。这L(fng)重构的规模要得多,其内容一般涉及通过引入接口或者抽象类来更改类的承关p,以及对类q行分割和重新组l,{等?/P>

重构的最后一个原因是Q当存在可用的自动重构工hQ可以有一个用来预先生成代码的快捷方式——就好比在?zhn)无法定如何拼写某个单词的时候,可以用某U拼写检查工兯入这个单词。比如说Q?zhn)可以用这U^淡无奇的重构Ҏ(gu)生成 getter ?setter Ҏ(gu)Q一旦熟(zhn)了q样的工P它就可以为?zhn)节省很多的时间?/P>

Eclipse 的重构工h意进行英雄的重构——适合q种规模的工具几乎没有——但是不论是否用到敏捷开发技术,Eclipse 的工具对于一般程序员修改代码的工作都h无法衡量的h(hun)倹{毕竟Q何复杂的操作只要能够自动q行Q就可以不那么烦闷了。只要?zhn)知?Eclipse 实现了什么样的重构工Pq理解了它们的适用情况Q?zhn)的生产力׃?x)得到极大的提高?/P>

要降低对代码造成破坏的风险,有两U重要的Ҏ(gu)。第一U方法是对代码进行一套完全彻底的单元试Q在重构之前和之后都必须通过q样的测试。第二种Ҏ(gu)是用自动化的工hq行重构Q比如说 Eclipse 的重构特性?/P>

彻底的试与自动化重构l合h׃(x)更加有效了,q样重构也就从一U神U的艺术变成了有用的日常工具。ؓ(f)了增加新的功能或者改q代码的可维护性,我们可以在不影响原有代码功能的基上迅速且安全地改变其l构。这U能力会(x)Ҏ(gu)设计和开发代码的方式产生极大的媄响,即便是?zhn)没有其l合到正式的敏捷Ҏ(gu)中也没有关系?/P>

回页?/FONT>


Eclipse 中重构的cd

Eclipse 的重构工具可以分Z大类Q下面的序也就是这些工具在 Refactoring 菜单中出现的序Q:(x)

  1. 对代码进行重命名以及改变代码的物理结构,包括对属性、变量、类以及接口重新命名Q还有移动包和类{?
  2. 改变cMU的代码逻辑l构Q包括将匿名c{变ؓ(f)嵌套c,嵌套类转变为顶U类、根据具体的cd建接口,以及从一个类中将Ҏ(gu)或者属性移到子cL者父cM?
  3. 改变一个类内部的代码,包括局部变量变成类的属性、将某个Ҏ(gu)中选中部分的代码变成一个独立的Ҏ(gu)、以及ؓ(f)属性生?getter ?setter Ҏ(gu)?

q有几个重构工具q不能完全归入这三个U类Q特别是 Change Method SignatureQ不q在本文中还是将q个工具归入W三cR除了这U例外情况以外,本文下面几节都是按照上面的顺序来讨论 Eclipse 重构工具的?/P>

回页?/FONT>


物理重组与重命名

昄Q?zhn)即便没有特别的工P也可以在文gpȝ中重命名文g或者是Ud文gQ但是如果操作对象是 Java 源代码文Ӟ(zhn)就需要编辑很多文Ӟ更新其中?import ?package 语句。与此类|用某U文本编辑器的搜索与替换功能也可以很Ҏ(gu)地给cR方法和变量重新命名Q但是这样做的时候必d分小心,因ؓ(f)不同的类可能h名称怼的方法或者变量;要是从头到尾查项目中所有的文gQ来保证每个东西的标识和修改的正性,那可真够乏味的?

Eclipse ?Rename ?Move 工具能够十分聪明地在整个目中完成这L(fng)修改Q而不需要用L(fng)q涉。这是因?Eclipse 可以理解代码的语义,从而能够识别出Ҏ(gu)个特定方法、变量或者类名称的引用。简化这一d有助于确保方法、变量和cȝ名称能够清晰地指C其用途?/P>

我们l常可以发现代码的名字不恰当或者o(h)人容易误解,q是因ؓ(f)代码与最初设计的功能有所不同。比方说Q某个用来在文g中查扄定单词的E序也许?x)扩展?f)?Web 面中通过 URL 获取 InputStream 的操作。如果这一输入最初叫?file Q那么就应该修改它的名字Q以便能反映其新增的更加一般的Ҏ(gu),比方?sourceStream 。开发h员经常无法成功地修改q些名称Q因个过E是十分混ؕ和乏味的。这当然也会(x)把下一个不得不对这些类q行操作的开发h员弄p涂?

要对某个 Java 元素q行重命名,只需要简单地?Package Explorer 视图中点击这个元素,或者从Java 源代码文件中选中q个元素Q然后选择菜单?Refactor > Rename。在对话框中输入新的名称Q然后选择是否需?Eclipse 也改变对q个名称的引用。实际显C出来的切内容与?zhn)所选元素的cd有关。比方说Q如果选择的属性具?getter ?setter Ҏ(gu)Q那么也可以同时更新这些方法的名称Q以反映新的属性。图1昄了一个简单的例子?

?1. 重命名一个局部变?/B>
Renaming a local variable

像所有的 Eclipse 重构操作一P当?zhn)指定了全部用来执行重构的必要信息之后Q?zhn)可以点?Preview 按钮Q然后在一个对话框中对?Eclipse 打算q行哪些变更Q?zhn)可以分别否决或者确认每一个受到媄响的文g中的每一变更。如果?zhn)对?Eclipse 正确执行变更的能力有信心的话Q?zhn)可以只按?OK按钮。显Ӟ如果(zhn)不定重构到底做了什么事情,(zhn)就?x)想先预览一下,但是对于 Rename ?Move q样单的重构而言Q通常没有必要预览?

Move 操作?Rename 十分怼Q?zhn)选择某个 Java 元素Q通常是一个类Q,为其指定一个新位置Qƈ定义是否需要更新引用。然后,(zhn)可以选择 Preview查变更情况,或者选择 OK 立即执行重构Q如?所C?

?2. 类从一个包Ud另一个包
Moving a class

在某些^CQ特别是 WindowsQ,(zhn)还可以?Package Explorer 视图中通过单拖攄Ҏ(gu)类从一个包或者文件夹中移到另一个包或文件夹中。所有的引用都会(x)自动更新?/P>

回页?/FONT>


重新定义cȝ关系

Eclipse 中有大量的重构工P使?zhn)能够自动改变cȝ关系。这些重构工具ƈ没有 Eclipse 提供的其他工具那么常用,但是很有价|因ؓ(f)它们能够执行非常复杂的Q务。可以说Q当它们用得上的时候,׃(x)非常有用?/P>

提升匿名cM嵌套c?/FONT>

Convert Anonymous ClassQ{换匿名类Q和 Convert Nested TypeQ{换嵌套类Q这两种重构Ҏ(gu)比较怼Q它们都某个类从其当前范围Ud到包含这个类的范围上?/P>

匿名cL一U语法速写标记Q(zhn)能够在需要实现某个抽象类或者接口的地方创徏一个类的实例,而不需要显式提供类的名U。比如在创徏用户界面中的监听器时Q就l常用到匿名cR在清单1中,假设 Bag 是在其他地方定义的一个接口,其中声明了两个方法, get() ?set() ?


清单 1. Bag c?/B>
 
      public class BagExample
{
   void processMessage(String msg)
   {
      Bag bag = new Bag()
      {
         Object o;
         public Object get()
         {
            return o;
         }
         public void set(Object o)
         {
            this.o = o;
         }
      };
      bag.set(msg);
      MessagePipe pipe = new MessagePipe();
      pipe.send(bag);
   }
}

当匿名类变得很大Q其中的代码难以阅读的时候,(zhn)就应该考虑这个匿名类变成严格意义上的c;Z保持装性(换句话说Q就是将它隐藏v来,使得不必知道它的外部cM知道它)Q?zhn)应该其变成嵌套c,而不是顶U类。?zhn)可以在这个匿名类的内部点击,然后选择 Refactor > Convert Anonymous Class to Nested 可以了。当出现认对话框的时候,个类输入名称Q比?BagImpl Q然后选择 Preview或?OK。这P代码变成了如清?所C的情Ş?


清单 2. l过重构?Bag c?/B>
 

public class BagExample
{
   private final class BagImpl implements Bag
   {
      Object o;
      public Object get()
      {
         return o;
      }
      public void set(Object o)
      {
         this.o = o;
      }
   }
       
   void processMessage(String msg)
   {
     Bag bag = new BagImpl();
     bag.set(msg);
     MessagePipe pipe = new MessagePipe();
     pipe.send(bag);
   }
}

当?zhn)惌其他的类使用某个嵌套cLQConvert Nested Type to Top Level 很有用了。比方说Q?zhn)可以在一个类中用值对象,像上面?BagImpl c那栗如果?zhn)后来又决定应该在多个cM间共享这个数据,那么重构操作p从这个嵌套类中创建新的类文g。?zhn)可以在源代码文g中高亮选中cdUͼ或者在 Outline 视图中点ȝ的名UͼQ然后选择 Refactor > Convert Nested Type to Top LevelQ这样就实现了重构?

q种重构要求(zhn)ؓ(f)装入实例提供一个名字。重构工具也?x)提供徏议的名称Q比?example Q?zhn)可以接受q个名字。这个名字的意思过一?x)儿清楚了。点?OK 之后Q外层类 BagExample ׃(x)变成清单3所C的样子?


清单 3. l过重构?Bag c?/B>

public class BagExample
{
   void processMessage(String msg)
   {
      Bag bag = new BagImpl(this);
      bag.set(msg);
      MessagePipe pipe = new MessagePipe();
      pipe.send(bag);
   }
}

h意,当一个类是嵌套类的时候,它可以访问其外层cȝ成员。ؓ(f)了保留这U功能,重构q程一个装入类 BagExample 的实例放在前面那个嵌套类中。这是之前要求(zhn)输入名U的实例变量。同时也创徏了用于设|这个实例变量的构造函数。重构过E创建的新类 BagImpl 如清?所C?


清单 4. BagImpl c?/B>
  
final class BagImpl implements Bag
{
   private final BagExample example;
   /**
    * @paramBagExample
    */
  BagImpl(BagExample example)
   {
      this.example = example;
      // TODO Auto-generated constructor stub
   }
   Object o;
   public Object get()
   {
      return o;
   }
   public void set(Object o)
   {
      this.o = o;
   }
}

如果(zhn)的情况与这个例子相同,不需要保留对 BagExample 的访问,(zhn)也可以很安全地删除q个实例变量与构造函敎ͼ?BagExample cM的代码改成缺省的无参数构造函数?

在类l承关系内移动成?/FONT>

q有两个重构工具QPush Down ?Pull UpQ分别实现将cL法或者属性从一个类Ud到其子类或父cM。假设?zhn)有一个名?Vehicle 的抽象类Q其定义如清?所C?


清单 5. 抽象?Vehicle c?/B>

public abstract class Vehicle
{
   protected int passengers;
   protected String motor;
   
   public int getPassengers()
   {
      return passengers;
   }
   public void setPassengers(int i)
   {
      passengers = i;
   }
   public String getMotor()
   {
      return motor;
   }
   public void setMotor(String string)
   {
      motor = string;
   }
}

(zhn)还有一?Vehicle 的子c,cd?Automobile Q如清单6所C?


清单6. Automobile c?/B>

public class Automobile extends Vehicle
{
   private String make;
   private String model;
   public String getMake()
   {
      return make;
   }
   public String getModel()
   {
      return model;
   }
   public void setMake(String string)
   {
      make = string;
   }
   public void setModel(String string)
   {
      model = string;
   }
}

h意, Vehicle 有一个属性是 motor 。如果?zhn)知道?zhn)将永远只处理汽车,那么q样做就好了Q但是如果?zhn)也允许出现划艇之cȝ东西Q那么?zhn)需要将 motor 属性从 Vehicle cM攑ֈ Automobile cM。ؓ(f)此,(zhn)可以在 Outline 视图中选择 motor Q然后选择 Refactor > Push Down?

Eclipse q是明的Q它知道(zhn)不可能L单单Ud某个属性本w,因此q提供了 Add Required 按钮Q不q在 Eclipse 2.1 中,q个功能q不L能正地工作。?zhn)需要验证一下,看所有依赖于q个属性的Ҏ(gu)是否都推C下一层。在本例中,q样的方法有两个Q即?motor 怼?getter ?setter Ҏ(gu)Q如?所C?

?3. 加入所需的成?/B>
Adding required members

在按q?OK按钮之后Q?motor 属性以?getMotor() ?setMotor() Ҏ(gu)׃(x)Ud?Automobile cM。清?昄了在q行了这ơ重构之?Automobile cȝ情Ş?


清单 7. l过重构?Automobile c?/B>
public class Automobile extends Vehicle
{
   private String make;
   private String model;
   protected String motor;
   public String getMake()
   {
      return make;
   }
   public String getModel()
   {
      return model;
   }
   public void setMake(String string)
   {
      make = string;
   }
   public void setModel(String string)
   {
      model = string;
   }
   public String getMotor()
   {
      return motor;
   }
   public void setMotor(String string)
   {
      motor = string;
   }
}

Pull Up 重构?Push Down 几乎相同Q当?Pull Up 是将cL员从一个类中移到其父类中,而不是子cM。如果?zhn)E后改变LQ决定还是把 motor Ud?Vehicle cMQ那么?zhn)也许׃?x)用到q种重构。同样需要提醒?zhn)Q一定要认(zhn)是否选择了所有必需的成员?

Automobile cMh成员 motorQ这意味着(zhn)如果创建另一个子c,比方?Bus Q?zhn)p需要将 motor Q及其相x法)加入?Bus cM。有一U方法可以表CU关p,卛_Z个名?Motorized 的接口, Automobile ?Bus 都实现这个接口,但是 RowBoat 不实现?

创徏 Motorized 接口最单的Ҏ(gu)是在 Automobile 上?Extract Interface 重构。ؓ(f)此,(zhn)可以在 Outline 视图中选择 Automobile Q然后从菜单中选择 Refactor > Extract Interface。?zhn)可以在弹出的对话框中选择(zhn)希望在接口中包含哪些方法,如图4所C?

?4. 提取 Motorized 接口
Motorized interface

点击 OK 之后Q接口就创徏好了Q如清单8所C?/P>
清单 8. Motorized 接口

public interface Motorized
{
   public abstract String getMotor();
   public abstract void setMotor(String string);
}

同时Q?Automobile 的类声明也变成了下面的样子:(x)


public class Automobile extends Vehicle implements Motorized

使用父类

本重构工L(fng)型中最后一个是 User Supertyp Where Possible。想象一个用来管理汽车细帐的应用E序。它自始至终都?Automobile cd的对象。如果?zhn)惛_理所有类型的交通工P那么(zhn)就可以用这U重构将所有对 Automobile 的引用都变成?Vehicle 的引用(参看?Q。如果?zhn)在代码中?instanceof 操作执行了Q何类型检查的话,(zhn)将需要决定在q些地方适用的是原先的类q是父类Q然后选中W一个选项“Use the selected supertype in 'instanceof' expressions”?

?5. ?Automobile Ҏ(gu)其父c?Vehicle
Supertype

使用父类的需求在 Java 语言中经常出玎ͼ特别是在使用?Factory Method 模式的情况下。这U模式的典型实现方式是创Z个抽象类Q其中具有静态方?create() Q这个方法返回的是实Cq个抽象cȝ一个具体对象。如果需创徏的具体对象的cd依赖于实现的l节Q而调用类对实现细节ƈ不感兴趣的情况下Q可以用这一模式?



回页?/FONT>


改变cd部的代码

最大一c重构是实现了类内部代码重组的重构方法。在所有的重构Ҏ(gu)中,只有q类Ҏ(gu)允许(zhn)引入或者移除中间变量,Ҏ(gu)原有Ҏ(gu)中的部分代码创徏新方法,以及为属性创?getter ?setter Ҏ(gu)?/P>

提取与内?/FONT>

有一些重构方法是?Extract q个词开头的QExtract Method、Extract Local Variable 以及Extract Constants。第一?Extract Method 的意思?zhn)可能已经猜到了,它根据(zhn)选中的代码创建新的方法。我们以清单8中那个类?main() Ҏ(gu)Z。它首先取得命o(h)行选项的|如果有以 -D 开头的选项Q就其以名-值对的Ş式存储在一?Properties 对象中?


清单 8. main()

import java.util.Properties;
import java.util.StringTokenizer;
public class StartApp
{
   public static void main(String[] args)
   {
      Properties props = new Properties();
      for (int i= 0; i < args.length; i++)
      {
         if(args[i].startsWith("-D"))
         {
           String s = args[i].substring(2);
           StringTokenizer st = new StringTokenizer(s, "=");
            if(st.countTokens() == 2)
            {
              props.setProperty(st.nextToken(), st.nextToken());
            }
         }
      }
      //continue...
   }
}

一部分代码从一个方法中取出q放q另一个方法中的原因主要有两种。第一U原因是q个Ҏ(gu)太长Qƈ且完成了两个以上逻辑上截然不同的操作。(我们不知道上面那?main() Ҏ(gu)q要处理哪些东西Q但是从现在掌握的证据来看,q不是从其中提取Z个方法的理由。)另一U原因是有一D逻辑上清晰的代码Q这D代码可以被其他Ҏ(gu)重用。比方说在某些时候,(zhn)发现自己在很多不同的方法中都重复编写了相同的几行代码。那有可能是需要重构的原因了,不过除非真的需要重用这部分代码Q否则?zhn)很可能ƈ不?x)执行重构?

假设(zhn)还需要在另外一个地方解析名-值对Qƈ其攑֜ Properties 对象中,那么(zhn)可以将包含 StringTokenizer 声明和下面的 if 语句的这D代码抽取出来。ؓ(f)此,(zhn)可以高亮选中q段代码Q然后从菜单中选择 Refactor > Extract Method。?zhn)需要输入方法名Uͼq里输入 addProperty Q然后验证这个方法的两个参数Q?Properties prop ?Strings 。清?昄?Eclipse 提取?addProp() Ҏ(gu)之后cȝ情况?


清单 9. 提取出来?addProp()

import java.util.Properties;
import java.util.StringTokenizer;
public class Extract
{
   public static void main(String[] args)
   {
      Properties props = new Properties();
      for (int i = 0; i < args.length; i++)
      {
         if (args[i].startsWith("-D"))
         {
            String s = args[i].substring(2);
            addProp(props, s);
         }
      }
   }
   private static void addProp(Properties props, String s)
   {
      StringTokenizer st = new StringTokenizer(s, "=");
      if (st.countTokens() == 2)
      {
         props.setProperty(st.nextToken(), st.nextToken());
      }
   }
}

Extract Local Variable 重构取出一D被直接使用的表辑ּQ然后将q个表达式首先赋值给一个局部变量。然后在原先使用那个表达式的地方使用q个变量。比方说Q在上面的方法中Q?zhn)可以高亮选中?st.nextToken() 的第一ơ调用,然后选择 Refactor > Extract Local Variable。?zhn)被提示输入一个变量名Uͼq里输入 key 。请注意Q这里有一个将被选中表达式所有出现的地方都替换成新变量的引用的选项。这个选项通常是适用的,但是对这里的 nextToken() Ҏ(gu)不适用Q因个方法(昄Q在每一ơ调用的时候都q回不同的倹{确认这个选项未被选中。参见图6?

?6. 不全部替换所选的表达?/B>
Extract variable

接下来,在第二次调用 st.nextToken() 的地斚w复进行重构,q一ơ调用的是一个新的局部变?value 。清?0昄了这两次重构之后代码的情形?


清单 10. 重构之后的代?/B>

private static void addProp(Properties props, String s)
   {
     StringTokenizer st = new StringTokenizer(s, "=");
      if(st.countTokens() == 2)
      {
         String key = st.nextToken();
         String value = st.nextToken();
        props.setProperty(key, value);
      }
   }

用这U方式引入变量有几点好处。首先,通过辑ּ提供有意义的名称Q可以得代码执行的d更加清晰。第二,代码调试变得更容易,因ؓ(f)我们可以很容易地查表辑ּq回的倹{最后,在可以用一个变量替换同一表达式的多个实例的情况下Q效率将大大提高?/P>

Extract Constant ?Extract Local Variable 怼Q但是?zhn)必须选择静态常量表辑ּQ重构工具将?x)把它{换成静态的 final 帔R。这在将编码的数字和字W串从代码中去除的时候非常有用。比方说Q在上面的代码中我们用?D”这一命o(h)行选项来定义名-值对。先?D”高亮选中Q选择 Refactor > Extract ConstantQ然后输?DEFINE 作ؓ(f)帔R的名U。重构之后的代码如清?1所C:(x)


清单 11. 重构之后的代?/B>

public class Extract
{
   private static final String DEFINE = "-D";
   public static void main(String[] args)
   {
      Properties props = new Properties();
      for (int i = 0; i < args.length; i++)
      {
         if (args[i].startsWith(DEFINE))
         {
            String s = args[i].substring(2);
            addProp(props, s);
         }
      }
   }
   // ...

对于每一U?Extract... cȝ重构Q都存在对应?Inline... 重构Q执行与之相反的操作。比方说Q如果?zhn)高亮选中上面代码中的变量 sQ选择 Refactor > Inline...Q然后点?OKQEclipse ׃(x)在调?addProp() 的时候直接?args[i].substring(2) q个表达式,如下所C:(x)

        if(args[i].startsWith(DEFINE))
         {
            addProp(props,args[i].substring(2));
         }

q样比用(f)时变量效率更高,代码也变得更加简要,至于q样的代码是易读q是含؜Q就取决于?zhn)的观点了。不q一般说来,q样的内嵌重构没什么值得推荐的地斏V?/P>

(zhn)可以按照用内嵌表达式替换变量的相同Ҏ(gu)Q高亮选中Ҏ(gu)名,或者静?final 帔RQ然后从菜单中选择 Refactor > Inline...QEclipse ׃(x)用方法的代码替换Ҏ(gu)调用Q或者用帔R的值替换对帔R的引用?

装属?/FONT>

通常我们认ؓ(f)对象的内部l构暴露出来是一U不好的做法。这也正?Vehicle cd其子c都h private 或?protected 属性,而用 public setter ?getter Ҏ(gu)来访问属性的原因。这些方法可以用两种不同的方式自动生成?

W一U生成这些方法的方式是?Source > Generate Getter and Setter 菜单。这会(x)昄一个对话框Q其中包含所有尚未存在的 getter ?setter Ҏ(gu)。不q因U方式没有用新方法更新对q些属性的引用Q所以ƈ不算是重构;必要的时候,(zhn)必自己完成更新引用的工作。这U方式可以节U很多时_(d)但是最好是在一开始创建类的时候,或者是向类中加入新属性的时候用,因ؓ(f)q些时候还不存在对属性的引用Q所以不需要再修改其他代码?

W二U生?getter ?setter Ҏ(gu)的方式是选中某个属性,然后从菜单中选择 Refactor > Encapsulate Field。这U方式一ơ只能ؓ(f)一个属性生?getter ?setter Ҏ(gu)Q不q它?Source > Generate Getter and Setter 相反Q可以将对这个属性的引用改变成对新方法的调用?

例如Q我们可以先创徏一个新的简?Automobile c,如清?2所C?


清单 12. 单的 Automobile c?/B>

public class Automobile extends Vehicle
{
   public String make;
   public String model;
}

接下来,创徏一个类实例化了 Automobile 的类Qƈ直接讉K make 属性,如清?3所C?


清单 13. 实例?Automobile

public class AutomobileTest
{
   public void race()
   {
      Automobilecar1 = new Automobile();
      car1.make= "Austin Healy";
      car1.model= "Sprite";
      // ...
   }
}

现在装 make 属性。先高亮选中属性名Uͼ然后选择 Refactor > Encapsulate Field。在弹出的对话框中输?getter ?setter Ҏ(gu)的名U——如(zhn)所料,~省的方法名U分别是 getMake() ?setMake()。?zhn)也可以选择与这个属性处在同一个类中的Ҏ(gu)是l直接访问该属性,q是像其他类那样改用q些讉KҎ(gu)。(有一些h非常們֐于用这两种方式的某一U,不过y在这U情况下(zhn)选择哪一U方式都没有区别Q因?Automobile 中没有对 make 属性的引用。)

?. 装属?/B>
Encapsulating a field

点击 OK之后Q?Automobile cM?make 属性就变成了私有属性,也同时具有了 getMake() ?setMake() Ҏ(gu)?

>
清单 14. l过重构?Automobile c?/B>
public class Automobile extends Vehicle
{
   private String make;
   public String model;

   public void setMake(String make)
   {
      this.make = make;
   }

   public String getMake()
   {
      return make;
   }
}

AutomobileTest cM要进行更斎ͼ以便使用新的讉KҎ(gu)Q如清单15所C?


>清单 15. AutomobileTest c?/B>

public class AutomobileTest
{
   public void race()
   {
      Automobilecar1 = new Automobile();
      car1.setMake("Austin Healy");
      car1.model= "Sprite";
      // ...
   }
}

改变Ҏ(gu)的签?/FONT>

本文介绍的最后一个重构方法也是最难以使用的方法:(x)Change Method SignatureQ改变方法的{֐Q。这U方法的功能显而易见——改变方法的参数、可见性以及返回值的cd。而进行这L(fng)改变对于调用q个Ҏ(gu)的其他方法或者代码会(x)产生什么媄响,׃是那么显而易见了。这么也没有什么魔斏V如果代码的改变在被重构的方法内部引发了问题——变量未定义Q或者类型不匚w——重构操作将对这些问题进行标记。?zhn)可以选择是接受重构,E后Ҏ(gu)q些问题Q还是取消重构。如果这U重构在其他的方法中引发问题Q就直接忽略q些问题Q?zhn)必须在重构之后亲自修攏V?/P>

为澄清这一点,考虑清单16中列出的cdҎ(gu)?/P>
清单 16. MethodSigExample c?/B>

public class MethodSigExample
{
   public int test(String s, int i)
   {
      int x = i + s.length();
      return x;
   }
}

上面q个cM?test() Ҏ(gu)被另一个类中的Ҏ(gu)调用Q如清单17所C?


清单 17. callTest Ҏ(gu)

public void callTest()
   {
     MethodSigExample eg = new MethodSigExample();
     int r = eg.test("hello", 10);
   }

在第一个类中高亮选中 test Q然后选择 Refactor > Change Method Signature。?zhn)看到如?所C的对话框?

?8. Change Method Signature 选项
Change Method Signature options

W一个选项是改变该Ҏ(gu)的可见性。在本例中,其改变?protected 或?privateQ这L(fng)二个cȝ callTest() Ҏ(gu)׃能访问这个方法了。(如果q两个类在不同的包中Q将讉KҎ(gu)设ؓ(f)~省g?x)引赯L(fng)问题。) Eclipse 在进行重构的时候不?x)将q些问题标出Q?zhn)只有自己选择适当的倹{?

下面一个选项是改变返回值类型。如果将q回值改?float Q这不会(x)被标记成错误Q因?test() Ҏ(gu)q回语句中的 int ?x)自动{换成 float 。即便如此,在第二个cȝ callTest() Ҏ(gu)中也?x)引起问题,因?f) float 不能转换?int 。?zhn)需要将 test() 的返回值改?int Q或者是?callTest() 中的 r 改ؓ(f) float ?

如果第一个参数的cd?String 变成 int Q那么也得考虑相同的问题。在重构的过E中q些问题会(x)被标出,因ؓ(f)它们?x)在被重构的?gu)内部引v问题Q?int 不具有方?length() 。然而如果将其变?StringBuffer Q问题就不会(x)标记出来Q因?StringBuffer 的确hҎ(gu) length() 。当然这?x)?callTest() Ҏ(gu)中引起问题,因ؓ(f)它在调用 test() 的时候还是把一?String 传递进M?

前面提到q,在重构引发了问题的情况下Q不问题是否被标出Q?zhn)都可以一个一个地修正q些问题Q以l箋下去。还有一U方法,是先行修改q些错误。如果?zhn)打算删除不再需要的参数 i Q那么可以先从要q行重构的方法中删除对它的引用。这样删除参数的q程更加顺利了?

最后一仉要解释的事情?Default Value 选项。这一选项g适用于将参数加入Ҏ(gu){֐中的情况。比方说Q如果我们加入了一个类型ؓ(f) String 的参敎ͼ参数名ؓ(f) n Q其~省gؓ(f) world Q那么在 callTest() Ҏ(gu)中调?test() 的代码就变成下面的样子:(x)

      
         public void callTest()
   {
      MethodSigExample eg = new MethodSigExample();
      int r = eg.test("hello", 10, "world");
   }

在这场有?Change Method Signature 重构的看似可怕的讨论中,我们q没有隐藏其中的问题Q但却一直没有提刎ͼq种重构其实是非常强大的工具Q它可以节约很多旉Q通常(zhn)必进行仔l的计划才能成功C用它?/P>

回页?/FONT>


l束?/FONT>

Eclipse 提供的工具重构变得单,熟?zhn)q些工具有助于(zhn)提高效率。敏捷开发方法采用P代方式增加程序特性,因此需要依赖于重构技术来改变和扩展程序的设计。但即便(zhn)ƈ没有使用要求q行正式重构的方法,Eclipse 的重构工兯是可以在q行一般的代码修改时提供节U时间的Ҏ(gu)。如果?zhn)׃旉熟(zhn)q些工具Q那么当出现可以利用它们的情冉|Q?zhn)p意识到所p的时间是值得的?/P>

回页?/FONT>


参考资?

  • (zhn)可以参阅本文在 developerWorks 全球站点上的 英文原文.

  • 有关重构的核心著作是 Refactoring: Improving the Design of Existing CodeQ?/I> 作?Martin Fowler、Kent Beck、John Brant、William Opdyke ?Don RobertsQAddison-WesleyQ?999q_(d)?

  • 重构是一U正在发展的Ҏ(gu)Q在 Eclipse In Action: A Guide for Java Developers QManningQ?2003q_(d)一书中Q作?David GallardoQEd Burnette 以及 Robert McGovern 从在 Eclipse 中设计和开发项目的角度讨论了这一话题?

  • 模式Q如本文中提到的 Factory Method 模式Q是理解和讨论面向对象设计的重要工具。这斚w的经典著作是 Design Patterns: Elements of Reusable Object-Oriented SoftwareQ作者ؓ(f) Erich Gamma、Richard Helm、Ralph Johnson ?John Vlissides QAddison-WesleyQ?995q_(d)?

  • Design Patterns 中的例子是用 C++ 写成的,q对?Java E序员是不小的障;Mark Grand 所著的 Patterns in Java, Volume One: A Catalog of Reusable Design Patterns Illustrated with UMLQWileyQ?998q_(d)模式翻译成?Java 语言?

  • 有关敏捷~程的一个变U,请参?Kent Beck 所著的 Extreme Programming Explained: Embrace ChangeQAddison-WesleyQ?999q_(d)
Web 站点 developerWorks 上的文章与教E?

回页?/FONT>


关于作?/FONT>

David Gallardo ?Studio B 上的一名作Ӟ他是一名独立Y仉问和作家Q专长ؓ(f)软g国际化、Java Web 应用E序和数据库开发。他成ؓ(f)专业软g工程师已l有十五q了Q他拥有许多操作pȝ、编E语a和网l协议的l验。他最q在一?BtoB ?sh)子商务公?TradeAccess, Inc 领导数据库和国际化开发。在q之前,他是 Lotus Development Corporation ?International Product Development l中的高U工E师Q负责ؓ(f) Lotus 产品Q包?DominoQ提?Unicode 和国际语a支持的跨q_库的开发。David ?Eclipse In Action: A Guide for Java DevelopersQ?003q_(d)一书的合著者。可以通过 david@gallardo.org ?David 联系?



]]>
Eclipse q行命o(h)行参数大全[转]http://www.aygfsteel.com/iNeo/archive/2005/11/28/21679.html只牵q只?/dc:creator>只牵q只?/author>Mon, 28 Nov 2005 07:20:00 GMThttp://www.aygfsteel.com/iNeo/archive/2005/11/28/21679.htmlhttp://www.aygfsteel.com/iNeo/comments/21679.htmlhttp://www.aygfsteel.com/iNeo/archive/2005/11/28/21679.html#Feedback0http://www.aygfsteel.com/iNeo/comments/commentRss/21679.htmlhttp://www.aygfsteel.com/iNeo/services/trackbacks/21679.html  包括英文版本和中文版本两U的说明, 特别需要值得一提的是那?-nl 参数, 可以指定E序启动时所使用的语a. 例如:
eclipse -nl en_US
启动英文语a, q个Ҏ(gu)在安装了国际化语言包以后特别有? 可以方便的切换各个语a的版? 注意 IBM WSAD v5.1 也支持这个功?

q行 Eclipse
?Eclipse 驱动E序安装Q解压羃Q到某个目录Q例如,c:\eclipseQ中之后Q通过q行安装目录中的 Eclipse 可执行文件来启动"工作?。在 Windows pȝ上,该可执行文gUCؓ(f) eclipse.exeQ而在 Linux pȝ上称?eclipse。注意:(x)下列讨论描述 Windows pȝ上的讄。Linux 上的讄是相似的?BR>
如果(zhn)没有另行指定,则^台将~省工作区目录创Zؓ(f)可执行文件的兄弟目录Q例?c:\eclipse\workspaceQ。此工作区目录用作项目的~省内容区,q用于保存Q何必需的元数据。要q行׃n安装或多工作区安装,应明指出工作区的位|而不是用缺省倹{有两种控制工作Z|的Ҏ(gu)Q用当前工作目录或使用 -data 命o(h)行自变量?BR>
工作区位置讄为在当前工作目录?BR>在此Ҏ(gu)中,工作Z|将是当前工作目录中UCؓ(f) workspace 的目录?BR>
实现此目的最Ҏ(gu)的方法可能是使用下列步骤来创建快h式:(x)

D?Windows 资源理器中?eclipse.exe q用右键拖动来创徏 eclipse.exe 的快h式?
~辑快捷方式的属性,以启动位置Q字D|识工作区位置的父目录Q例如,c:\users\robertQ?
关闭属性对话框q双dh式(如果提供的目录ؓ(f) c:\users\robertQ则工作Z|将?c:\users\robert\workspaceQ?
当然Q?zhn)也可以用命令提C符Q通过目录切换ؓ(f)工作区父目录然后q行 eclipse.exeQ来获得同样的效果?BR>
使用 -data 讄工作区的特定位置
要?-data 命o(h)行自变量Q只要将 -data your_workspace_locationQ例如,-data c:\users\robert\myworkspaceQ添加至快捷方式属性中的目标字D|昑ּ地将它包括在命o(h)行上?BR>
使用 -vm 讄 java VM
昑ּ指定在运?Eclipse 时要使用哪个 Java VM。?-vm 命o(h)行自变量Q例如,-vm c:\jre\bin\javaw.exeQ可以实现此目的。如果不使用 -vmQ则 Eclipse 用在 O/S 路径上找到的一?Java VM。当安装其它产品Ӟ它们可更Ҏ(gu)的\径,D在下一ơ启?Eclipse 时用另一 Java VM?BR>
q行 Eclipse 中的高主题
Eclipse 可执行文件及q_本n提供了h们感兴趣的开发或调试 Eclipse 各部件的许多执行选项。运?Eclipse 可执行文件的一般格式是Q?BR>
eclipse [platform options] [-vmargs [Java VM arguments]]
Eclipse 启动参数  命o(h) 描述  原因
-arch architecture
定义 Eclipse q_在其上运行的处理器体pȝ构。Eclipse q_通常使用 Java os.arch 属性的常用值来计算最佌|。如果在此处指定该项Q则q是 Eclipse q_使用的倹{此处指定的值可作ؓ(f) BootLoader.getOSArch() 用于插g。示例值有Q?x86"?sparc"?PA-RISC"?ppc"?2.0
-application applicationId
要运行的应用E序。应用程序由?org.eclipse.core.runtime.applications 扩展Ҏ(gu)供扩展的插g来声明。通常不需要此自变量。如果指定了此项Q则该g(x)覆盖配置提供的倹{如果不指定此项Q则?x)运?Eclipse 工作??1.0
-boot bootJarURL
Q徏议不使用Q用 -configuration 代替Q支?1.0 兼容Q。Eclipse q_的引导插件代码(boot.jarQ的位置Q表CZؓ(f) URL。如果指定此,则会(x)用它来ؓ(f)装入 Eclipse q_引导E序c装入器的类装入器设|类路径。仅当更?startup.jar ?boot.jar 的相对位|时才需要它。注意,不允怋用相?URL?nbsp; *1.0
-classloaderproperties [file]
如果指定的话Q则使用l定位置处的c装入器属性文件来Ȁzd^台类c装入器增强。文件自变量可以是文件\径或 URL。注意,不允怋用相?URL。单?yn)L处以获得更多详细信息?2.0.2
-configuration configurationFileURL
Eclipse q_配置文g的位|,表示?URL。配|文件确?Eclipse q_、可用插仉和主要功能部件的位置。注意,不允怋用相?URL。当安装或更?Eclipse q_旉|文件被写至此位|?nbsp; 2.0
-consolelog
?Eclipse q_的错误日志镜像到用来q行 Eclipse 的控制台。与 -debug l合时很方便使用?1.0
-data workspacePath
要运?Eclipse q_的工作区的\径。工作区位置也是目的缺省位|。相对于从中启动 eclipse 的目录来解释相对路径?1.0
-debug [optionsFile]
^台置于调试方式,q从l定位置处的文g装入调试选项Q如果指定的话)。此文g指示哪些调试点可用于插g以及是否已启用它们。如果未l出文g位置Q则q_在启?eclipse 的目录中查找UCؓ(f)".options"的文件。URL 和文件系l\径都可作为文件位|?1.0
-dev [classpathEntries]
^台置于开发方式。将可选类路径条目Q用逗号分隔的列表)dx个插件的q行时类路径。例如,当工作区包含要开发的插gӞ指定 -dev bin ?x)?f)每个插g目的名?bin 的目录添加类路径条目Q允许在其中存储最新生成的cL件。除M冗余或不存在的类路径条目?1.0
-endsplash params
用于?Eclipse q_启动q运行时关闭闪屏的内部选项。此选项在闪屏处理链中不同的位置有不同的语法和语义?2.0
-feature featureId
主要功能部g的标识。主要功能部件ؓ(f) Eclipse 的已启动实例提供了品个性,q确定用的产品定制信息?2.0
-keyring keyringFilePath
盘上授权数据库Q或"密钥?文gQ的位置。此自变量必M -password 选项配合使用。相对于从中启动 eclipse 的目录来解释相对路径?1.0
-nl locale
定义 Eclipse q_在其上运行的语言环境的名U。Eclipse q_通常自动计算最佌|。如果在此处指定该项Q则q是 Eclipse q_使用的倹{此处指定的值可作ؓ(f) BootLoader.getNL() 用于插g。示例值有Q?en_US"?fr_FR_EURO"?2.0
-nolazyregistrycacheloading
取消Ȁz装入优化的q_插g注册表高速缓存。缺省情况下Q仅当需要时才从注册表高速缓存(可用Ӟ中装入扩展的配置元素Q以减少内存占用。此选项在启动时强制完全装入注册表高速缓存?2.1
-noregistrycache
l过d内部插g注册表高速缓存文件?2.0
-nosplash
q行q_而不昄闪屏?1.0
-os operatingSystem
定义 Eclipse q_在其上运行的操作pȝ。Eclipse q_通常使用 Java os.name 属性的常用值来计算最佌|。如果在此处指定该项Q则q是 Eclipse q_使用的倹{此处指定的值可作ؓ(f) BootLoader.getOS() 用于插gQƈ用于解析插g清单文g中提及的路径?$os$ 变量的出现。示例值有Q?win32"?linux"?hpux"?solaris"?aix"?1.0
-password password
授权数据库的密码。与 -keyring 选项配合使用?1.0
-perspective perspectiveId
启动时要在活动工作台H口中打开的透视图。如果没有指定该参数Q则打开关闭时活动的透视图?1.0
-plugincustomization          propertiesFile
包含插g首选项~省讄的属性文件的位置。这些缺省设|覆盖在主要功能部g中指定的~省讄。相对于从中启动 eclipse 的目录来解释相对路径?2.0
-plugins pluginsFileURL
Q徏议不使用Q用 -configuration 代替Q支?1.0 兼容Q?指定 Eclipse q_查找插g的文件的位置Q表CZؓ(f) URL。该文g为属性文件格式,其中键是L用户定义名称Q值是指向 plugin.xml 文g的显式\径或指向包含插g的目录的路径的用逗号分隔的列表。注意,不允怋用相?URL。如果指定此,则此选项?x)导致创建适当的(f)旉|?*1.0
-refresh
启动时执行工作区的全局h的选项。这从上ơ^台运行以来在文gpȝ中所做的M更改一致?1.0
-showlocation
用于在窗口标题栏中显C工作区的位|的选项。在发行?2.0 中,此选项仅与 -data 命o(h)行自变量一起用?2.0
-showsplash params
用于昄闪屏Q由可执行的 Eclipse q_启动器执行)的内部选项。此选项在闪屏处理链中不同的位置有不同的语法和语义?2.0
-vm vmPath
要用来运?Eclipse q_?Java q行时环?QJREQ的位置。如果不指定此项Q则 JRE 位于 jreQ它?Eclipse 可执行文件的兄弟目录Q。相对于从中启动 eclipse 的目录来解释相对路径?1.0
-ws windowSystem
定义 Eclipse q_在其上运行的 Windows pȝ。Eclipse q_通常使用 Java os.name 属性的常用值来计算最佌|。如果在此处指定该项Q则q是 Eclipse q_使用的倹{此处指定的值可作ؓ(f) BootLoader.getWS() 用于插g、用于配|?SWT 以及用于解析插g清单文g中提及的路径?$ws$ 变量的出现。示例值有Q?win32"?motif"?gtk"?1.0

?-vmargs 条目后面的所有自变量Q但不包?-vmargsQ作拟机自变量(卻I在要q行的类的前面)直接传递到所指示?Java VM。注意:(x)如果 Eclipse 启动?Java vm 自变量(-vmargsQ之后提供的自变量(例如Q?dataQ,?Eclipse 不?x)启动ƈ且(zhn)接收?JVM 已终止。出口代码ؓ(f) 1"的错误?BR>
在不同的 VM 上运?
?J9 上运?Eclipse
当在 J9 版本 1.5 上运?Eclipse Ӟ使用以下 VM 选项Q?

eclipse.exe [eclipse arguments] -vm path_to_j9w.exe             -vmargs -ms:32 -mm:2048 -mo:32768 -moi:32768 -mca:32 -mco:128 -mx:2000000
当在 J9 版本 2.0 上运?Eclipse ӞJ9W 选择的缺省自变量应ؓ(f)合适的选项。但是,要覆?Eclipse 可执行文件以内部方式自动讄的参敎ͼ必须指定 -vmargs 不带M参数Q如下所C:(x)

eclipse.exe [eclipse arguments] -vm path_to_j9w.exe -vmargs
有关q一步信息,参?J9 VM 文档和帮助?BR>
?IBM Developer Kit, Java(TM) Technology Edition VM 上运?Eclipse
IBM Developer Kit, Java(TM) Technology Edition 1.3 Linux 的缺?VM 讄适合q行初期研究工作Q但在进行大型开发时是不够的。对于大型开发,应修?VM 自变量以使有更多的堆可用。例如,下列讄允?Java 堆增大ؓ(f) 256MBQ?BR>
-vmargs -Xmx256M


]]>
վ֩ģ壺 | | | | | | ½| | º| | | Ԫ| ͷ| | ˮ| | ²| | | | | | | ˮ| | | ϵ| ˮ| | | Զ| Ϋ| ׯ| | | | ɽ| | | | ǭ|