2012-05-09 9 views
7

ちょうど大学の外で、カップリングを減らす必要のあるコードが出てきています。しかし、私は完全にすべての概念を理解していないし、私を助けるための簡単な例が欲しいです。あなたを始めさせるために、私は1つのフィールド、名前を持つ人のクラスを持っています。そのクラス内にテキストを連結するメソッドがあります。カップリングの低減シンプルな例が初心者のために必要

私はこれが馬鹿げた例であることを知っています。ほとんどの人は、これほどシンプルな状況でカップリングを減らすことは絶対に考えませんが、コードと概念を完全に理解するための簡単な例がほしいだけです。

メインウィンドウの背後にあるコードには、テキストボックスとボタンがあります。ウィンドウがロードされると、person x nameフィールドの現在の値が表示されます。ボタンがクリックされると、x.PersonAddTextメソッドが呼び出されます。現在、この例では8で計算された結合があります。ボタンクリックイベントの場合は3、ウィンドウロードイベントの場合は3となります。

この例では、どちらか一方または両方についてこれよりも少なくすることができます。

マイ者クラス::

public class Person 
{ 
    //Fields 
    private string name; 

    //Properties 
    public string Name 
    { 
     get { return name; } 
     set { name = value; } 
    } 

    //Constructors 
    public Person() 
    { 
     name = "joe"; 
    } 

    //Methods 
    public string PersonAddText(string text) 
    { 
     return name += " - " + text; 
    } 

    //Interfaces (or additional code below here please to aid understanding) 
} 

マイコードの後ろ:以下

はすべて私のコードです

Person x = new Person(); 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     txtname.Text = x.Name; 
    } 

    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     txtname.Text = x.PersonAddText(txtname.Text); 
     txtname.Text = x.Name; 
    } 

私の単純なXAML:私が午前

<Grid> 
    <TextBox Name="txtname" Margin="12,12,12,0" Height="23" VerticalAlignment="Top" /> 
    <Button Content="Add Text" Margin="12,41,12,0" Name="button1" VerticalAlignment="Top" Click="button1_Click" /> 
</Grid> 

大きな困難これを説明しているインターネットのチュートリアルに目を通してください。

  • サービスロケータ
  • 依存性注入
  • 反転:私はこれを行うには3つの方法があります表示されるものと(3つすべての例に変換された上記の私のコードを持つことが可能ならば、それはいいだろう)私が読んでいるものを説明する制御(IOC)

articleで優れているが、彼はデータベース接続文字列でVBとASP.Netを使用しているような例は私には関係ありません。これは私が必要とするものとはまったく反対であり、コードを翻訳する方法を考えたり、概念を学んだり、関連するものにそれをどのように適用するかについて考えることは考えたくありません。例は良いですが、それはあまりにも多く、私は本当に余分な助けに感謝します。

編集履歴:綴りが訂正されました。私の質問を明確にするために以下を追加しました:

私はカップリングとコヒェションの背後にある理論を理解しています。しかし、大学での例は決してコード化する必要はありませんでした。また、大学ではカバーされていませんが、私はインターフェイスを理解しています。しかし、私はカップリングを減らすためにそれらを使用する方法を理解していません。

the article I refrenced aboveへのリンクが追加されました。

編集2:これまでのところ、私が今持っているものを以下の通りです:

public interface IPerson 
{ 
    string Name { get; set; } 
    string PersonAddText(string text); 
} 

public class Person : IPerson 
{ 
    //The code from the person class above 
} 

どのように私は今の背後にあるメイン・ウィンドウのコードでこれを使うのですか?私は、この正しいですし、もしそうなら、私がする必要がある何かがある

IPerson x = new Person(); 

Person x = new Person(); 

を交換する必要があります推測しています。私が依頼する理由は、ビジュアルスタジオで報告されたコード結合数の減少はまだ見られないからです(実際には、メインウィンドウのコードの後ろに1つ増えます)。

+0

あなたは何を理解していますか?あなたはどのコンセプトに問題がありますか? – Oded

+0

