Question

Just out of college and am coming across some code where I need to reduce coupling. But I don’t understand fully all the concepts and would like a simple example to help me. To get you started I have a person class with a single field, name. I have a method within that class to concatenate some text.

I know this is a silly example, and most people would never consider reducing coupling in situations as simple as this but I only want a simple example to help me fully understand the code and concepts together.

In the code behind the main window I put a text box, and a button. When the window loads it shows the current value of the person x name field. When the button is clicked, the x.PersonAddText method is called. Currently this example has coupling calculated at 8. With a 3 for the button click event and a 3 for the window loaded event.

Is there any way, using this example we can get it down to less than this for either or both of them.

Below is all my code:

My Person Class:

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)
}

My Code Behind:

    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;
    }

My Simple 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>

I am having great difficulty understanding the tutorials around the internet explaining this. From what I see there are 3 ways to do this (it would be nice if possible, to have my code above converted to an example of all three):

  • Service Locator
  • Dependency Injection
  • Inversion of control (IoC)

The article explaining the stuff i have read is excellent, but the examples are not relevant to me as he is using VB and ASP.Net with database connection strings. This is totally opposite what I need, and I don’t want to be thinking about how to translate the code, while learning the concepts, and thinking also about how to apply it to something relevant. While the example is good, it’s just too much, and I would really appreciate any extra help.

Edit History: Corrected spellings. Added the following to clarify my question:

I understand the theory behind coupling and coheasion and why you should reduce one and increase the other. But we never got to code any examples in college. Also, while not covered in college, I do understand interfaces. However, I dont understand how to use them to reduce coupling.

Added a link to the article I refrenced above.

Edit 2: So far what I have now got is the following:

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

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

How do I now use this in the mainwindow code behind? I am guessing I should replace

Person x = new Person();

with

IPerson x = new Person(); 

Is this correct, and if so, is there anything else I need to do. The reason I ask is because I still dont see any reduction in code coupling figures reported by visual studio (infact, it increases it by 1 on the main window code behind).

Was it helpful?

Solution

Edit

I'm glad my answer helped a bit, let me update it slightly further. To use your question as a direct answer, all you would need to change is your field declaration from:

Person x = new Person();

to

IPerson x = new Person();

Your code-behind now know the properties and methods that are specified in your interface, and is a lot less coupled, as you could swap out new Person() for new Student() later-on. As long as the object implements the interface. Your code-behind should now work without any necessary changes.

Side note

I would recommend considering lazy-loading the x person, and also using a property with a more recognisable name. N.B. this doesn't answer your question, but it's just a suggestion. :)

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

De-coupling is when two, or more, code blocks should not depend on each other. Inversion of Control is when the coupling of objects is bound at runtime, thus allowing for much more flexibility, and therefore less coupling, of objects and their instances. Inversion of control is best use in conjunction with interfaces. The interfaces define that ClassA will do MethodX and have PropertyY. Our main object does not care what object is returned at run-time, as log as it can fulfil an interface, it's happy.

In your above example, you will want to interface your person class, maybe something like so:

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

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

Then, within your main method calls, instead of explicitly using a Person object, you will use an instance of an object that implements the interface IPerson. The "hooking" up of the interface and the object can be achieved by various different libraries which will help in setting up your dependencies. In my experience I've used StructureMap and Microsoft's Enterprise Library. They can be a bit fiddly to set-up, but once they are, you'll be able to do something like so...

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

I know this ins't a full answer, but hopefully it'll help a bit. :)

OTHER TIPS

Say you have an IPerson interface and several implementation (Person, Student, Teacher etc) and you have some code that simply needs to operate on an IPerson.

Having:

IPerson x = new Person();

in your code behind strongly couples it to the Person class.

Inversion of control comes into play by having the dependencies coming from outside instead of creating the inside the class.

This is normally achieved by using dependency injection - an IPerson being passed into the class instead of the class creating it directly. You can do that by passing an instance to the constructor (constructor injection) or as a property (property injection).

Service locator is another way to get dependencies without hard coding them - the pattern "locates" an instance for a type/interface.

An example of how to inject a dependency to a class:

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;
  }
}

Suppose you have a Person class that can load itself from database, get changed and send email when he or she died.

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

What you can see here is that this Person is actually doing three things (at the least!).

It knows how to talk to a database to load itself. It knows how to send email. It can change itself.

Any code, in theory if not practise, should be responsible for only one thing. To reduce the coupling between these components, you must pull them apart. Decouple them so they can work independantly.

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

In this contrived example, the Person has no idea how to load something from a database. Ignoring the fact that -loading- is something you should decouple too. Mail sending too has been decoupled, since you tell the Person.HaveDiedWillMail that you want to use a particular mailer (IMailer mailer).

Dependency injection, Service containers and such technology automatically find the components your Person needs/wants in order to function, sort of an extra layer on top of decoupling to make it easier to wire all the seperate parts together.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top