<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    iNeo

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      30 Posts :: 8 Stories :: 2 Comments :: 0 Trackbacks

    2006年8月3日 #

    我的tomcat工程建在:d:\eclipse\workspace\luc,索引文件是d:\eclipse\workspace\luc\public\index,建立索引的時候路徑為"luc\\public\\index",但在搜索的時候,我用
    searcher = new IndexSearcher(“l(fā)uc\\public\\index”);
    報錯了,因為lucene在FSDirectory里將我的路徑給new File(file.getCanonicalPath());
    但奇怪的是file.getCanonicalPath()出來路徑不對呀
    錯誤是
    java.io.IOException: D:\eclipse\luc\public\index not a directory
    應該是d:\eclipse\workspace\luc\public\index 才對的
    郁悶很久了,現(xiàn)在還沒辦法解決!!!!!!!!!!!!!!!!!!!!!!!!!!
    posted @ 2006-08-03 09:12 只牽這只狗 閱讀(327) | 評論 (0)編輯 收藏

    2006年3月30日 #

    今天上午升級 Eclipse 3.1.2 版本,完了之后就想找個數(shù)據(jù)庫的插件,但花了近 2 個小時后得出的結論是:還沒有支持 3.1.x 版本的數(shù)據(jù)庫插件,郁悶的不行。看看 eclipse3.1.12 的發(fā)行日期—— 2005.12.26 ,咳,去年 12 月份出的,想不到到現(xiàn)在還沒有支持的版本。當然也可能是我沒找到。如果哪位兄臺能給個支持 3.1.x 版本的數(shù)據(jù)庫插件,將不甚感激!

    雖然沒找到正主,但還是找到了一些 Eclipse3.0.x 版本可用的版本,以共將來參考。

    SQLExplorer
    SQLExplorer 可以通過JDBC訪問幾乎任何一種數(shù)據(jù)庫。同時也支持像Hibernate這樣的工具訪問數(shù)據(jù)庫。現(xiàn)在的版本是SQLExporer 2.2.4 released

    下栽地址:http://sourceforge.net/projects/eclipsesql

    JFaceDBC

    是一個很好的 SQL 控制臺 , 支持各類主流數(shù)據(jù)庫。現(xiàn)在的版本是 JFaceDbc 3.0

    下栽地址:http://sourceforge.net/projects/jfacedbc

    Quantum
    Quantum 是一個數(shù)據(jù)庫訪問插件.它當前支持的數(shù)據(jù)庫有:Postgres,MySQL,Adabas,DB2,Oracle與有JDBC驅(qū)動的數(shù)據(jù)庫.它可以顯示表格,視圖并提供一個語法可高亮顯示的SQL編輯器

    com.quantum.feature_3.0.1.bin.dist

    下栽地址:http://sourceforge.net/project/showfiles.php?group_id=7746&package_id=57047

    posted @ 2006-03-30 12:42 只牽這只狗 閱讀(3637) | 評論 (1)編輯 收藏

    2006年3月15日 #

    TMD..........

    posted @ 2006-03-15 16:54 只牽這只狗 閱讀(220) | 評論 (0)編輯 收藏

    2006年1月17日 #

    任何人都可以重構

    使用 Eclipse 自動重構特性的方法與原因

     

     

    未顯示需要 JavaScript 的文檔選項


    對此頁的評價

     


    級別: 初級

    David Gallardo, 獨立軟件顧問和作家

    2003 年 11 月 10 日

    Eclipse 提供了一組強大的自動重構(refactoring)功能,這些功能穿插在其他功能當中,使您能夠重命名 Java元素,移動類和包,從具體的類中創(chuàng)建接口,將嵌套的類變成頂級類,以及從舊方法的代碼片斷中析取出新的方法。您熟悉了 Eclipse 的重構工具之后,就掌握了一種提高生產(chǎn)率的好方法。本文綜覽Eclipse 的重構特性,并通過例子闡明了使用這些特性的方法與原因。

    為什么重構?

    重構是指在不改變程序功能的前提下改變其結構。重構是一項功能強大的技術,但是執(zhí)行起來需要倍加小心才行。主要的危險在于可能在不經(jīng)意中引入一些錯誤,尤其是在進行手工重構的時候更是如此。這種危險引發(fā)了對重構技術的普遍批評:當代碼不會崩潰的時候為什么要修改它呢?

    您需要進行代碼重構的原因可能有以下幾個:傳說中的第一個原因是:需要繼承為某個古老產(chǎn)品而開發(fā)的年代久遠的代碼,或者突然碰到這些代碼。最初的開發(fā)團隊已經(jīng)不在了。我們必須創(chuàng)建增加了新特性的新版本軟件,但是這些代碼已經(jīng)無法理解了。新的開發(fā)隊伍夜以繼日地工作,破譯代碼然后映射代碼,經(jīng)過大量的規(guī)劃與設計之后,人們將這些代碼分割成碎片。歷經(jīng)重重磨難之后,所有這些東西都按照新版本的要求歸位了。這是英雄般的重構故事,幾乎沒有人能在經(jīng)歷了這些之后活著講述這樣的故事。

    還有一種現(xiàn)實一些的情況是項目中加入了新的需求,需要對設計進行修改。至于是因為在最初的規(guī)劃過程中失察,還是由于采用了迭代式的開發(fā)過程(比如敏捷開發(fā),或者是測試驅(qū)動的開發(fā))而在開發(fā)過程中有意引入需求,這兩者并沒有實質(zhì)性的區(qū)別。這樣的重構的規(guī)模要小得多,其內(nèi)容一般涉及通過引入接口或者抽象類來更改類的繼承關系,以及對類進行分割和重新組織,等等。

    重構的最后一個原因是,當存在可用的自動重構工具時,可以有一個用來預先生成代碼的快捷方式——就好比在您無法確定如何拼寫某個單詞的時候,可以用某種拼寫檢查工具輸入這個單詞。比如說,您可以用這種平淡無奇的重構方法生成 getter 和 setter 方法,一旦熟悉了這樣的工具,它就可以為您節(jié)省很多的時間。

    Eclipse 的重構工具無意進行英雄級的重構——適合這種規(guī)模的工具幾乎沒有——但是不論是否用到敏捷開發(fā)技術,Eclipse 的工具對于一般程序員修改代碼的工作都具有無法衡量的價值。畢竟任何復雜的操作只要能夠自動進行,就可以不那么煩悶了。只要您知道 Eclipse 實現(xiàn)了什么樣的重構工具,并理解了它們的適用情況,您的生產(chǎn)力就會得到極大的提高。

    要降低對代碼造成破壞的風險,有兩種重要的方法。第一種方法是對代碼進行一套完全徹底的單元測試:在重構之前和之后都必須通過這樣的測試。第二種方法是使用自動化的工具來進行重構,比如說 Eclipse 的重構特性。

    將徹底的測試與自動化重構結合起來就會更加有效了,這樣重構也就從一種神秘的藝術變成了有用的日常工具。為了增加新的功能或者改進代碼的可維護性,我們可以在不影響原有代碼功能的基礎上迅速且安全地改變其結構。這種能力會對您設計和開發(fā)代碼的方式產(chǎn)生極大的影響,即便是您沒有將其結合到正式的敏捷方法中也沒有關系。



    回頁首


    Eclipse 中重構的類型

    Eclipse 的重構工具可以分為三大類(下面的順序也就是這些工具在 Refactoring 菜單中出現(xiàn)的順序):

    1. 對代碼進行重命名以及改變代碼的物理結構,包括對屬性、變量、類以及接口重新命名,還有移動包和類等。
    2. 改變類一級的代碼邏輯結構,包括將匿名類轉(zhuǎn)變?yōu)榍短最悾瑢⑶短最愞D(zhuǎn)變?yōu)轫敿夘悺⒏鶕?jù)具體的類創(chuàng)建接口,以及從一個類中將方法或者屬性移到子類或者父類中。
    3. 改變一個類內(nèi)部的代碼,包括將局部變量變成類的屬性、將某個方法中選中部分的代碼變成一個獨立的方法、以及為屬性生成 getter 和 setter 方法。

    還有幾個重構工具并不能完全歸入這三個種類,特別是 Change Method Signature,不過在本文中還是將這個工具歸入第三類。除了這種例外情況以外,本文下面幾節(jié)都是按照上面的順序來討論 Eclipse 重構工具的。



    回頁首


    物理重組與重命名

    顯然,您即便沒有特別的工具,也可以在文件系統(tǒng)中重命名文件或者是移動文件,但是如果操作對象是 Java 源代碼文件,您就需要編輯很多文件,更新其中的 import package 語句。與此類似,用某種文本編輯器的搜索與替換功能也可以很容易地給類、方法和變量重新命名,但是這樣做的時候必須十分小心,因為不同的類可能具有名稱相似的方法或者變量;要是從頭到尾檢查項目中所有的文件,來保證每個東西的標識和修改的正確性,那可真夠乏味的。

    Eclipse 的 Rename 和 Move 工具能夠十分聰明地在整個項目中完成這樣的修改,而不需要用戶的干涉。這是因為 Eclipse 可以理解代碼的語義,從而能夠識別出對某個特定方法、變量或者類名稱的引用。簡化這一任務有助于確保方法、變量和類的名稱能夠清晰地指示其用途。

    我們經(jīng)常可以發(fā)現(xiàn)代碼的名字不恰當或者令人容易誤解,這是因為代碼與最初設計的功能有所不同。比方說,某個用來在文件中查找特定單詞的程序也許會擴展為在 Web 頁面中通過 URL 獲取 InputStream 的操作。如果這一輸入流最初叫做 file ,那么就應該修改它的名字,以便能反映其新增的更加一般的特性,比方說 sourceStream 。開發(fā)人員經(jīng)常無法成功地修改這些名稱,因為這個過程是十分混亂和乏味的。這當然也會把下一個不得不對這些類進行操作的開發(fā)人員弄糊涂。

    要對某個 Java 元素進行重命名,只需要簡單地從 Package Explorer 視圖中點擊這個元素,或者從Java 源代碼文件中選中這個元素,然后選擇菜單項 Refactor > Rename。在對話框中輸入新的名稱,然后選擇是否需要 Eclipse 也改變對這個名稱的引用。實際顯示出來的確切內(nèi)容與您所選元素的類型有關。比方說,如果選擇的屬性具有 getter 和 setter 方法,那么也就可以同時更新這些方法的名稱,以反映新的屬性。圖1顯示了一個簡單的例子。

    圖 1. 重命名一個局部變量
    Renaming a local variable

    就像所有的 Eclipse 重構操作一樣,當您指定了全部用來執(zhí)行重構的必要信息之后,您就可以點擊 Preview 按鈕,然后在一個對話框中對比 Eclipse 打算進行哪些變更,您可以分別否決或者確認每一個受到影響的文件中的每一項變更。如果您對于 Eclipse 正確執(zhí)行變更的能力有信心的話,您可以只按下 OK按鈕。顯然,如果您不確定重構到底做了什么事情,您就會想先預覽一下,但是對于 Rename 和 Move 這樣簡單的重構而言,通常沒有必要預覽。

    Move 操作與 Rename 十分相似:您選擇某個 Java 元素(通常是一個類),為其指定一個新位置,并定義是否需要更新引用。然后,您可以選擇 Preview檢查變更情況,或者選擇 OK 立即執(zhí)行重構,如圖2所示。

    圖 2. 將類從一個包移到另一個包
    Moving a class

    在某些平臺上(特別是 Windows),您還可以在 Package Explorer 視圖中通過簡單拖放的方法將類從一個包或者文件夾中移到另一個包或文件夾中。所有的引用都會自動更新。



    回頁首


    重新定義類的關系

    Eclipse 中有大量的重構工具,使您能夠自動改變類的關系。這些重構工具并沒有 Eclipse 提供的其他工具那么常用,但是很有價值,因為它們能夠執(zhí)行非常復雜的任務。可以說,當它們用得上的時候,就會非常有用。

    提升匿名類與嵌套類

    Convert Anonymous Class(轉(zhuǎn)換匿名類)和 Convert Nested Type(轉(zhuǎn)換嵌套類)這兩種重構方法比較相似,它們都將某個類從其當前范圍移動到包含這個類的范圍上。

    匿名類是一種語法速寫標記,使您能夠在需要實現(xiàn)某個抽象類或者接口的地方創(chuàng)建一個類的實例,而不需要顯式提供類的名稱。比如在創(chuàng)建用戶界面中的監(jiān)聽器時,就經(jīng)常用到匿名類。在清單1中,假設 Bag 是在其他地方定義的一個接口,其中聲明了兩個方法, get() set()


    清單 1. Bag 類
     
          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);
       }
    }
    

    當匿名類變得很大,其中的代碼難以閱讀的時候,您就應該考慮將這個匿名類變成嚴格意義上的類;為了保持封裝性(換句話說,就是將它隱藏起來,使得不必知道它的外部類不知道它),您應該將其變成嵌套類,而不是頂級類。您可以在這個匿名類的內(nèi)部點擊,然后選擇 Refactor > Convert Anonymous Class to Nested 就可以了。當出現(xiàn)確認對話框的時候,為這個類輸入名稱,比如 BagImpl ,然后選擇 Preview或者 OK。這樣,代碼就變成了如清單2所示的情形。


    清單 2. 經(jīng)過重構的 Bag 類
     
    
    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);
       }
    }

    當您想讓其他的類使用某個嵌套類時,Convert Nested Type to Top Level 就很有用了。比方說,您可以在一個類中使用值對象,就像上面的 BagImpl 類那樣。如果您后來又決定應該在多個類之間共享這個數(shù)據(jù),那么重構操作就能從這個嵌套類中創(chuàng)建新的類文件。您可以在源代碼文件中高亮選中類名稱(或者在 Outline 視圖中點擊類的名稱),然后選擇 Refactor > Convert Nested Type to Top Level,這樣就實現(xiàn)了重構。

    這種重構要求您為裝入實例提供一個名字。重構工具也會提供建議的名稱,比如 example ,您可以接受這個名字。這個名字的意思過一會兒就清楚了。點擊 OK 之后,外層類 BagExample 就會變成清單3所示的樣子。


    清單 3. 經(jīng)過重構的 Bag 類
    
    public class BagExample
    {
       void processMessage(String msg)
       {
          Bag bag = new BagImpl(this);
          bag.set(msg);
          MessagePipe pipe = new MessagePipe();
          pipe.send(bag);
       }
    }
    

    請注意,當一個類是嵌套類的時候,它可以訪問其外層類的成員。為了保留這種功能,重構過程將一個裝入類 BagExample 的實例放在前面那個嵌套類中。這就是之前要求您輸入名稱的實例變量。同時也創(chuàng)建了用于設置這個實例變量的構造函數(shù)。重構過程創(chuàng)建的新類 BagImpl 如清單4所示。


    清單 4. BagImpl 類
      
    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;
       }
    }
    

    如果您的情況與這個例子相同,不需要保留對 BagExample 的訪問,您也可以很安全地刪除這個實例變量與構造函數(shù),將 BagExample 類中的代碼改成缺省的無參數(shù)構造函數(shù)。

    在類繼承關系內(nèi)移動成員

    還有兩個重構工具,Push Down 和 Pull Up,分別實現(xiàn)將類方法或者屬性從一個類移動到其子類或父類中。假設您有一個名為 Vehicle 的抽象類,其定義如清單5所示。


    清單 5. 抽象的 Vehicle 類
    
    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;
       }
    }
    

    您還有一個 Vehicle 的子類,類名為 Automobile ,如清單6所示。


    清單6. Automobile 類
    
    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;
       }
    }
    

    請注意, Vehicle 有一個屬性是 motor 。如果您知道您將永遠只處理汽車,那么這樣做就好了;但是如果您也允許出現(xiàn)劃艇之類的東西,那么您就需要將 motor 屬性從 Vehicle 類下放到 Automobile 類中。為此,您可以在 Outline 視圖中選擇 motor ,然后選擇 Refactor > Push Down

    Eclipse 還是挺聰明的,它知道您不可能總是單單移動某個屬性本身,因此還提供了 Add Required 按鈕,不過在 Eclipse 2.1 中,這個功能并不總是能正確地工作。您需要驗證一下,看所有依賴于這個屬性的方法是否都推到了下一層。在本例中,這樣的方法有兩個,即與 motor 相伴的 getter 和 setter 方法,如圖3所示。

    圖 3. 加入所需的成員
    Adding required members

    在按過 OK按鈕之后, motor 屬性以及 getMotor() setMotor() 方法就會移動到 Automobile 類中。清單7顯示了在進行了這次重構之后 Automobile 類的情形。


    清單 7. 經(jīng)過重構的 Automobile 類
    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 幾乎相同,當然 Pull Up 是將類成員從一個類中移到其父類中,而不是子類中。如果您稍后改變主意,決定還是把 motor 移回到 Vehicle 類中,那么您也許就會用到這種重構。同樣需要提醒您,一定要確認您是否選擇了所有必需的成員。

    Automobile 類中具有成員 motor,這意味著您如果創(chuàng)建另一個子類,比方說 Bus ,您就還需要將 motor (及其相關方法)加入到 Bus 類中。有一種方法可以表示這種關系,即創(chuàng)建一個名為 Motorized 的接口, AutomobileBus 都實現(xiàn)這個接口,但是 RowBoat 不實現(xiàn)。

    創(chuàng)建 Motorized 接口最簡單的方法是在 Automobile 上使用 Extract Interface 重構。為此,您可以在 Outline 視圖中選擇 Automobile ,然后從菜單中選擇 Refactor > Extract Interface。您可以在彈出的對話框中選擇您希望在接口中包含哪些方法,如圖4所示。

    圖 4. 提取 Motorized 接口
    Motorized interface

    點擊 OK 之后,接口就創(chuàng)建好了,如清單8所示。


    清單 8. Motorized 接口
    
    public interface Motorized
    {
       public abstract String getMotor();
       public abstract void setMotor(String string);
    }
    

    同時, Automobile 的類聲明也變成了下面的樣子:

    
    public class Automobile extends Vehicle implements Motorized
    

    使用父類

    本重構工具類型中最后一個是 User Supertyp Where Possible。想象一個用來管理汽車細帳的應用程序。它自始至終都使用 Automobile 類型的對象。如果您想處理所有類型的交通工具,那么您就可以用這種重構將所有對 Automobile 的引用都變成對 Vehicle 的引用(參看圖5)。如果您在代碼中用 instanceof 操作執(zhí)行了任何類型檢查的話,您將需要決定在這些地方適用的是原先的類還是父類,然后選中第一個選項“Use the selected supertype in 'instanceof' expressions”。

    圖 5. 將 Automobile 改成其父類 Vehicle
    Supertype

    使用父類的需求在 Java 語言中經(jīng)常出現(xiàn),特別是在使用了 Factory Method 模式的情況下。這種模式的典型實現(xiàn)方式是創(chuàng)建一個抽象類,其中具有靜態(tài)方法 create() ,這個方法返回的是實現(xiàn)了這個抽象類的一個具體對象。如果需創(chuàng)建的具體對象的類型依賴于實現(xiàn)的細節(jié),而調(diào)用類對實現(xiàn)細節(jié)并不感興趣的情況下,可以使用這一模式。



    回頁首


    改變類內(nèi)部的代碼

    最大一類重構是實現(xiàn)了類內(nèi)部代碼重組的重構方法。在所有的重構方法中,只有這類方法允許您引入或者移除中間變量,根據(jù)原有方法中的部分代碼創(chuàng)建新方法,以及為屬性創(chuàng)建 getter 和 setter 方法。

    提取與內(nèi)嵌

    有一些重構方法是以 Extract 這個詞開頭的:Extract Method、Extract Local Variable 以及Extract Constants。第一個 Extract Method 的意思您可能已經(jīng)猜到了,它根據(jù)您選中的代碼創(chuàng)建新的方法。我們以清單8中那個類的 main() 方法為例。它首先取得命令行選項的值,如果有以 -D 開頭的選項,就將其以名-值對的形式存儲在一個 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...
       }
    }
    

    將一部分代碼從一個方法中取出并放進另一個方法中的原因主要有兩種。第一種原因是這個方法太長,并且完成了兩個以上邏輯上截然不同的操作。(我們不知道上面那個 main() 方法還要處理哪些東西,但是從現(xiàn)在掌握的證據(jù)來看,這不是從其中提取出一個方法的理由。)另一種原因是有一段邏輯上清晰的代碼,這段代碼可以被其他方法重用。比方說在某些時候,您發(fā)現(xiàn)自己在很多不同的方法中都重復編寫了相同的幾行代碼。那就有可能是需要重構的原因了,不過除非真的需要重用這部分代碼,否則您很可能并不會執(zhí)行重構。

    假設您還需要在另外一個地方解析名-值對,并將其放在 Properties 對象中,那么您可以將包含 StringTokenizer 聲明和下面的 if 語句的這段代碼抽取出來。為此,您可以高亮選中這段代碼,然后從菜單中選擇 Refactor > Extract Method。您需要輸入方法名稱,這里輸入 addProperty ,然后驗證這個方法的兩個參數(shù), Properties prop Strings 。清單9顯示由 Eclipse 提取了 addProp() 方法之后類的情況。


    清單 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 重構取出一段被直接使用的表達式,然后將這個表達式首先賦值給一個局部變量。然后在原先使用那個表達式的地方使用這個變量。比方說,在上面的方法中,您可以高亮選中對 st.nextToken() 的第一次調(diào)用,然后選擇 Refactor > Extract Local Variable。您將被提示輸入一個變量名稱,這里輸入 key 。請注意,這里有一個將被選中表達式所有出現(xiàn)的地方都替換成新變量的引用的選項。這個選項通常是適用的,但是對這里的 nextToken() 方法不適用,因為這個方法(顯然)在每一次調(diào)用的時候都返回不同的值。確認這個選項未被選中。參見圖6。

    圖 6. 不全部替換所選的表達式
    Extract variable

    接下來,在第二次調(diào)用 st.nextToken() 的地方重復進行重構,這一次調(diào)用的是一個新的局部變量 value 。清單10顯示了這兩次重構之后代碼的情形。


    清單 10. 重構之后的代碼
    
    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);
          }
       }
    

    用這種方式引入變量有幾點好處。首先,通過為表達式提供有意義的名稱,可以使得代碼執(zhí)行的任務更加清晰。第二,代碼調(diào)試變得更容易,因為我們可以很容易地檢查表達式返回的值。最后,在可以用一個變量替換同一表達式的多個實例的情況下,效率將大大提高。

    Extract Constant 與 Extract Local Variable 相似,但是您必須選擇靜態(tài)常量表達式,重構工具將會把它轉(zhuǎn)換成靜態(tài)的 final 常量。這在將硬編碼的數(shù)字和字符串從代碼中去除的時候非常有用。比方說,在上面的代碼中我們用“-D”這一命令行選項來定義名-值對。先將“-D”高亮選中,選擇 Refactor > Extract Constant,然后輸入 DEFINE 作為常量的名稱。重構之后的代碼如清單11所示:


    清單 11. 重構之后的代碼
    
    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);
             }
          }
       }
       // ...
    

    對于每一種 Extract... 類的重構,都存在對應的 Inline... 重構,執(zhí)行與之相反的操作。比方說,如果您高亮選中上面代碼中的變量 s,選擇 Refactor > Inline...,然后點擊 OK,Eclipse 就會在調(diào)用 addProp() 的時候直接使用 args[i].substring(2) 這個表達式,如下所示:

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

    這樣比使用臨時變量效率更高,代碼也變得更加簡要,至于這樣的代碼是易讀還是含混,就取決于您的觀點了。不過一般說來,這樣的內(nèi)嵌重構沒什么值得推薦的地方。

    您可以按照用內(nèi)嵌表達式替換變量的相同方法,高亮選中方法名,或者靜態(tài) final 常量,然后從菜單中選擇 Refactor > Inline...,Eclipse 就會用方法的代碼替換方法調(diào)用,或者用常量的值替換對常量的引用。

    封裝屬性

    通常我們認為將對象的內(nèi)部結構暴露出來是一種不好的做法。這也正是 Vehicle 類及其子類都具有 private 或者 protected 屬性,而用 public setter 和 getter 方法來訪問屬性的原因。這些方法可以用兩種不同的方式自動生成。

    第一種生成這些方法的方式是使用 Source > Generate Getter and Setter 菜單。這將會顯示一個對話框,其中包含所有尚未存在的 getter 和 setter 方法。不過因為這種方式?jīng)]有用新方法更新對這些屬性的引用,所以并不算是重構;必要的時候,您必須自己完成更新引用的工作。這種方式可以節(jié)約很多時間,但是最好是在一開始創(chuàng)建類的時候,或者是向類中加入新屬性的時候使用,因為這些時候還不存在對屬性的引用,所以不需要再修改其他代碼。

    第二種生成 getter 和 setter 方法的方式是選中某個屬性,然后從菜單中選擇 Refactor > Encapsulate Field。這種方式一次只能為一個屬性生成 getter 和 setter 方法,不過它與 Source > Generate Getter and Setter 相反,可以將對這個屬性的引用改變成對新方法的調(diào)用。

    例如,我們可以先創(chuàng)建一個新的簡版 Automobile 類,如清單12所示。


    清單 12. 簡單的 Automobile 類
    
    public class Automobile extends Vehicle
    {
       public String make;
       public String model;
    }
    

    接下來,創(chuàng)建一個類實例化了 Automobile 的類,并直接訪問 make 屬性,如清單13所示。


    清單 13. 實例化 Automobile
    
    public class AutomobileTest
    {
       public void race()
       {
          Automobilecar1 = new Automobile();
          car1.make= "Austin Healy";
          car1.model= "Sprite";
          // ...
       }
    }

    現(xiàn)在封裝 make 屬性。先高亮選中屬性名稱,然后選擇 Refactor > Encapsulate Field。在彈出的對話框中輸入 getter 和 setter 方法的名稱——如您所料,缺省的方法名稱分別是 getMake() 和 setMake()。您也可以選擇與這個屬性處在同一個類中的方法是繼續(xù)直接訪問該屬性,還是像其他類那樣改用這些訪問方法。(有一些人非常傾向于使用這兩種方式的某一種,不過碰巧在這種情況下您選擇哪一種方式都沒有區(qū)別,因為 Automobile 中沒有對 make 屬性的引用。)

    圖7. 封裝屬性
    Encapsulating a field

    點擊 OK之后, Automobile 類中的 make 屬性就變成了私有屬性,也同時具有了 getMake() setMake() 方法。

    >
    清單 14. 經(jīng)過重構的 Automobile 類
    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 類也要進行更新,以便使用新的訪問方法,如清單15所示。


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

    改變方法的簽名

    本文介紹的最后一個重構方法也是最難以使用的方法:Change Method Signature(改變方法的簽名)。這種方法的功能顯而易見——改變方法的參數(shù)、可見性以及返回值的類型。而進行這樣的改變對于調(diào)用這個方法的其他方法或者代碼會產(chǎn)生什么影響,就不是那么顯而易見了。這么也沒有什么魔方。如果代碼的改變在被重構的方法內(nèi)部引發(fā)了問題——變量未定義,或者類型不匹配——重構操作將對這些問題進行標記。您可以選擇是接受重構,稍后改正這些問題,還是取消重構。如果這種重構在其他的方法中引發(fā)問題,就直接忽略這些問題,您必須在重構之后親自修改。

    為澄清這一點,考慮清單16中列出的類和方法。


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

    上面這個類中的 test() 方法被另一個類中的方法調(diào)用,如清單17所示。


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

    在第一個類中高亮選中 test ,然后選擇 Refactor > Change Method Signature。您將看到如圖8所示的對話框。

    圖 8. Change Method Signature 選項
    Change Method Signature options

    第一個選項是改變該方法的可見性。在本例中,將其改變?yōu)?protected 或者 private,這樣第二個類的 callTest() 方法就不能訪問這個方法了。(如果這兩個類在不同的包中,將訪問方法設為缺省值也會引起這樣的問題。) Eclipse 在進行重構的時候不會將這些問題標出,您只有自己選擇適當?shù)闹怠?

    下面一個選項是改變返回值類型。如果將返回值改為 float ,這不會被標記成錯誤,因為 test() 方法返回語句中的 int 會自動轉(zhuǎn)換成 float 。即便如此,在第二個類的 callTest() 方法中也會引起問題,因為 float 不能轉(zhuǎn)換成 int 。您需要將 test() 的返回值改為 int ,或者是將 callTest() 中的 r 改為 float

    如果將第一個參數(shù)的類型從 String 變成 int ,那么也得考慮相同的問題。在重構的過程中這些問題將會被標出,因為它們會在被重構的方法內(nèi)部引起問題: int 不具有方法 length() 。然而如果將其變成 StringBuffer ,問題就不會標記出來,因為 StringBuffer 的確具有方法 length() 。當然這會在 callTest() 方法中引起問題,因為它在調(diào)用 test() 的時候還是把一個 String 傳遞進去了。

    前面提到過,在重構引發(fā)了問題的情況下,不管問題是否被標出,您都可以一個一個地修正這些問題,以繼續(xù)下去。還有一種方法,就是先行修改這些錯誤。如果您打算刪除不再需要的參數(shù) i ,那么可以先從要進行重構的方法中刪除對它的引用。這樣刪除參數(shù)的過程就更加順利了。

    最后一件需要解釋的事情是 Default Value 選項。這一選項值僅適用于將參數(shù)加入方法簽名中的情況。比方說,如果我們加入了一個類型為 String 的參數(shù),參數(shù)名為 n ,其缺省值為 world ,那么在 callTest() 方法中調(diào)用 test() 的代碼就變成下面的樣子:

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

    在這場有關 Change Method Signature 重構的看似可怕的討論中,我們并沒有隱藏其中的問題,但卻一直沒有提到,這種重構其實是非常強大的工具,它可以節(jié)約很多時間,通常您必須進行仔細的計劃才能成功地使用它。



    回頁首


    結束語

    Eclipse 提供的工具使重構變得簡單,熟悉這些工具將有助于您提高效率。敏捷開發(fā)方法采用迭代方式增加程序特性,因此需要依賴于重構技術來改變和擴展程序的設計。但即便您并沒有使用要求進行正式重構的方法,Eclipse 的重構工具還是可以在進行一般的代碼修改時提供節(jié)約時間的方法。如果您花些時間熟悉這些工具,那么當出現(xiàn)可以利用它們的情況時,您就能意識到所花費的時間是值得的。



    回頁首


    參考資料

    • 您可以參閱本文在 developerWorks 全球站點上的 英文原文.

    • 有關重構的核心著作是 Refactoring: Improving the Design of Existing Code, 作者 Martin Fowler、Kent Beck、John Brant、William Opdyke 和 Don Roberts(Addison-Wesley,1999年)。

    • 重構是一種正在發(fā)展的方法,在 Eclipse In Action: A Guide for Java Developers (Manning, 2003年)一書中,作者 David Gallardo,Ed Burnette 以及 Robert McGovern 從在 Eclipse 中設計和開發(fā)項目的角度討論了這一話題。

    • 模式(如本文中提到的 Factory Method 模式)是理解和討論面向?qū)ο笤O計的重要工具。這方面的經(jīng)典著作是 Design Patterns: Elements of Reusable Object-Oriented Software,作者為 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides (Addison-Wesley,1995年)。

    • Design Patterns 中的例子是用 C++ 寫成的,這對于 Java 程序員是不小的障礙;Mark Grand 所著的 Patterns in Java, Volume One: A Catalog of Reusable Design Patterns Illustrated with UML(Wiley,1998年)將模式翻譯成了 Java 語言。

    • 有關敏捷編程的一個變種,請參看 Kent Beck 所著的 Extreme Programming Explained: Embrace Change(Addison-Wesley,1999年)
    Web 站點 developerWorks 上的文章與教程

    回頁首


    關于作者

    David Gallardo 是 Studio B 上的一名作家,他是一名獨立軟件顧問和作家,專長為軟件國際化、Java Web 應用程序和數(shù)據(jù)庫開發(fā)。他成為專業(yè)軟件工程師已經(jīng)有十五年了,他擁有許多操作系統(tǒng)、編程語言和網(wǎng)絡協(xié)議的經(jīng)驗。他最近在一家 BtoB 電子商務公司 TradeAccess, Inc 領導數(shù)據(jù)庫和國際化開發(fā)。在這之前,他是 Lotus Development Corporation 的 International Product Development 組中的高級工程師,負責為 Lotus 產(chǎn)品(包括 Domino)提供 Unicode 和國際語言支持的跨平臺庫的開發(fā)。David 是 Eclipse In Action: A Guide for Java Developers(2003年)一書的合著者。可以通過 david@gallardo.org 與 David 聯(lián)系。

    posted @ 2006-01-17 15:28 只牽這只狗 閱讀(333) | 評論 (0)編輯 收藏

    2006年1月10日 #

    原來自己的生日已經(jīng)過了......不知不覺的過了...........
    posted @ 2006-01-10 09:29 只牽這只狗 閱讀(200) | 評論 (0)編輯 收藏

    男人25歲前不會明白的道理

        

      1、男人是社會的主體,不管你信或不信。所以男人應該有種責任感。
       
      2、25歲之前,請記得,愛情通常是假的,或者不是你所想象的那樣純潔和永遠。如果你過了25歲,那么你應該懂得這個道理。
       
      3、吃飯7成飽最舒服。對待女友最多也請你保持在7成。
       
      4、30歲之前請愛惜自己的身體,前30年你找病,后30年病找你。如果你過了30歲,你自然也會懂得這個道理。
       
      5、事業(yè)遠比愛情重要。如果說事業(yè)都不能永恒,那么愛情只能算是曇花一現(xiàn)。
       
      6、不要輕易接受追求你的女孩。女追男隔層紗,如果你很容易就陷進去,你會發(fā)現(xiàn)你會錯過很多東西,失去很多東西。
       
      7、請你相信,能用錢解決的問題,都不是問題。如果你認為錢索王道,有錢有女人,沒錢沒女人,那么,女人不是問題。
       
      8、請永遠積極向上。每個男人都有他可愛的地方,但是不可愛的地方只有:不積極面對生活。
       
      9、不要連續(xù)2次讓同一個女人受到傷害。好馬不吃回頭草是有道理的。如果認真考慮過該分手,那么請不要做任何舍不得的行動。
       
      10、如果你和你前女友能做朋友,那么你要問自己:為什么?如果分手后還是朋友,那么只有2個可能:你們當初都只是玩玩而已,沒付出彼此最真的感情;或者:必定有個人是在默默的付出無怨無悔!
       
      11、永遠不要太相信女人在戀愛時的甜言蜜語。都說女人愛聽甜言蜜語,其實,男人更喜歡。
       
      12、請不要為自己的相貌或者身高過分擔心和自卑。人是動物,但是區(qū)別于動物。先天條件并不是阻擋你好好生活的借口。人的心靈遠勝于相貌,請相信這點。如果有人以相貌取人,那么你也沒必要太在意。因為他從某種意義來講,只是只動物,你會跟動物慪氣嗎?
       
      13、失戀時,只有2種可能,要么你愛她她不愛你,或者相反。那么,當你愛的人不再愛你,或者從來沒愛過你時,你沒有遺憾,因為你失去的只是一個不愛你的人。
       
      14、請不要欺騙善良的女孩。這個世界上善良的女孩太少。
       
      15、不能偏激的認為金錢萬能,至少,金錢治不好艾滋病。
       
      16、請一定要有自信。你就是一道風景,沒必要在別人風景里面仰視。
       
      17、受到再大的打擊,只要生命還在,請相信每天的太陽都是新的。
       
      18、愛情永遠不可能是天平。你想在愛情里幸福就要舍得傷心。
       
      19、如果你喜歡一個她認為別人應該對她好的MM,請盡早放棄。沒有人是應該對一個人好的。如果她不明白這個道理,也就是她根本不懂得珍惜。
       
      20、不要因為寂寞而“找”GF,寂寞的男人請要學會品味寂寞。請記住:即使寂寞,遠方黑暗的夜空下,一定有人和你一樣,寂寞的人不同,仰望的星空卻是唯一。
       
      21、任何事沒有永遠,也別問怎樣才能永遠。生活有很多無奈,請盡量充實自己,充實生活。請善待生活。
       
      End、男人有很多無奈,生活很累,但是因為生活才有意義。當你以為你一無所有時,你至少還有時間,時間能撫平一切創(chuàng)傷。所以請不要流淚。

    posted @ 2006-01-10 09:12 只牽這只狗 閱讀(234) | 評論 (0)編輯 收藏

    也許明天會更好.......

    posted @ 2006-01-10 08:51 只牽這只狗 閱讀(218) | 評論 (0)編輯 收藏

    2006年1月4日 #

    摘要:

    雖然大部分開發(fā)人員在過去使用過XMLHttp或者使用Iframe來加載數(shù)據(jù),但僅到現(xiàn)在我們才看到傳統(tǒng)的開發(fā)人員和公司開始采用這些技術。就像新的編程語言或模型伴隨著更多的痛苦,開發(fā)人員需要學習新的技巧及如何最好利用這些新技術。這篇文章講述了開發(fā)人員使用AJAX需要使用的工具和技術。

    文章工具

    作者:Andrew Thompson;xMatrix (他的blog:http://blog.matrix.org.cn/page/xMatrix)
    原文地址:http://www.javaworld.com/javaworld/jw-10-2005/jw-1017-ajax.html
    中文地址:http://www.matrix.org.cn/resource/article/44/44116_AJAX.html
    關鍵詞: AJAX

    AJAX開發(fā)者的最新工具和技術

    基于XML的異步JavaScript,簡稱AJAX,是當前Web創(chuàng)新(稱為Web2.0)中的一個王冠。感謝組成AJAX的各種技術,Web應用的交互如Flickr, Backpack和Google在這方面已經(jīng)有質(zhì)的飛躍。這個術語源自描述從基于網(wǎng)頁的Web應用到基于數(shù)據(jù)的應用的轉(zhuǎn)換。在基于數(shù)據(jù)的應用中,用戶需求的數(shù)據(jù)如聯(lián)系人列表,可以從獨立于實際網(wǎng)頁的服務端取得并且可以被動態(tài)地寫入網(wǎng)頁中,給緩慢的Web應用體驗著色使之像桌面應用一樣。

    雖然大部分開發(fā)人員在過去使用過XMLHttp或者使用Iframe來加載數(shù)據(jù),但僅到現(xiàn)在我們才看到傳統(tǒng)的開發(fā)人員和公司開始采用這些技術。就像新的編程語言或模型伴隨著更多的痛苦,開發(fā)人員需要學習新的技巧及如何最好利用這些新技術。這篇文章講述了開發(fā)人員使用AJAX枰褂玫墓ぞ吆圖際酢?lt;br />
    AJAX模式
    許多重要的技術和AJAX開發(fā)模式可以從現(xiàn)有的知識中獲取。例如,在一個發(fā)送請求到服務端的應用中,必須包含請求順序、優(yōu)先級、超時響應、錯誤處理及回調(diào),其中許多元素已經(jīng)在Web服務中包含了,就像現(xiàn)在的SOA。AJAX開發(fā)人員擁有一個完整的系統(tǒng)架構知識。同時,隨著技術的成熟還會有許多地方需要改進,特別是UI部分的易用性。

    AJAX開發(fā)與傳統(tǒng)的CS開發(fā)有很大的不同。這些不同引入了新的編程問題,最大的問題在于易用性。由于AJAX依賴瀏覽器的JavaScript和XML,瀏覽器的兼容性和支持的標準也變得和JavaScript的運行時性能一樣重要了。這些問題中的大部分來源于瀏覽器、服務器和技術的組合,因此必須理解如何才能最好的使用這些技術。

    綜合各種變化的技術和強耦合的客戶服務端環(huán)境,AJAX提出了一種新的開發(fā)方式。AJAX開發(fā)人員必須理解傳統(tǒng)的MVC架構,這限制了應用層次之間的邊界。同時,開發(fā)人員還需要考慮CS環(huán)境的外部和使用AJAX技術來重定型MVC邊界。最重要的是,AJAX開發(fā)人員必須禁止以頁面集合的方式來考慮Web應用而需要將其認為是單個頁面。一旦UI設計與服務架構之間的范圍被嚴格區(qū)分開來后,開發(fā)人員就需要更新和變化的技術集合了。


    時刻想著用戶
    AJAX的最大機遇在于用戶體驗。在使應用更快響應和創(chuàng)新的過程中,定義Web應用的規(guī)則正在被重寫;因此開發(fā)人員必須更注重用戶。現(xiàn)在用戶已經(jīng)逐漸習慣如何使用Web應用了。例如用戶通常希望每一次按鈕點擊會導致幾秒的延遲和屏幕刷新,但AJAX正在打破這種長時間的狀況。因此用戶需要重新體驗按鈕點擊的響應了。

    可用性是AJAX另人激動的地方而且已經(jīng)產(chǎn)生了幾種新穎的技術。其中最引人注目的是一種稱為“黃色隱出”的技術,他在數(shù)據(jù)更新之前時將用戶界面變?yōu)辄S色,更新完成后立刻恢復原來的顏色。AJAX開發(fā)人員將用戶從Web應用的負載中解放出來;小心地利用AJAX提供的豐富接口,不久桌面開發(fā)人員會發(fā)現(xiàn)AJAX是他們的方向。


    幾種工具和技術
    隨著AJAX迅速地引人注目起來,我想開發(fā)人員對這種技術的期待也迅速地增加。就像任何新技術,AJAX的興旺也需要一整個開發(fā)工具/編程語言及相關技術系統(tǒng)來支撐。

    JavaScript
    如名字所示AJAX的概念中最重要而最被忽視的是他也是一種JavaScript編程語言。JavaScript是一種粘合劑使AJAX應用的各部分集成在一起。在大部分時間,JavaScript通常被服務端開發(fā)人員認為是一種企業(yè)級應用不需要使用的東西應該盡力避免。這種觀點來來自以前編寫JavaScript代碼的經(jīng)歷:繁雜而又易出錯的語言。類似的,他也被認為將應用邏輯任意地散布在服務端和客戶端中,這使得問題很難被發(fā)現(xiàn)而且代碼很難重用。在AJAX中JavaScript主要被用來傳遞用戶界面上的數(shù)據(jù)到服務端并返回結果。XMLHttpRequest對象用來響應通過HTTP傳遞的數(shù)據(jù),一旦數(shù)據(jù)返回到客戶端就可以立刻使用DOM將數(shù)據(jù)放到網(wǎng)面上。

    XMLHttpRequest
    XMLHttpRequest對象在大部分瀏覽器上已經(jīng)實現(xiàn)而且擁有一個簡單的接口允許數(shù)據(jù)從客戶端傳遞到服務端,但并不會打斷用戶當前的操作。使用XMLHttpRequest傳送的數(shù)據(jù)可以是任何格式,雖然從名字上建議是XML格式的數(shù)據(jù)。

    開發(fā)人員應該已經(jīng)熟悉了許多其他XML相關的技術。XPath可以訪問XML文檔中的數(shù)據(jù),但理解XML DOM是必須的。類似的,XSLT是最簡單而快速的從XML數(shù)據(jù)生成HTML或XML的方式。許多開發(fā)人員已經(jīng)熟悉Xpath和XSLT,因此AJAX選擇XML作為數(shù)據(jù)交換格式有意義的。XSLT可以被用在客戶端和服務端,他能夠減少大量的用JavaScript編寫的應用邏輯。

    CSS
    為了正確的瀏覽AJAX應用,CSS是一種AJAX開發(fā)人員所需要的重要武器。CSS提供了從內(nèi)容中分離應用樣式和設計的機制。雖然CSS在AJAX應用中扮演至關重要的角色,但他也是構建創(chuàng)建跨瀏覽器應用的一大阻礙,因為不同的瀏覽器廠商支持各種不同的CSS級別。

    服務器端
    但不像在客戶端,在服務端AJAX應用還是使用建立在如Java,.Net和PHP語言基礎上機制;并沒有改變這個領域中的主要方式。
    既然如此,我們對Ruby on Rails框架的興趣也就迅速增加了。在一年多前,Ruby on Rails已經(jīng)吸引了大量開發(fā)人員基于其強大功能來構建Web和AJAX應用。雖然目前還有很多快速應用開發(fā)工具存在,Ruby on Rails看起來已經(jīng)儲備了簡化構建AJAX應用的能力。

    開發(fā)工具
    在實際構建AJAX應用中,你需要的不只是文本編輯器。既然是JavaScript非編譯的,他可以容易地編寫和運行在瀏覽器中;然而,許多工具提供了有用的擴展如語法高亮和智能完成。

    不同的IDE提供了對JavaScript支持的不同等級。來自JetBrains的IntelliJ IDEA是一個用來JavaScript開發(fā)的更好的IDE,雖然許多開發(fā)人員也喜歡Microsoft’s Visual Studio產(chǎn)品(允諾會在最新的版本中改善對AJAX的支持)。Eclipse包含了兩個免費的JavaScript編輯器插件和一個商業(yè)的來自ActiveStat的Komodo IDE。

    另一個JavaScript和AJAX開發(fā)中的問題是調(diào)試困難。不同的瀏覽器提供不同的通常是隱藏的運行時錯誤信息,而JavaScript的缺陷如雙重變量賦值(通常是由于缺少數(shù)據(jù)類型)使得調(diào)試更加困難。在AJAX的開發(fā)中,調(diào)試就更復雜了,因為其需要標識究竟是客戶端還是服務端產(chǎn)生的錯誤。在過去,JavaScript調(diào)試的方法是刪除所有代碼然后一行行的增加直到錯誤出現(xiàn)。現(xiàn)在,更多開發(fā)人員回到為IE準備的Microsoft Script Debugger和為Mozilla瀏覽器準備的Venkman。


    瀏覽器兼容性
    JavaScript編程的最大問題來自不同的瀏覽器對各種技術和標準的支持。構建一個運行在不同瀏覽器(如IE和火狐)是一個困難的任務。因此幾種AJAX JavaScript框架或者生成基于服務端邏輯或標記庫的JavaScript,或者提供符合跨瀏覽器AJAX開發(fā)的客戶端JavaScript庫。一些流行的框架包括:AJAX.Net, Backbase, Bitkraft, Django, DOJO, DWR, MochiKit, Prototype, Rico, Sajax, Sarissa, and Script.aculo.us.

    這些框架給開發(fā)人員更多的空間使得他們不需要擔心跨瀏覽器的問題。雖然這些框架提升了開發(fā)人員構建應用的能力,但由于廠商已經(jīng)開發(fā)了更細節(jié)的用戶界面的打包組件解決方案,因此在AJAX組件市場中需要考慮一些其他因素。例如提供通用用戶界面的組件如組合框和數(shù)據(jù)柵格的幾個廠商,都可以被用來在應用中創(chuàng)建良好的通過類似電子數(shù)據(jù)表方式來查看和編輯數(shù)據(jù)的體驗。但這些組件不僅是封裝了組件的用戶界面而且包括與服務端數(shù)據(jù)的通訊方式,這些組件通常使用基于標記方式來實現(xiàn)如ASP.Net或JSF控件。


    展望
    最近IE和火狐之間的瀏覽器之爭變得火熱起來,因此AJAX開發(fā)人員需要足夠敏捷的作出反應。關鍵點在一些問題如CSS或XML,雖然各種瀏覽器形成采用最新標準的不同陣營(如Mozilla擁抱SVG和E4X標準及在最新火狐BETA版本中使用XUL,而微軟使用自己的XAML技術)。所有這些技術代表當前AJAX主流JavaScript和XML的市場方向改變。
    總的來說,AJAX開發(fā)人員必須盡快地跟進最新的技術并利用高產(chǎn)的工具集。成功的AJAX開發(fā)人員還需要留心他們的使用者以避免將任何問題擴大化。并且AJAX開發(fā)人員還需要持續(xù)地創(chuàng)新來創(chuàng)建增強Web應用易用性的新方法。


    作者
    Dave Johnson是加拿大Vancouver一家軟件咨詢公司eBusiness Applications創(chuàng)始人和傳道者,擁有七年以上的XML相關工作經(jīng)驗。


    Resources
    ? AJAX開發(fā)人員的編譯模式:http://www.ajaxpatterns.org
    ?  XMLHttpRequest教程:“動態(tài)網(wǎng)頁接口”:http://www.xml.com/pub/a/2005/02/09/xml-http-request.html
    ? JavaScript性能基準:http://blogs.ebusiness-apps.com/dave/?p=14
    ? AJAX資源:http://www.ajaxmatters.com
    ? JavaScript規(guī)范:http://www.ecma-international.org/publications/standards/Ecma-262.htm
    ? 介紹JavaScript對象標識:http://www.crockford.com/JSON/index.html
    ?  Mozilla 的Venkman JavaScript調(diào)試器:http://www.mozilla.org/projects/venkman/
    ?  XML DOM參考:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/
    xmlsdk/html/e9da2722-7879-4e48-869c-7f16714e2824.asp
    ? Microsoft Dynamic HTML reference: http://msdn.microsoft.com/library/default.asp?url=/
    workshop/author/dhtml/reference/dhtml_reference_entry.asp
    ? Gecko DOM Reference: http://www.mozilla.org/docs/dom/domref/
    ? "“移植IE應用到Mozilla”
    http://www-128.ibm.com/developerworks/web/library/wa-ie2mozgd/
    ? Mozilla XUL reference:
    http://www.xulplanet.com/
    ? Microsoft XAML reference:
    http://windowssdk.msdn.microsoft.com/library/default.asp?url=/library/
    en-us/wcp_conceptual/html/0ff5f36e-dd84-44d1-aa3e-5bb4f147b169.asp?frame=true
    ? James Jesses Garret introduced the term AJAX in his article "AJAX: A New Approach to Web Applications," (Adaptive Path, February 2005): “AJAX:新的網(wǎng)頁應用開發(fā)方式”
    http://www.adaptivepath.com/publications/essays/archives/000385.php
    ? JetBrains IntelliJ IDEA:
    http://www.jetbrains.com/
    ? Microsoft Visual Studio:
    http://msdn.microsoft.com/vstudio/
    ? JSEditor:
    http://jseditor.sourceforge.net/
    ? JSEclipse:
    http://www.interaktonline.com/Products/Eclipse/JSEclipse/Overview/
    ? ActiveState Komodo:
    http://www.activestate.com/Products/Komodo/
    ? XHTML:
    http://www.w3.org/TR/xhtml1/
    ? Document Object Model:
    http://www.w3.org/DOM/
    ? Cascading Style Sheets:
    http://www.w3.org/Style/CSS/
    ? Extensible Stylesheet Language:
    http://www.w3.org/Style/XSL/
    ? XForms:
    http://www.w3.org/MarkUp/Forms/
    ? Scaling Vector Graphics:
    http://www.w3.org/Graphics/SVG/
    ? XPath:
    http://www.w3.org/TR/xpath
    ? AJAX.Net:
    http://ajax.schwarz-interactive.de/csharpsample/default.aspx
    ? Backbase:
    http://www.backbase.com
    ? Bitkraft:
    http://www.tiggrbitz.com/
    ? Django:
    http://www.djangoproject.com/
    ? Dojo:
    http://www.dojotoolkit.org/
    ? DWR (Direct Web Reporting):
    http://getahead.ltd.uk/dwr/
    ? MochiKit:
    http://mochikit.com/
    ? Prototype:
    http://prototype.conio.net/
    ? Rico:
    http://openrico.org/rico/home.page
    ? Sajax:
    http://www.modernmethod.com/sajax/
    ? Sarissa:
    http://sarissa.sourceforge.net/doc/
    ? Script.aculo.us:
    http://script.aculo.us/
    ? Ruby on Rails:
    http://www.rubyonrails.org/
    ? For more on AJAX and DWR, read "AJAX Made Simple with DWR," Cloves Carneiro Jr. (JavaWorld, June 2005): 關于AJAX和DWR,請閱讀“AJAX使用DWR更簡單”
    http://www.javaworld.com/javaworld/jw-06-2005/jw-0620-dwr.html
    ? For more articles on Java development tools, browse the Development Tools section of JavaWorld’s Topical Index: 更多Java開發(fā)工具的文章,請瀏覽JavaWorld的開發(fā)工具部分索引頁
    http://www.javaworld.com/channel_content/jw-tools-index.shtml
    ? For more articles on XML, browse the Java and XML section of JavaWorld’s Topical Index: 更多XML的文章,請瀏覽JavaWorld的Java和XML部分索引頁
    http://www.javaworld.com/channel_content/jw-xml-index.shtml
    ? For more articles on UI design, browse the User Interface Design section of JavaWorld’s Topical Index: 更多UI設計的文章,請瀏覽JavaWorld的UI設計部分索引頁
    http://www.javaworld.com/channel_content/jw-ui-index.shtml


    原文地址:
    posted @ 2006-01-04 10:53 只牽這只狗 閱讀(209) | 評論 (0)編輯 收藏

    2005年12月30日 #

    2.3 業(yè)務邏輯層設計

      2.3.1 動態(tài)加載技術

      如果一次性獲取完整的先序樹,構造成xml提供給JavaScript解析,數(shù)據(jù)量越大,消耗的資源越多,客戶端響應延遲時間就越長,因此對于大數(shù)據(jù)量的樹,采用動態(tài)加載方式,即每次單擊“+”圖片時,判斷是否已加載子節(jié)點數(shù)據(jù),如果未加載則通過Ajax的XMLHTTP組件XMLHTTPRequest對象異步發(fā)送請求,連接服務器執(zhí)行SQL 語句“select * from tree_class where parent = ?order by classcode ”獲取節(jié)點數(shù)據(jù)。相關JavaScript 代碼如下:

    /*判斷是否已經(jīng)加載數(shù)據(jù),未加載則訪問服務器加載數(shù)據(jù)*/

    dhtmlTree.prototype.Loading=function(pObject){
     if(((pObject.XMLload==0)&&(this.XMLsource))&&(!this.XMLloading)){
      pObject.XMLload=1;
      this.loadXML(this.XMLsource+getUrlSymbol(this.XMLsource)+"id="+escape(pObject.id));
     }
    }
    dtmlXMLObject.prototype.loadXML=function(url){//加載數(shù)據(jù)
     try {
      this.xmlDoc = new XMLHttpRequest();
      /*通過GET方法異步連接到 url 加載數(shù)據(jù)*/
      this.xmlDoc.open("GET", url,true);//true:異步;false:同步
      this.xmlDoc.send(null);
     } catch(e){
      this.xmlDoc = new ActiveXObject("Microsoft.XMLHTTP");//使用IE
      this.xmlDoc.open("GET", url,true);//true:異步;false:同步
      this.xmlDoc.send(null);
     }
     return this.xmlDoc.responseXML;
    }

      每次只取同一個父節(jié)點ParentId的子節(jié)點序列,按XML格式封裝成樹的文檔結構,例如:

    <tree id="0">
    <leaf child=”1" name="國防科技大學" id="1" im0="leaf.gif" im1="folderOpen.gif" im2=" folderClosed.gif"/>
    </tree>

      提供給JavaScript的dhtmlTreeObject.prototype.insertItem()解析并組織好html輸出節(jié)點;其中 child:1表示有子節(jié)點,0表示沒有子節(jié)點;im0表示沒有子節(jié)點時的圖標;im1表示有子節(jié)點并且打開節(jié)點時的圖標;im2表示有子節(jié)點并且關閉時的圖標;所以還可以在構造XML時自定義圖標。

      2.3.2 樹型結構的構造

      從數(shù)據(jù)庫中返回的是有序的先序樹,而XML是完整的樹型結構文檔,所以將樹型數(shù)據(jù)構造成預定義的XML格式,只需從根節(jié)點開始,遍歷一遍樹,即可將樹全部生成。相關JavaScript代碼如下:

    /*動態(tài)加載樹的構造方法*/

    dtmlXMLObject.prototype.constructTree=function(){

    //采用動態(tài)加載時獲取的xml數(shù)據(jù),解析樹型數(shù)據(jù)

    var node=this.XMLLoader.getXMLTopNode("tree");

    var parentId=node.getAttribute("id");

    for(var i=0;i<node.childNodes.length;i++) { //逐個解析xml文件的leaf節(jié)點

     if((node.childNodes[i].nodeType==1)&&(node.childNodes[i].tagName == "leaf")){
      var name=node.childNodes[i].getAttribute("text");
      …………
      var temp=dhtmlObject.a0Find(parentId);//獲取父節(jié)點對象
      temp.XMLload=1;//已加載
      //構造html輸出節(jié)點
      dhtmlObject.insertItem(parentId,cId,name,im0,im1,im2,chd);
      dhtmlObject.addDragger = this;//設置可拖放的對象
     };
    }

      2.3.3 樹型結構的維護

      在維護樹型結構表時,刪除節(jié)點較為簡單,SQL 語句為: "delete from tree_class where classcode like′"+ classcode +"%′",即可將其節(jié)點和孩子一并刪除;增加節(jié)點時,分為前插、后插、和插入子節(jié)點三種情況,前兩種情況需要更新遞歸更新類別代碼,后者只需找到父節(jié)點的孩子的最大類別代碼加1 后,作為增加節(jié)點的類別代碼;通過拖放來改變樹的結構時,只需將拖動節(jié)點的parentId更新為目標節(jié)點的Classid即可,對應的SQL語句為:"update tree_class set parentId = "+ classidTo+" where classid = "+ classidFrom。

      3、效率分析

      對于樹的存儲一般有兩種形式:二維表和鏈表,遍歷方式一般也有深度遍歷和廣度遍歷兩種方式,遍歷的時間復雜度都是O( n )。用二維表存儲時,在內(nèi)存中用數(shù)組的下標能準確定位節(jié)點的父節(jié)點、兄弟節(jié)點所在的數(shù)組下標。數(shù)據(jù)庫中節(jié)點的定位也是準確的,但是將節(jié)點信息從數(shù)據(jù)庫中讀到內(nèi)存中時,如果無法通過內(nèi)存數(shù)組下標定位節(jié)點信息,那么就必須遍歷一遍尋找一個節(jié)點,n 個節(jié)點中尋找一個節(jié)點的時間是O(n/2),n 個節(jié)點排序的時間復雜度將是O( n 2/2),這也是一般實現(xiàn)的B/S 模式的樹結構效率低下的原因。本方案采用字典序編號方案,使得從數(shù)據(jù)庫中取得的樹是已經(jīng)排序的,直接遍歷生成客戶頁面程序,時間復雜度為O( n )。

      4、結 論

      本文討論了基于Ajax的動態(tài)樹型結構的實現(xiàn)方案,支持無刷新動態(tài)維護樹的節(jié)點信息,支持拖放節(jié)點改變樹的節(jié)點結構以及次序;同時采用數(shù)據(jù)庫存儲節(jié)點信息,保證了該方案有一定的通用性,此外結合XML描述樹的節(jié)點信息,使得任何按本方案預定的xml文檔描述的信息都可以通過樹來展現(xiàn)。本方案已經(jīng)應用在我校的數(shù)字迎新系統(tǒng)以及老百姓大藥房信息系統(tǒng)中。

    posted @ 2005-12-30 08:32 只牽這只狗 閱讀(392) | 評論 (0)編輯 收藏

    2.1 表示層實現(xiàn)

      類似Windows資源管理器的文件夾模式,節(jié)點的圖片樣式如表1所示。對于每個節(jié)點的DHTML 代碼,需要包含節(jié)點的位置、前導圖片、樣式、針對該節(jié)點的其他操作等。同時為了節(jié)點顯示的連貫性,還需一些前導圖片。

      表1 樹節(jié)點的前的圖片樣式表

     對于樹的非葉子節(jié)點,圖片和節(jié)點信息等,采用一個DIV ( division) 容器包含。DIV 等容器是DHTML 的基礎,使用它可以通過腳本程序?qū)ζ鋵傩赃M行操作,如設置其style 樣式的display 屬性來控制子節(jié)點的展開和隱藏。節(jié)點的位置、前導圖片、樣式、針對該節(jié)點的其他的操作等都放入容器中,例:

    < DIV id =mParentID>
    < IMG align = center border = 0 onclick =″nodeExpand (‘leafid’)″ name = m1Tree src =′Tplus.gif′>
    < IMG align = center border = 0 name = m1Folder src =′folderClosed. gif′> 計算機學院 </p>

      葉子節(jié)點無需容器直接輸出即可。

      當點擊某節(jié)點前的“ + ”、“ - ”圖片時通過DIV 的style 樣式的display 屬性控制子節(jié)點的展開和隱藏。display:“none”(隱藏,不可見),display:“block”(顯示) 。相關JavaScript 代碼如下:

    if (expandChild.style.display = =″none″){
     // 當前為隱藏狀態(tài),執(zhí)行展開動作
     this.Loading(parentObject);//判斷該分支的數(shù)據(jù)是否已經(jīng)加載
     expandChild.style.display =″block″;
    if (para2 = =″last″)
     parentObject.src =″Lminus. gif″; // 最后一個節(jié)點
    else
     parentObject.src = ″Tminus. gif″; // 顯示┠
     expandFolder.src = ″folderOpen. gif″;
    }else {
     // 將當前節(jié)點的子節(jié)點全部隱藏
     expandChild.style.display = ″none″;
     if (para2 = = ″last″)
      parentObject.src = ″Lplus. gif″;
     else
      parentObject.src = ″Tplus. gif″;
      expandFolder.src = ″folderClosed. gif″;
    }

      2.2 樹型表結構設計

      我們以數(shù)據(jù)庫為載體記錄節(jié)點的變化,樹型表結構至少要有以下字段:節(jié)點的編號(CLASSID) ,對節(jié)點的描述(ClassName),父節(jié)點的編號(ParentId),這些是構建樹結構所必須的信息。同時引入節(jié)點的類別代碼(ClassCode),節(jié)點的級別(ClassLevel),是否葉子節(jié)點 (Terminated)等輔助字段,記錄節(jié)點次序,實體關系圖如圖3所示。


    圖 3 樹型表結構示意圖

      樹遍歷的時間復雜度是O( n ),但是將樹信息存放到數(shù)據(jù)庫后,就不能按傳統(tǒng)的方式遍歷樹,必須使用SQL 語句訪問數(shù)據(jù)庫表的內(nèi)容,而一次性取的數(shù)據(jù)量越多,消耗的資源也越多,用戶等待的時間就越長。如果將無序的數(shù)據(jù)從數(shù)據(jù)庫中讀出,在服務器端,必須將排序后的樹送到客戶端顯示。因此,最好從數(shù)據(jù)庫讀出已排好序的樹。

      我們知道,字符串排序是按照字典序形式。結合SQL 語句的特點和樹結構特點,數(shù)據(jù)庫表中,節(jié)點的類別代碼采用多級字符串形式,如AAABBBCCC,從樹根節(jié)點開始,每向下一級字符串就增加一級,并且子節(jié)點類別代碼以父節(jié)點類別代碼開始,再開始本級的類別代碼。同級的節(jié)點按照生成的順序編號,如節(jié)點類別代碼為AAA 的下一級孩子類別代碼為AAAAAA,AAAAAB 等,AAAAAB 的孩子節(jié)點為AAAAABAAA、AAAAABAAB等。每一級編號字符的寬度與實際的應用關聯(lián),如AAA~ZZZ 一級則有263 個節(jié)點,如果不夠用再增加一個字符用于編碼。該巧妙的編號方式。使得在執(zhí)行SQL 語句select * from tree_class order by classcode 后,一次獲得完整的先序.

    原文鏈接:http://www.7dspace.com/doc/44/0512/2005122906292220003.htm

    posted @ 2005-12-30 08:31 只牽這只狗 閱讀(397) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 亚洲成在人线在线播放无码| 五级黄18以上免费看| 国产色爽免费视频| 亚美影视免费在线观看| 亚洲综合无码一区二区| 国产色爽女小说免费看| 99re6热视频精品免费观看| 亚洲av永久无码天堂网| 亚洲AV成人精品网站在线播放 | 亚洲国产美女精品久久久久∴| 91在线精品亚洲一区二区| 麻豆国产精品免费视频| 瑟瑟网站免费网站入口| 水蜜桃亚洲一二三四在线 | 亚洲三级高清免费| 免费视频成人国产精品网站| 亚洲尹人香蕉网在线视颅| 啊灬啊灬别停啊灬用力啊免费看| 亚洲一卡2卡3卡4卡乱码 在线| 日韩在线免费视频| 一级毛片视频免费| 亚洲一区二区三区丝袜| 亚洲成A人片777777| 全免费a级毛片免费看不卡| 中文字幕免费在线看| 亚洲熟妇无码一区二区三区 | 亚洲AV第一页国产精品| 国产伦精品一区二区三区免费迷| 亚洲三级中文字幕| 久久青青草原亚洲av无码| 男人的好看免费观看在线视频| 亚洲av无码片在线观看| 久久久久久久综合日本亚洲| 国产免费观看视频| 国产在线国偷精品产拍免费| 国产精品免费一区二区三区四区| 久久亚洲精品无码AV红樱桃| 国产国拍亚洲精品福利| 午夜色a大片在线观看免费| 51在线视频免费观看视频| 黄视频在线观看免费|