私は、クーペルと結束が理論的に何を意味するのか知っています。しかし、私はそれをコード化する方法を理解していません。特に、私たちは決して大学でのインターフェースをカバーしていなかったので(確かに、私は偉大な大学です)。私はインターフェイスも理解していますが、私はそれらを使用してクーペルを減らす方法を知りません。 –

答えて

3

編集

私は私の答えは私が少しさらにそれを更新させ、ビットを助けてくれてうれしいです。

Person x = new Person(); 

IPerson x = new Person(); 

へのあなたのコードビハインド今で指定されているプロパティとメソッドを知っている:直接答えとしてあなたの質問を使用するには、変更する必要があるすべてはからあなたのフィールド宣言がありますお使いのインターフェイスは、後でnew Student()のためにnew Person()を交換することができます。オブジェクトがインタフェースを実装している限り。 コードビハインドは必要な変更を加えることなく動作するはずです。

サイドノート

私は遅延ロードx人を、また、より多くのわかりやすい名前とプロパティを使用して検討することをお勧めします。 N.B.これはあなたの質問に答えませんが、単なる提案です。 :)

private IPerson _CurrentPerson = null; 
private IPerson CurrentPerson 
{ 
    get 
    { 
     if (this._CurrentPerson == null) 
     { 
      this._CurrentPerson = new Person(); 
     } 
     return this._CurrentPerson 
    } 
    set 
    { 
     this._CurrentPerson = value; 
    } 
} 

デカップリングは、二つまたはそれ以上のコードブロックは、互いに依存してはならない場合です。 Inversion of Controlは、実行時にオブジェクトの結合がバインドされているため、オブジェクトとそのインスタンスの柔軟性が高まり、したがって結合が少なくなります。制御の反転は、インタフェースと組み合わせて使用​​するのが最も良い方法です。インターフェイスは、ClassAMethodXを実行し、PropertyYを持つことを定義します。私たちの主な目的は、実行時に返されるオブジェクトを気にせず、ログをインターフェイスとして実行できるようにすることです。あなたの主なメソッドコールの中、その後

public interface IPerson 
{ 
    string Name { get; set; } 
    string PersonAddText(string text); 
} 

public class Person : IPerson 
{ 
    // your code here 
} 

を、代わりに明示的Personオブジェクトを使用して、あなたが使用されます:あなたの上記の例で

、あなたはそうのようなあなたのPersonクラス、多分何かをインターフェイスしたいと思うでしょうインタフェースIPersonを実装するオブジェクトのインスタンス。インタフェースとオブジェクトの「フックアップ」は、依存関係の設定に役立つさまざまなライブラリによって実現できます。私の経験では、StructureMapMicrosoft's Enterprise Libraryを使用しました。 「彼らは、セットアップをする少し手間のかかることができますが、彼らは一度、あなたがそうのような何かを行うことができるでしょう...

public void MainMethod_InInterfaceLayer() 
{ 
    // container is an instance of UnityContainer 
    Person newPerson = container.Resolve<IPerson>(); 
} 

私は、これは完全な答えをins't知っているが、うまくいけば少し助けてくれるでしょう。:)

+0

これまでのところ、この回答は分かりやすいようです。私は現在それと一緒に遊んでいるとあなたに戻ってきます。私が抱えている唯一の問題は、あなたが提供したリンクが非常に多くの部門に入ることです。この単純な例では、理解がより重要になります。 MainMethod_InInterfaceLayer()の代わりに拡張機能を使わずに必要なコードを書くことができれば、答えを得ることができます。可能であれば、MainWindowコードの中で何をすべきかを変更することによって、これまでのご協力ありがとうございます。 –

+1

私は自分の答えを更新しました。うまくいけば、@ Odedの答えと一緒に、それはあなたが探しているものでなければなりません。 – Richard

+0

リチャードに感謝します。私はあなたの答えを今実装しています。その背後にある説明はとてもいいです。私は、私の例があまりにも単純で、上記の方法でVisual Studios Couplingマークを3から2に減らすことができないと仮定しようとしています。私の編集で説明したように、記述したように私がすると、減らすことはできません。あなたのお手伝いをありがとう。私はあなたのサイドノートでも演奏しますが、私はこれが幾分無関係であると感じています(しかし私は提案を賛美します)。私はこのケースでは怠け者ローディングの恩恵を知りたいと思います。あなたが時間があれば、どのような教え方があなたにそれを示唆してくれたのですか? –

