Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deal with temporal coupling?

Tags:

c#

oop

decoupling

I'm struggling because of this:

My classes have some methods that have temporal coupling. This is, some method MethodA has to be invoked first to "initialize" the data that MethodB needs to work properly.

I usually make the temporal coupling explicit by passing the offending dependency to "MethodB" as argument, like in this snippet:

private class SomeClass
{
    private string field;
    private int count;

    public SomeClass()
    {
        MethodA();
        MethodB(field);
    }

    private void MethodA()
    {
        field = "Something";
    }

    private void MethodB(string str)
    {
        count = str.Length;
    }
}

Although it makes things explicit I feel I'm doing something wrong. I end up having method that don't use fields at all (static methods!), so the class starts to seem less cohesive.

Is this the best way to do it? (losing cohesion by passing arguments)

EDIT: Regarding some answers that suggest using field as a parameter in the constructor or using the Builder Pattern to avoid invalid states: I cannot do that, because in my case I'm building a Parser. MethodA reads the input and sets the state depending on it (reading characters from a file) and then, MethodB is invoked. They have to be invoked in the correct order. That is the real problem: one should be invoked before the other.

like image 558
SuperJMN Avatar asked Apr 07 '15 19:04

SuperJMN


2 Answers

If you follow Anemic Domain Model, you can break your class and make it 2 smaller classes. You become aware of bad design because your current class violates SRP, in short it has 2 responsibility: 1 for handle the input process, 1 for process the input result.

Break it down so that ClassA will handle the input and returning result, then ClassB will take the result from ClassA as parameter, then process it. ex:

public class ClassA
{
    public string MethodA()
    {
        // read the input
        return "Something"; // or return the input
    }
}

public class ClassB
{
    private int count;
    public void MethodB(string str)
    {
        count = str.Length;
    }
}

If you find the use of both class is bothersome, use another aggregate service for that. ex:

public class ClassC
{
    public ClassA ClassA = new ClassA();
    public ClassB ClassB = new ClassB();
    public void Execute(){
        string result = ClassA.MethodA();
        ClassB.MethodB(result);
    }
}
like image 199
Fendy Avatar answered Sep 24 '22 08:09

Fendy


Fluent API's solve this kind of thing on public interfaces by not exposing dependent methods in the "builder" object until appropriate:

SomeClass someInstance = SomeClassBuilder(x=> { 
     x.MethodA().MethodB("somevalue");
});

This requires alot more plumbling because you need the builder object, as well as builder components such as an object that is returned from MethodA which exposes MethodB. This way the only way to call MethodB is to first call MethodA.

I'm not encouraging you to take this approach. It's probably overkill for many scenarios, but is important to be aware of this option in case you encounter a scenario where it is appropriate.

like image 20
AaronLS Avatar answered Sep 25 '22 08:09

AaronLS