朱雀的IT世界

          每天進步一點點,努力做好自己

           

          一點重構心得

          昨天,要寫一段程序完成一個定時任務,是有關Socket 發送的。胖子給我發了一段現成的程序,這段程序基本上的功能是實現了,但是表達的并不是那么清晰,因此我想重構一下。沒想到重構的過程竟然花了一個多小時,從晚上八點多,一下就寫到了十點,但是重構完后,感覺清晰多了。仔細想想收獲頗多,因此在這里寫寫經驗進行總結。

          重構程序的目的,不是因為程序不能用才要你去重構,重構的目的是因為一、你的代碼,被人看的次數,遠比它用到的次數多;二、重構有利于你發現問題,讓你的程序結構優化,因此可復用性更強,遵守了知識的唯一性,DRY 原則;三、如果你要改動這段代碼,那么先重構,使得你的代碼好改,這實際是在為你的未來減少工作量,而且一段優秀的代碼,帶給你的價值,遠比你每次都要Ctrl+C,Ctrl+V 大得多。

          寫代碼,要讓你的代碼第一次呈現在別人面前的時候,像讀英語一般,那么你的代碼功底是足夠了。你的代碼就可以稱作你最好的文檔了,其余什么文檔,大可不必!

          基于昨天的經驗,我新總結了兩條:
          一、經常使用重構方法extract method 的人,會發現,總是可以省掉一些臨時變量。這是好事,但這可能會造成如下的結果:

          method_one(method_two(method_three(method_four())))

          也就是說,很可能會導致這種長串的嵌套,導致程序可讀性的下降,使人看的暈頭轉向。那么如何解決呢,其實是一個度的問題。我給自己定了一個規矩,臨界點是三個函數這樣級聯起來,如果超過三個,我就將它們拆開。比如說上面這個小例子,我會拆成:

          arg = method_three(method(four));
          method_one(method_two(arg));

          雖然浪費了一個臨時變量,但是這樣就可以讓人一眼看懂我的意思,可讀性提升,修改起來自然也會容易些。

          二、寫過Java I/O 的人,肯定看到過這樣的程序:

          Reader in = null;
          Writer out = null;
          try
          {
              in = new InputStreamReader(socket.getInputStream(),"utf8");
              out = new OutputStreamWriter(socket.getOutputStream(),"utf8");

          /**
           * some TODOs here
           *
          **/
          }catch(IOException ioe)
          {
              System.err.println("error message");
              ioe.printStackTrace();
          }
          finally
          {
             try
              {
                  if(in != null)
                     in.close();
                  if(out != null)
                     out.close();
              }catch(IOException ioe2)
              {
                 System.err.println("some error message");
                 ioe2.printStackTrace();
              }
          }


          怎么說呢,這段代碼看上去,其實是夠好了,其實不重構也是可以的。也許我偏執吧,我認為它不夠好,因為:首先,大段的try catch 的確會捕獲異常,但是這段代碼至少有好幾段是會獨立拋出異常的,這里包含了四個IO 實例的創建和銷毀,這四段代碼如果出錯都會拋出異常,那么你捕獲的到底是哪個呢?其次,沒有把功能段合理分開,這段代碼的邏輯功能實際上是兩個,一個是讀,一個是寫,那么合并在一起,首先順序很亂,其次容易讓閱讀的人產生困惑,從而造成代碼可讀性差。我是這樣做的:

          private void writeFile(String fileName, String outStr)
                  {
                      Writer writer = null;
                      try
                      {
                          writer = new OutputStreamWriter(new FileOutputStream(fileName),
                                  "utf8");
                      }
                      catch (UnsupportedEncodingException e)
                      {
                          System.err.println("不支持的編碼方式");
                          e.printStackTrace();
                      }
                      catch (FileNotFoundException e)
                      {
                          System.err.println("初始化文件失敗,或路徑不存在:" + fileName);
                          e.printStackTrace();
                      }
                      try
                      {
                          writer.write(outStr);
                          writer.flush();
                      }
                      catch (IOException e)
                      {
                          System.err.println("寫文件失敗");
                          e.printStackTrace();
                      }
                      finally
                      {
                          try
                          {
                              if(writer != null)
                                  writer.close();
                          }
                          catch (IOException e)
                          {
                              System.err.println("關閉文件失敗");
                              e.printStackTrace();
                          }

                      }
                  }


          類似的,也將讀的邏輯獨立抽出來,雖然,這不但沒使代碼的量減少,卻增加了很多try catch 模塊,不過邏輯上很完整,而且發揮了每個try catch 的最佳功效。我把它起名曰,我個人的偏執情節吧。

          困了,要睡覺了,本來還想將代碼從最初模樣,到最后模樣的過程復述一遍,改天有機會再說,精華都已經說了。嘿嘿

          posted on 2008-01-08 23:56 朱雀 閱讀(352) 評論(0)  編輯  收藏 所屬分類: java 基礎應用

          導航

          統計

          常用鏈接

          留言簿(5)

          隨筆分類

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 凤凰县| 顺昌县| 淄博市| 临洮县| 虞城县| 宁南县| 禄丰县| 故城县| 寻甸| 共和县| 阆中市| 沭阳县| 晋州市| 江安县| 通辽市| 南和县| 伊吾县| 舟山市| 师宗县| 翁牛特旗| 隆昌县| 芮城县| 镇江市| 江北区| 海晏县| 宕昌县| 山西省| 内江市| 喀喇| 甘德县| 澜沧| 专栏| 平谷区| 灌云县| 达拉特旗| 泽州县| 顺平县| 聂荣县| 江西省| 容城县| 湾仔区|