2

あなたはIPersonインタフェースと、いくつかの実装(PersonStudentTeacherなど)を持っていて、単にIPersonで稼動するために必要ないくつかのコードを持っていると言います。

持つ:

IPerson x = new Person(); 

をあなたのコード内の後ろに強くカップルはPersonクラスに。

コントロールの反転は、クラスを内部で作成するのではなく、外部からの依存関係を持つことによって影響を受けます。

これは、通常、依存関係注入を使用することによって実現されます。IPersonは、クラスを直接作成するクラスではなく、クラスに渡されます。インスタンスをコンストラクタ(コンストラクタインジェクション)またはプロパティ(プロパティインジェクション)に渡すことで、これを行うことができます。

サービスロケータは、ハードコーディングなしで依存関係を取得する別の方法です。パターンは、タイプ/インタフェースのインスタンスを「見つけます」。

クラスに依存性を注入する方法の例:

public class MyClass 
{ 
    IPerson person; 

    public MyClass(IPerson p) 
    { 
    person = p; // injected an instance of IPerson to MyClass 
    } 

    // can now use person in any method of the class, or pass it around: 

    public void MyMethod() 
    { 
    string name = person.Name; 
    } 
} 
+0

まずはあなたの答えに感謝します。リチャードの答えを使って、私はこれまでのインターフェースを作ることができました。私が今問題にしているのは、コードの代わりにコードを使用する方法です。それとも、あなたが私の上に見せていることです。私にはあまり明確ではありませんが、より多くのコードを明確にすることができれば、私はあなたに答えを与えます。再度、感謝します。 –

+1

@FrancisRodgers - 'MyClass'クラスがどのように' IPerson'の実装から切り離されているかの例を追加したので、_any_ implementerを使うことができます。コンストラクタインジェクションの場合も示します。 – Oded

0

あなたは、データベースから自分自身を読み込むことができます変更を取得し、彼または彼女が亡くなったときに電子メールを送信Personクラスを持っていると仮定します。

class Person 
{ 
    ... 
    void LoadUsingId(int id); 
    void HaveDiedWillMail(); 
    void SetFirstName(string name); 
    ... 
} 

ここで見ることができるのは、このPersonが実際には3つのことを実行していることです(少なくとも!)。

データベースを読み込んで自分自身を読み込む方法を知っています。 メールを送信する方法を知っています。 それ自体を変更することができます。

練習ではないにしても理論上のコードは、1つのことにのみ責任があります。これらのコンポーネント間の結合を減らすには、それらを引き離す必要があります。彼らは独立して働くことができるようにそれらを分離する。

class Person 
{ 
    ... 
    void LoadUsingId(PersonRepository person); 
    void HaveDiedWillMail(IMailer mailer); 
    void SetFirstName(string name); 
    ... 
} 

この人為的な例では、Personはデータベースから何かを読み込む方法がわかりません。荷物を積むという事実を無視することは、あなたも切り離すべきことです。 Person.HaveDiedWillMailに特定のメーラー(IMailer mailer)を使用するように指示するので、メールの送信も分離されています。

依存性注入、サービスコンテナとそのような技術は、機能するために人が必要とする/必要とするコンポーネントを自動的に見つけ出し、デカップリングの上に余分なレイヤーを並べ替えて、

+0

私は、疎結合の方法であっても、オブジェクト(モデル)がデータベースからロードされるべきではないという意見に同意します。モデルは一つのことをすべき*:実際の物体を表現する。データベースからの読み込みは、別のオブジェクトの仕事です。これは*データベースからデータをロードすることです*。実際には、モデルとデータベースの間に2つの層があります。 –

+0

私もあなたに同意します。しかし、私はここにすべてを説明しようとしているわけではないし、賢明なものも...デカップリングしています。 – Jaapjan

関連する問題