2008年10月25日

          不止一次我們的項目在靠開發人員硬扛著,bug來不及修改,文檔還在猛補,項目經理又在催著出版本,每修改一個bug都要在代碼的泥沼中摸爬滾打半天,卻又在制造著另外的bug,為了文檔而制造著根本沒有參考價值的文檔。每發布一個版本都要瞻前顧后并且總要無休止的加班,似乎開發人員永遠有干不完的活。

          我們不禁問自己,為什么會有那么多失敗的軟件,軟件開發我們到底還需要什么? 

          工具?我們不乏偉大的工具,IDE我們有eclipse、intelliJ、VC++等等,建模我們有Rose、together、Visio等等,配置管理我們Subversion、CVS、ClearCase等等,bug管理我們有ClearQuest、bugzilla等等,文檔我們word、wps等,還有集成、測試甚至生成代碼等等我們都有偉大的工具,工具我們不缺。流程?瀑布模型、迭代模型、UP、XP我們不缺流程管理的理論。知識?軟件開發算是一項知識型的工作,我們的開發人員一般都是本科碩士畢業,況且搜索引擎如此發達的今天,知識根本不是問題,況且我們的軟件開發需要多么高深的知識嗎?

           優秀的理論支持、有能力的人員、先進的工具,這些我們都具備,我們所缺的只是一種軟件開發的理念,缺少軟件開發的情商。我們一開始學習編程知識接觸到的就是C語言和數據結構,慢慢的一些結構化的思想就扎根于大腦,其實在商業軟件中數據結構、算法很少涉及,我們所需要的僅僅是一種設計、開發的理念。比如用面向對象本來是一種簡單的思想,目的是為了降低軟件的復雜性而出現的,可是讓熟悉了結構化編程的人去搞反而覺得很難。一些好的實踐經驗我們也經常提到,比如模塊化、松散耦合、面向接口編程、類應只關注本職工作等等開發設計理念以及規范命名、詳盡使用的注釋、清晰的結構等代碼規范以及每日構建、有效溝通、配置管理、bug管理等一些管理理念,這些做起來都非常容易,關鍵是懶惰是人的本性,不知不覺中我們就會犯著大家都在重復的錯誤。如果在項目開工之初就充分貫徹這些優秀的理念,在項目進行中無論時間多緊都持之以恒,并且項目進行中不斷的反思代碼中的壞味道,一經發現立即重構,相信我們的開發過程會進入一個良性的循環中去,我們的開發人員將會體會到什么是快樂開發。

          posted @ 2008-11-17 23:09 徐辛波 閱讀(353) | 評論 (0)編輯 收藏
          徐辛波,西安,從事軟件開發設計工作,熟悉Java語言,愛好開發工作,特別是java相關的編程,業余關注開源項目,誠心結識志同道合之士組建開源團隊,共同學習、進步、協作、為中國開源事業貢獻微薄之力。
          徐辛波 sinpo.xu@gmail.com
          posted @ 2008-10-31 21:00 徐辛波 閱讀(362) | 評論 (1)編輯 收藏

          JDOM因其簡潔易用易懂的API而被廣泛的使用。JDOM常用的核心類及它們間的關系如下圖所示:

          Document代表了文檔對象,抽象類Content表示文檔中的內容元素,各種內容組成了文檔對象。常用的內容元素有xml元素Element、xml注釋Comment、文本Text。下面以如下片段來說明各類的含義。

          <?xml version="1.0" encoding="UTF-8"?>

          <customers>

          <customer>

          <name>徐辛波</name>

          <occupation>developer</occupation>

          <!-- comment:following is contact info -->

          <contact>

          <email>sinpo.xu@hotmail.com</email>

          <mobile>15029357227</mobile>

          <fix-phone>02985457683</fix-phone>

          </contact>

          </customer>

          </customers>

          上述文檔用Document來抽象;customers為文檔的根元素(root element ),Element即一個封閉起來的元素,element元素可以有子元素,如<mobile>15029357227</mobile>是一個元素,而<contact>...</contact>也是一個元素,甚至<customers>...</customers>也是一個大元素;<!-- ... -->代表了xml中注釋,注釋在JDOM中用Comment類來抽象;Text代表了xml中的文本值,如元素屬性的值、元素的值、注釋的內容等,父元素的Text為子元素和值組成的串,使用Text類可以方便的表示一些特殊字符,如:

          Element element = new Element("name");

          Text text = new Text("AAA.<、BBB/>.<CCC>");

          element.addContent(text);

          值得一提的是Element的方法addContent(Content content),因參數是抽象父類Content,所以可以添加Text、Element和Comment等,如果添加的是Text則自動作為element的文本值,如果是Element則作為element的子元素,如果是Comment則作為element的注釋,使用十分方便。元素的值如<name>徐辛波</name>中的“徐辛波”也是一個和元素平行的Content對象(Text對象),當使用Element的getDescendants()方法時將返回一個該元素所有后代的迭代器,這些后代包括Element、Comment、Text等,如元素<contact>的后代包括email、mobile、fix-phone三個元素以及這三個元素的Text共6個后代,如果計算后代時有父子嵌套則應注意,父元素作為一個后代,其嵌套的子元素作為另一個后代。

          剛才提到核心類都包含在org.jdom包下,jdom還包含了org.jdom.input和org.jdom.output兩個包分別來處理xml內容的輸入輸出。當要讀取xml資源時我們通常使用input包下的SAXBuilder類從輸入流構建dom對象,當資源加載后常用的做法是在內存中緩存,這樣后續的查找修改等操作就非常快。文檔加載后內存的中各個元素是記錄有各自的位置和關系的,即保持有上下文環境的。如果想要刪除一段內容(Element Comment Text),只用調用該內容的detach方法即可,這樣元素即和文檔脫離關系了,再對文檔進行遍歷或者持久化到磁盤上時游離的元素就不可見了。Jdom的輸出類包括XMLOutputter、DOMOutputter、SAXOutputter。最常用的是XMLOutputter,通過它可以將dom對象輸出到指定的輸出流,并且可以指定所輸出xml文件的格式,比如縮進的樣式等。DOMOutputter輸出org.w3c.dom.Document對象,用于JDOM對象同w3c dom對象轉換,SAXOutputter可以注冊回調函數來處理相應的sax事件。


          一下示例代碼實現一個常用的讀取配置文件并且允許更改后同步到磁盤的操作:
          package sinpo.usagedemo;

          import java.io.File;
          import java.io.FileOutputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.io.OutputStream;
          import java.net.URL;
          import java.util.List;

          import org.jdom.Document;
          import org.jdom.Element;
          import org.jdom.input.SAXBuilder;
          import org.jdom.output.Format;
          import org.jdom.output.XMLOutputter;

          /**
           * 讀取配置文件,并且修改后及時同步到磁盤
           @author 徐辛波(sinpo.xu@hotmail.com) 
           * Oct 23, 2008
           */
          public class Configuration {

              private Element root = null;

              private Document dom = null;

              private static final String resourceName = "/config.xml";

              private static Configuration _INSTANCE = null;

              public static synchronized Configuration getInstance() {
                  if (_INSTANCE == null) {
                      _INSTANCE = new Configuration();
                  }

                  return _INSTANCE;
              }

              private Configuration() {
                  load();
              }

              public String getConfig(String configName) {
                  String configValue = null;
                  Element found = findRecursively(configName, root);
                  if (found != null) {
                      configValue = found.getText();
                  }
                  return configValue;
              }

              public void updateConfig(String configName, String newValue)
                      throws IOException {
                  Element found = findRecursively(configName, root);
                  if (found != null) {
                      found.setText(newValue);
                  else {
                      Element configNode = new Element(configName);
                      configNode.addContent(newValue);
                      // also: configNode.setText(newValue);
                      root.addContent(configNode);
                  }
                  sync();
              }

              public void deleteConfig(String configNamethrows IOException {
                  Element found = findRecursively(configName, root);
                  if (found != null) {
                      found.detach();
                  }
                  sync();
              }
              
              private void load() {
                  SAXBuilder builder = new SAXBuilder();
                  InputStream source = getClass().getResourceAsStream(resourceName);
                  try {
                      dom = builder.build(source);
                      root = dom.getRootElement();
                  catch (Exception e) {
                      e.printStackTrace();
                  }
              }

              // 遞歸查找. 在指定的父節點下查找葉子元素
              private Element findRecursively(String name, Element parent) {
                  Element found = null;
                  List<Element> children = parent.getChildren();
                  if (children != null) {
                      for (int i = 0; i < children.size(); i++) {
                          Element element = children.get(i);
                          String tmpName = element.getName();
                          if ((name.equals(tmpName)) && (!hasChild(element))) {
                              return element;
                          }
                      }

                      for (int i = 0; i < children.size(); i++) {
                          Element element = children.get(i);
                          if (hasChild(element)) {
                              found = findRecursively(name, element);
                              if (found != null) {
                                  return found;
                              }
                          }
                      }
                  }

                  return found;
              }

              private boolean hasChild(Element element) {
                  boolean hasChild = false;
                  List children = element.getChildren();
                  if ((children != null&& (children.size() 0)) {
                      hasChild = true;
                  }

                  return hasChild;
              }

              private void sync() throws IOException {
                  Format format = Format.getPrettyFormat();
                  XMLOutputter outputter = new XMLOutputter(format);
                  File file = null;
                  URL url = getClass().getResource(resourceName);
                  if (url == null) {
                      file = new File(resourceName);
                  else {
                      file = new File(url.getPath());

                      OutputStream out = null;
                      try {
                          out = new FileOutputStream(file);
                          outputter.output(dom, out);
                          out.close();
                          out = null;
                      catch (Exception e) {
                          e.printStackTrace();
                          if (out != null) {
                              out.close();
                          }
                      }
                  }
              }
          }
          posted @ 2008-10-25 21:02 徐辛波 閱讀(797) | 評論 (0)編輯 收藏

          導航

          <2008年10月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          統計

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          最新隨筆

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 比如县| 黄梅县| 雅江县| 辉南县| 育儿| 仁寿县| 太保市| 彭阳县| 长汀县| 华宁县| 泰来县| 雅安市| 曲松县| 景谷| 曲水县| 凤翔县| 中江县| 铅山县| 兴国县| 肇东市| 屏东市| 红原县| 缙云县| 珲春市| 敦化市| 石阡县| 大连市| 孟村| 宝山区| 芦山县| 三门县| 惠水县| 游戏| 屏南县| 南岸区| 虎林市| 鄄城县| 汝城县| 淮阳县| 博白县| 陆川县|