0

Suppose we have 2 classes: Car and Engine. Engine depends on Car - when the car is destroyed, Engine also. How to correctly express Engin's dependence on Car? The relationship is that the Engine class does not make sense outside of Car. In my opinion, injection of Engine indicates some independence from Car. Which Car constructor is correct in this case? With DI or without?

Example code:

interface IEngine { }

class Engine : IEngine { }

class Car
{
    private readonly IEngine _engine;

    public Car()
    {
        _engine = new Engine();
    }

    public Car(IEngine engine)
    {
        _engine = engine;
    }

}
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • Those 2 constructors say something about how Car depends on Engine, not the other way around. – H H Sep 29 '19 at 20:54
  • The dependence/independence of Engine does not have to be part of the class definitions. IoC means that there is another layer (eg a Factory) to manage this. – H H Sep 29 '19 at 20:58
  • To elaborate on @HenkHolterman: It is undesirable that `Car` knows (this particular, concrete) `Engine`; it has to know the class because it creates one. But `Car` should actually only know the interface `IEngine` which describes what a `Car` can rely on in any engine. Obtaining one should be left to a different agent, e.g. a factory, as Hank said, which returns only a reference to `IEngine`, of course. – Peter - Reinstate Monica Sep 29 '19 at 21:15
  • I don't agree with the Engine/IEngine distinction. IEngine is there to support testing and maybe a modular structure. It does not affect the dependency relation so directly. Interfaces are usually applied to Services, not Models. – H H Sep 29 '19 at 22:26

3 Answers3

0

You can use a nested class:

public interface IEngine
{
  void SomeMethod();
}

public class Car
{

  private class DefaultEngine : IEngine
  {
    void IEngine.SomeMethod()
    {
      throw new NotImplementedException();
    }
  }

  private readonly IEngine _engine;

  public Car()
  {
    _engine = new DefaultEngine ();
  }

  public Car(IEngine engine)
  {
    _engine = engine;
  }

}

Here are some explanations:

Nested Types (C# Programming Guide)

Why/when should you use nested classes in .net? Or shouldn't you?

0

Two thoughts:

  1. Architecture may be influenced by testability. Injection makes it easier to test a class because one can inject mocks or stubs.

  2. Be careful when assuming relations which are overly strict: Engines can certainly exist independently of cars, e.g. in factories, repair shops and in recycling. Similar for tires etc. (This is why I would not design it as an inner class, as Olivier suggested.)

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • A good point - it is clewer not to establish a strict and close relationship. In addition, DI is a standard ... – Piotr Klimaszewski Sep 29 '19 at 19:53
  • Point 2 is somewhat correct, but not because of realworld constraints. You could certainly create a model where an orphan Engine would be invalid. – H H Sep 29 '19 at 20:56
  • @HenkHolterman What do you mean? I mean, I can create all kinds of models, but how useful are they? What else if not the real world are we modeling? – Peter - Reinstate Monica Sep 29 '19 at 21:03
  • When you try to model the 'real world' you will never be done. Application models are set up to meet a finite set of requirements. – H H Sep 29 '19 at 22:23
0

Use the one with DI.

As for the analogy; if your car is responsible for building the engine; it's hard to change the engine at some point. Even if you don't change the actual type (e.g. gas to electric), changing the constructor will give you some issues.

Ofcourse the car does not depend on the engine and visa versa, well, the concrete type that is.

E.g.; You could have a show model car with a dummy engine. Or a test facility for your hyper modern engine.

So, if its possible: don't do new (especially when working with interfaces), but use DI. Especially; when you're dealing with actual hardware ;-)

Stefan
  • 17,448
  • 11
  • 60
  • 79