熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

分析用Javadoc形式集成文檔的利與弊

2013-11-15 09:50:28  來源: JSP教程 

  Java語言按照Javadoc注釋約定采用了一種集成的方法來進行API文檔編制Javadoc工具可以幫助生成好的API文檔然而大多數Java API文檔卻很糟糕因為它是源代碼的一部分所以 API 的文檔編制職責最終還是落到了工程師身上在本文中Brian 對 Java 文檔編制實踐的當前狀態進行了嚴厲的批評同時提供了一些關於如何編寫更有用的 Javadoc 的准則
  對於大多數 Java 類庫來說Javadoc 是唯一的文檔而且除了商業軟件組件之外許多 Java 類不會用到 Javadoc雖然 Javadoc 作為 API 參考工具很出色但對於了解類庫是如何組織的和應該如何使用它來說它卻是一種十分差勁的方法並且即便用了 Javadoc它通常只包含有關方法完成了什麼的最基本信息而忽略了諸如錯誤處理參數及返回值的作用域和范圍線程安全鎖定行為前置條件後置條件不變條件或副作用之類的重要特性
  向 Javadoc 學習
  對於包括大多數開放源碼包和大多數內部開發的組件在內的許多Java工具而言實際情況是包括Javadoc在內幾乎所有類庫或組件都不具有有效的文檔這就意味著開發人員要從Javadoc學習使用工具而且我們應該考慮根據這一現實組織我們的Javadoc我經常開玩笑說現在Java程序員需要具備的最重要的技能之一是熟練地使用Google和Javadoc來對那些文檔編制得十分糟糕的 API 進行逆向工程這可能是真的但卻並不十分好笑
  大多數 Java 包都有某種對象它是在得到該工具內的任何其它對象之前必須創建的第一個對象在 JNDI中該根對象是Context而在JMS和JDBC中它是Connection如果有人告訴您JDBC中的基礎對象是 Connection以及如何獲得這一對象那麼接著您很可能會從 Javadoc 中通過仔細察看 Javadoc 中可用的方法列表找到如何創建並執行 Statement以及如何迭代生成的 ResultSet但您如何知道獲得 Connection 是您的第一步呢?Javadoc 在包內按照字母順序組織類在類中按照字母順序組織方法遺憾的是Javadoc 中沒有神奇的從這裡開始(Start Here)記號把讀者帶到浏覽 API 的邏輯開始位置
  包描述
  最接近從這裡開始記號的是包描述但它卻很少得到有效的使用如果將文件 l 與源代碼一起放在一個包中那麼標准的 doclet 會將已生成的 l 文件中的內容連同類列表一起放在該包內遺憾的是生成我們都很熟悉的 HTML 文檔的標准 doclet 卻無法使包描述易於找到如果您單擊左上窗格中的某個包那麼這會在左下窗格中產生方法列表但並不會在主窗格中產生包的摘要 — 必須單擊左下窗格中的包名稱來查看摘要但不要緊畢竟大多數包並沒有包描述
  包文檔是一個放置從這裡開始文檔的極好的地方這一文檔用來概述包做什麼主要摘要是什麼以及從何處開始浏覽包的 Javadoc
  類文檔
  除包文檔之外特定於類的文檔對於幫助用戶徹底了解新工具也能起到重要的作用類文檔當然應該包括此特定類做什麼的描述但還應該描述該類與包中的其它類如何關聯特別是要標識任何與該類相關的工廠類例如JDBC 中的 Statement 類文檔應該說明Statement 是通過 Connection 類的 createStatement() 方法獲得的這樣如果一個新用戶偶然進入 Statement 頁面那麼他會發現首先他需要獲得 Connection對每個類都應用這一約定的包會迅速為用戶指出根對象用戶因而能夠得心應手
  因為 Javadoc 是圍繞對特定類進行文檔編制而設計的因此在 Javadoc 中通常沒有明顯的位置來放置演示幾個相關類一起使用的示例代碼但由於一味地側重於特定類或方法的文檔編制我們失去了討論如何組合包中內容的機會如果對於根對象在包文檔或類文檔中有一個演示一些基本用法的簡單代碼示例則對於許多用戶來說將是非常有用的例如Connection 類文檔可以有一個簡單示例該示例獲取連接創建預編譯語句執行該語句並迭代結果集從技術上說這可能不屬於 Connection 頁面因為它還描述了包中的其它類然而尤其是當結合了上面那種引用當前類所依賴的類的技術時用戶才能非常迅速地找到獲取簡單的實用示例的途徑不管類的組織方式如何
  糟糕的文檔=糟糕的代碼
  對於大多數 Java 類庫來說除了那些作為打包組件出售的商業產品之外要麼沒有 Javadoc要麼非常糟糕由於存在的事實是對於大多數包來說Javadoc 是我們擁有的唯一文檔這基本上意味著使我們自己陷入了這樣的困境除了作者之外其他人沒法使用我們的大部分代碼——如果不付出重大的考古一樣的努力至少會這樣
  由於文檔現在是代碼的一部分因此我認為是軟件工程社區形成一個共識的時候了這就是即使代碼很出色如果文檔很糟糕也應該被認為是差勁的代碼因為不能有效地重用單元測試不久前還聲譽不佳只是到了最近它才受到了許多工程師的青睐就和它一樣為了改善我們生產的軟件的可靠性和可重用性API 文檔也必須成為開發過程的一個集成部分
  編寫Javadoc就是某種形式的代碼檢查
  編寫合理的Javadoc也會產生副作用它迫使我們進行某種形式的代碼檢查來研究類的體系結構和它們之間的關系如果單個包類或方法很難編制文檔那麼或許可以嘗試同時對多個包類或方法進行文檔編制這應該是個提示即可能它需要重新設計
  文檔的自我檢查方面使得某些方面更加重要即在開發過程中盡早編寫Javadoc然後隨著代碼的不斷開發定期對其進行檢查而不是僅僅等待代碼完成再編寫文檔(如果有剩余時間的話)後一種策略十分常見它將編寫文檔拖到項目最後而那時時間安排十分緊張開發人員的壓力也很大結果再常見不過了就是那種一文不值的文檔它只提供了文檔假象用戶真正需要的是了解該類的工作原理而該文檔卻沒有提供任何這樣的信息
  清單 典型的一文不值的 Javadoc
  
  /**
   * Represents a command history
   */
   public class CommandHistory {
   /**
   * Get the command history for a given user
   */
   public static CommandHistory getCommandHistory(String user) {
  
   }
   }
  什麼是好的文檔
  
  
  那麼好的文檔包括哪些內容呢?
  
  上面描述的組織技術(在類描述中引用相關類或工廠類也包括了包概述和代碼樣本)是形成優秀文檔的好開端它有助於新用戶使用 Javadoc 了解新工具
  
  但體系結構的概述只完成了任務的一半另一半則是詳細地解釋方法做什麼和不做什麼在什麼條件下運行以及它們如何處理錯誤條件大多數 Javadoc 都沒有完全提供所需的信息即便是那些充分描述了方法在期望情況下的行為的 Javadoc 也是如此這些缺少的信息包括
  
  · 方法如何處理錯誤條件或不合要求的輸入
  
  · 如何將錯誤條件傳回給調用者
  
  · 可能會拋出哪個特定異常的子類
  
  · 哪些值對於輸入是有效的
  
  · 類不變條件方法前置條件或方法後置條件
  
  · 副作用
  
  · 在方法之間是否有重要聯接
  
  · 類如何處理多個線程同時訪問一個實例的情況
  
  Javadoc 約定提供了 @param 標記它讓我們除了能夠對參數的名稱和類型編制文檔之外還可以對其意義編制文檔然而並不是所有的方法都能很好地接受參數的任何值例如雖然可以合法地向任何獲取對象參數的方法傳遞空值(null)而不違反類型檢查規則但並不是所有的方法都能在傳入空值時正常工作Javadoc 應該顯式地描述有效的參數范圍如果它希望某個參數非 null那麼它應該這樣描述而如果它期望參數值在某個范圍內例如某種長度的字符串或大於 的整數那麼它也應該那樣描述並非所有方法都仔細檢查其參數的有效性不進行有效性檢查也沒有編制關於可接受的輸入范圍的文檔這二者的結合為災難埋下了隱患
  
  返回代碼
  
  Javadoc 使得描述返回值的意義變得很容易但正如方法參數一樣@return 標記應該包括對可能返回的值范圍的詳細描述對於對象取值的返回類型而言它會返回空值嗎?對於整數取值的返回類型而言結果會限制在一個已知值或非負值的集合上嗎?任何返回代碼都有特殊意義嗎例如從 javaioInputStreamread() 返回 表示文件結束符?返回代碼會被用來表示例如如果無法找到表項則返回空值那樣的錯誤條件嗎?
  
  異常
  
  標准 doclet 復制方法的 throws 子句但 Javadoc @throws 標記應該更為具體例如NoSuchFileException 是 IOException 的子類但 javaio 中的大多數方法卻只被聲明為拋出 IOException然而方法可能獨立於其它 IOException 而拋出 NoSuchFileException這是調用者要了解的很有用的事實 — 它應該被包括在 Javadoc 中還應該指出拋出各種異常類的實際錯誤條件以便調用者知道在給定異常被拋出時該采取什麼糾正措施應該用 @throws 標記對方法可能拋出的每個經檢查的或未經檢查的異常編制文檔並對引發拋出異常的條件編制文檔
  
  前置條件後置條件和不變條件
  
  當然您應該對方法對對象狀態的影響編制文檔但您可能需要編制得更詳細一些描述方法的前置條件後置條件和類不變條件前置條件是在調用方法前對對象狀態的約束例如調用 Iteratornext() 的前置條件是 hasMore() 為真後置條件是方法調用完成後對對象狀態的約束例如在調用 add() 之後 List 不能為空不變條件是對對象狀態的一種約束它保證該狀態始終
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19207.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.