Cohesion

1243247999|%Y-%m-%d|agohover

知名的 C++ 經驗書 Exceptional C++ 中,有一個準則是這樣講的:

儘量內聚(cohesion)。盡力給予每段程式碼 –每個模組、每個 class、每個函式– 單一而明確的任務。

Herb Sutter 在書中提到了使用 C++ 來實作 Stack 的例子,這邊舉出另一個出現在 Java 中的例子。(會舉這個例子,是因為我有切身之痛了)

以下的程式碼來自 www.java2s.com,是個展示 Java enhanced for-loop 的程式:

import java.util.*; 
 
class StrIterable implements Iterable<Character>, 
                             Iterator<Character> { 
  private String str; 
  private int count = 0; 
 
  StrIterable(String s) { 
    str = s; 
  } 
 
  // The next three methods impement Iterator. 
  public boolean hasNext() { 
    if(count < str.length()) return true; 
    return false; 
  } 
 
  public Character next() { 
    if(count == str.length())  
      throw new NoSuchElementException(); 
 
    count++; 
    return str.charAt(count-1); 
  } 
 
  public void remove() { 
    throw new UnsupportedOperationException(); 
  } 
 
  // This method implements Iterable. 
  public Iterator<Character> iterator() { 
    return this; 
  } 
} 
 
public class MainClass {  
  public static void main(String args[]) {  
    StrIterable x = new StrIterable("This is a test."); 
 
    for(char ch : x) 
      System.out.print(ch); 
 
    System.out.println(); 
  }  
}

這段程式碼有趣的地方在於 StrIterable 同時是個容器(容納 Character),也同時是個 iterator。在這個簡單的例子中,把這兩個不同的功能合寫成一個 class 也許無傷大雅,但其實卻是個相當不良的習慣,當 iterator 正在尋訪容器時,事實上容器的內部狀態也跟著改變了。舉個簡單的例子:

public class MainClass {
  public static void main(String args[]) {  
    StrIterable x = new StrIterable("This is a test."); 
 
    for(char a : x)
      for(char b : x)
        System.out.print(a + " " + b);
  }
}

迴圈有兩層,但 loop counter 只有一個,顯然這段程式碼不會照著 programmer 的意思走。

正如同「變數的 scope 愈大,愈難找出它出錯的地方」,物件愈複雜,你也愈難從 bug 出錯的情況去判斷錯誤的位置在哪。


Comments

Add a New Comment
or Sign in as Wikidot user
(will not be published)
- +
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License