クラスの結束と結合の改善
-
28-10-2019 - |
質問
このコードのセットが与えられており、クラスのコードの結束と結合を改善する方法を提案する必要があります。しかし、私はこれらのクラスがイベントを利用しているように見えるため、非常によく分解されていると思いました。そして、まとまりの観点から、すべてのinit()呼び出しが一緒に配置され、すべてが私には非常に大丈夫のようです。
public class A
{
private C t;
private B g;
public static void main(String args[]) {
// Creates t and g.
t = new C();
t.init();
g = new B();
g.init();
g.start(this);
}
pubic void update (Event e)
{
// Performs updating of t based on event
}
}
public class C
{
public C() { ... }
public void init() { ... }
}
public class B
{
public B() { ... }
public void init() { ... }
public void start(A s) {
e = getNextEvent();
while (e. type != Quit)
if (e.type == updateB)
update(e) ;
else
s.update(e) ;
e = getNextEvent();
}
public void update(Event e) { ... }
}
}
クラスの結束と結合を改善する方法はまだありますか?私には大丈夫そうですが、私は何かが足りないと思います。
これに関する提案をありがとう。
解決
1つの提案は、コントローラーロジック(クラスA)からのロジックの取り扱いロジックを切り離すことです。
したがって、4種類のクラスがあります。
- 「サーバー」の実行に使用されるメインクラス(a)
- イベントを聞くスレッド(b)
- 更新されるモデルレイヤー(c)
- イベントの操作をサポートするイベントハンドラークラス(d)
それは次のように見えるかもしれません:
public class Main {
private Model m;
private EventListener listener;
... main() {
m = new Model();
listener = new EventListener();
EventHandler eventHandler = new MyEventHandler();
// set the event handler
listener.setEventHandler(eventHandler);
listener.start(m);
}
public class Model {
// nothing to see here
}
public class EventListener() {
private EventHandler handler = new DefaultEventHandler();
public void start(final Model m) {
// startup
while (event.type != Event.Quit) {
// get event
handler.handleEvent(event, m);
}
// shutdown
}
public void setEventHandler(EventHandler eh) { this.handler = eh }
}
public class MyEventHandler implements EventHandler {
public void handleEvent(Event e, Model m) {
// update the model
}
}
この新しいデザインでは、モデルを更新するビジネスロジック(例のC)は、「ランナー」クラスではなく外部クラスに移動したことに注意してください。メインクラスは、イベントが何であり、それらをどのように処理するかを知る必要がないため、これは少しきれいです。
もう1つの利点は、これを使用して、チェーン付きイベントハンドラーまたは複数のシリアルイベントハンドラーを使用して複雑なイベント処理を簡単にコーディングできることです。 Bはハンドラーの呼び出しのみを担当し、イベントタイプを理解する必要がないため、非同期イベントの取り扱いを実装することも非常に簡単です。これは時々と呼ばれます 公開/購読します リスナー(b)とハンドラー(更新(e)メソッド)をゆるく結合したままにします
他のヒント
ユニットテストの書き込みを開始します(さらに良いことに、そうしてください TDD)。カップリング(そして、それほどではないが、それの結束または欠如)はすぐに明らかになります。
たとえば、クラスBの開始方法にはタイプAのパラメーターがあります。例では、Aをインスタンス化することができますが、Aが他の依存関係を持っている場合はどうなりますか?おそらく、すべての開始ニーズは、(更新方法を使用して)実装するインターフェイスです。
そして、getnexteventは何をしますか?他の依存関係を使用する場合、テストハーネスでBを取得することは困難な場合があります。
テストは、設計の検証に役立ちます。
あなたのコードをもっと見ることなく、あなたのコードがどれほど分離されているかを言うのは困難です。イベントはコードを切り離す1つの方法ですが、コードを理解してデバッグするのがより困難になることもあります。
クラスを設計する場合、高調整は多くの方法が互いに再利用することを意味し、低カップリングは、いくつかの公開方法を公開するだけで必要なことを意味します。
パッケージを設計する場合、高コーティングはパッケージ内のクラスの多くが互いに依存していることを意味し、低カップリングとは、パブリックスコープ、またはインターフェイスを介した他のクラスとのメッセージが少ないことを意味します。
特に変化に反応することになると、高コース、低カップリングの利点は痛みを軽減する必要があります。痛みを軽減しない場合は、最適化に多くの時間を費やさないでください。私はここで私が輝かしいように聞こえるように聞こえますが、必ずしも理解していない人々の意見に頼るのではなく、高コース、低カップリングが「十分に良い」かどうかを測定する際に、あなた自身のメトリックを念頭に置いておく必要がありますあなたが解決しようとしている問題。
オリジナルの設計が、イベントハンドラーを使用して使用されているように、将来別の機能またはクラスを組み込むことである場合、それが使用されています。その後、クラスまたはインターフェイスの実装と最適化に関する戦略パターンに集中します。