-5
public Interface IFoo()
{
    void DoSomething();
}

public class Foo
{
    private IFoo _ifoo;

    public Foo(IFoo foo)
    {
        _ifoo = foo;
    }

    public void Bar()
    {
        // execute
        _ifoo.DoSomething();
    }
}

In the above example - I am using dependency injection via interfaces decoupling a dependency

VS

In this scenerio are the classes tightly coupled by using a class with static methods?

public class Foo
{
    public static void GenerateSomeFoo(){
        //do something here
    }
}

public class FooBar 
{
    public void Bar()
    {
        var somevariable = 123;
        Foo.GenerateSomeFoo();
    }
}
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
Harry
  • 3,031
  • 7
  • 42
  • 67
  • what is the question? – Patrick Artner Feb 18 '18 at 18:57
  • 2
    Yes they are. FooBar can't exist without Foo – Marcus Höglund Feb 18 '18 at 18:57
  • is it worth decoupling in a simple scenario like above? the latter just appears to have less work involved initially of course – Harry Feb 18 '18 at 18:59
  • The scenario is too simple and too artificial to tell. But you revert the IoC and make it less testable. – H H Feb 18 '18 at 19:10
  • If you don't write tests then static methods are fine. If you don't have many implementations and don't unit test, then you don't need interfaces. – FCin Feb 18 '18 at 19:12
  • **Close Voters:** There is only one question being asked here, and it is not opinion-based. While for the most part I agree with all of the other comments and answers here, they all seem to have completely missed the question that is actually being asked, making the advice off-topic. – NightOwl888 Feb 18 '18 at 20:30
  • I agree the latter becomes less testable, however if you we have a simple method or class - who always just serves one purpose I was wondering if it was overkill - I agree around the testing aspect. – Harry Feb 19 '18 at 09:08
  • @FCin I am writing unit tests - I looked at this one method in a single class and I know it will probably not change during the duration of the application. So wondered whether it was worth putting it through IOC approach for as it seemed like a lot of work – Harry Feb 19 '18 at 09:09
  • 1
    I wrote a couple of personal projects where from beginning I started isolating every possible thing, because I was following TDD. It was a nightmare. Simple class with a single method had to have its own interface, factory, interface for factory etc. Now, I only isolate things such as services which I want to mock. If something requires 3 classes to mock it I just use microsoft fakes or reflection to mock it. All "nasty" stuff is in a method in tests and it is not as bad as making 3 classes for a single method. – FCin Feb 19 '18 at 09:26

3 Answers3

3

are the classes tightly coupled by using a class with static methods?

Yes.

In your example, Foo.GenerateSomeFoo() is being called inside of the FooBar class, which makes it more difficult to swap the implementation of GenerateSomeFoo() if you need to use an alternate implementation for some reason. Therefore, FooBar is tightly coupled to Foo.GenerateSomeFoo().

Static methods are by their nature tightly coupled to the code that calls them, so you should avoid putting any logic in static methods that could now or in the future receive injected dependencies.

However, that doesn't mean that you should never use static methods. Extension methods in particular are extremely useful. It is just not very practical to inject dependencies into them, and they tend to make testing more difficult.

Steven
  • 166,672
  • 24
  • 332
  • 435
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • I see thanks for this, in the end I have gone with using Dependency Injection as above - and declared a static method - which gets called inside the method implementation. – Harry Feb 19 '18 at 09:11
0

Regarding the namings you have used, you create a misconfusion. Someone would expect a class named Foo to implement the interface IFoo and not inject an object that has implemented IFoo in Foo's constructor.

As far as the use of static method GenerateSomeFoo, it makes the code less helpful to test it, since now you depend on a concrete implementation.

Another approach would be this:

// This is the contract.
public interface IFoo
{
    void DoSomething();
}

// This is the implementation
public class Foo : IFoo
{
    public void DoSomething()
    {
        // ....
    }
}

If class Foo needs another object to implement their methods, you could inject it in it's constructor. For instance let's suppose that it needs a IBarRepository. Then the class Foo would be declared as below:

public class Foo : IFoo
{
    private readonly IBarRepository _barRepository;

    public Foo(IBarRepository barRepository)
    {
        _barRepository = barRepository 
                         ?? throw new ArgumentNullException(nameof(fooRepository));
    }

    public void DoSomething()
    {
        // ....
    }
}

Why the above approach is more preferrable ? Let's suppose that the definition of IBarRepository is the following:

public interface IBarRepository
{
    IEnumerable<Bar> GetAll();
}

and that a class that implements this interface makes a call to a database to retrieve Bar objects. Using the interface as a dependency you can test your code quite easily using a mock of this interface, a thing that is not possible when you rely on static class or methods.

Christos
  • 53,228
  • 8
  • 76
  • 108
0

Indirection is a matter of strategy. Having a strategy means you have at least a remote idea about what you want to do in the future. From your simple example I cannot recognize any strategic implications.

There is the saying "There ain't no problem in the world that can't be solved by another level of indirection". You can turn this upside down: even if you don't have a problem you can solve it by another level of indirection... Only because there is a hammer beside you that doesn't mean you have to hammer anything in your neighborhood.

Using an interface to decouple concepts can of course be helpful. It can also be pointless if all you do is call an empty method.

oliver
  • 2,771
  • 15
  • 32
  • this is what I was thinking, and which lead me to a question - we have a simple method which will never change so was it worth doing the DI approach. – Harry Feb 19 '18 at 09:11