依存とは
依存の定義
class A が class Bや Interface Bを利用するとき、AはBに依存するという。
結合の定義
AとBが互いに利用し合っている状態を結合という。
結合の強弱
結合には強度があり、密結合や疎結合と呼ばれる。結合は0か1ではなく、結合の強度は連続的なものである。
依存の方向性
依存関係は方向性が存在し、AがBに依存していてもBがAに依存しているとは限らない。
なぜ依存が悪いものなのか?
依存は再利用の阻害要因となる。
再利用性は開発速度・コードの可読性・コードの質を向上させる。
例えば、XMLファイルからカレンダーのイベント一覧を読み込むクラスを考えてみる。
public class CalendarReader {
public List readCalendarEvents(File calendarEventFile){
//open InputStream from File and read calendar events.
}
}
readCalenderEvents
はFile
を引数としてとり、readCalenderEvents
はFile
classに依存している。つまり、 CalednarRedaer
はファイルシステム上のローカルファイルからしかカレンダーイベントを読み取る事ができない。ネットワークからカレンダーを読み込んだり、データベースから読み込んだりもできない。この場合 CalenderReader
はFile
classに密結合していると言える。
File
parameter をInputStream
parameterに変更する事でより疎結合な実装ができる
public class CalendarReader {
public List readCalendarEvents(InputStream calendarEventFile){
//read calendar events from InputStream
}
}
InputStream
はFile
objectからも、Network Socket
からも、URLConnection
classからも取得できる。そのため、CalenderReader
classはInputStream
を引数にした方が再利用性が高まる。しかし、100%結合が解消したわけではない。例えば、NIO Channelからのデータを読み取ることは難しい。
You should not add functionality to an interface blindly.
Below is an example of what this means. The code example shows a tree node for a hierarchical tree structure.
public interface ITreeNode {
public void addChild(ITreeNode node);
public List<ITreeNode> getChildren();
public ITreeNode getParent();
}
Imagine that you want to be able to count descendents of a given node. At first you might be tempted to add a countDescendents() method to the ITreeNode interface. However, if you do so anyone who wants to implement the ITreeNode interface will also have to implement the countDescendent() method.
Instead you could implement a DescendentCounter class that can traverse an ITreeNode instance an count all descendents of that instance. This DescendentCounter can be reused with different implementations of the ITreeNode interface. You have just saved your users the trouble of implementing the countDescendents() method, even if they need to implement the ITreeNode interface!
疎結合を実現する方法
- 抽象化
- 必要最低限の構造を抜き出す
- 機能の分離