Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy initialization of dependencies injected into constructor

I have a class where I am injecting two service dependencies. I am using Unity container.

public interface IOrganizer
{
    void Method1();
    void Method2();
    void Method3();
}

public class Organizer : IOrganizer
{    
    private IService1 _service1;
    private IService2 _service2;

    public Organizer(Iservice1 service1, IService2 service2)
    {
        _service1 = service1;
        _service2 = service2;
    }

    public void Method1()
    {
        /*makes use of _service1 and _service2 both to serve the purpose*/
    }

    public void Method2()
    {
        /*makes use of only _service1 to serve the purpose*/
    }

    public void Method3()
    {
        /*makes use of only _service2 to serve the purpose*/
    }
}

While it all works, but somehow it smells because when I am only invoking Method2 and Method3, unity unnecessarily creates an instance of another not required service. The code snippet here is just a sample for explanation purposes. In a real situation object graph of these injected services itself is quite deep.

Is there a better way to design and address this kind of scenario?

like image 687
rahulaga_dev Avatar asked Mar 08 '18 18:03

rahulaga_dev


People also ask

Is it difficult to inject dependency by constructor?

Frameworks that apply the Constrained Construction anti-pattern can make using Constructor Injection difficult. The main disadvantage to Constructor Injection is that if the class you're building is called by your current application framework, you might need to customize that framework to support it.

How does lazy initialization work?

Lazy initialization of an object means that its creation is deferred until it is first used. (For this topic, the terms lazy initialization and lazy instantiation are synonymous.) Lazy initialization is primarily used to improve performance, avoid wasteful computation, and reduce program memory requirements.

What is lazy initialization in Java?

In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. It is a kind of lazy evaluation that refers specifically to the instantiation of objects or other resources.

Which constructor does dependency injection use?

Constructor Injection: In the constructor injection, the injector supplies the service (dependency) through the client class constructor.


2 Answers

I think your sense of smell is competent. Most people would happily code like this without a second thought. I do agree, though, that there's a few code smells in a design like outlined in the OP.

I'd like to point out that I use the term code smell as in Refactoring. It's an indication that something may not be right, and it might be worthwhile to investigate further. Sometimes, such investigation reveals that there are good reasons that the code is as it is, and you move on.

There's at least two separate smells in the OP. They're unrelated, so I'll treat each one separately.

Cohesion

A fundamental, but often forgotten concept of object-oriented design is that of cohesion. Think of it as a counter-force to separation of concerns. As Kent Beck once put it (the exact source escapes me, so I paraphrase), things that vary together, belong together, while things that vary independently should be separated.

Without the 'force' of cohesion, the 'force' of separation of concerns would pull code apart until you have extraordinarily small classes, and even simple business logic is spread across multiple files.

One way to look for cohesion, or lack thereof, is to 'count' how many class fields are being used by each method of a class. While only a crude indicator, it does trigger our sense of smell in the OP code.

Method1 uses both class fields, so is no cause for concern. Both Method2 and Method3, on the other hand, use only half of the class fields, so we could view that as indication of poor cohesion - a code smell, if you will.

How can you address that? Again, I wish to emphasise that a smell isn't guaranteed to be bad. It's only a reason to investigate.

Still, if you want to address the issue, I can't think of any other way than breaking up the class into several smaller classes.

The Organizer class in the OP implements the IOrganizer interface, so technically, breaking up Organizer is only possible if you can also break up the interface - although you could write a Facade, and then delegate each method to a separate class that implements that particular method.

Still, the presence of an interface emphasises the importance of the Interface Segregation Principle. I often see code bases exhibit this particular problem because the interfaces are too big. If at all possible, make the interfaces as small as possible. I tend to take it to the extreme and define only a single member on each interface.

From another of the SOLID principles, the Dependency Inversion Principle, follows that interfaces should be defined by the clients that use them, not the classes that implement them. Designing interfaces like that often enables you to keep them small, and to the point.

Recall also that a single class can implement multiple interfaces.

Performance

Another concern regarding the design in the OP is of performance, although I agree with NightOwl888's comment that you're likely in micro-optimisation territory.

In general, you can compose even large object graphs with confidence. As NightOwl888 also suggests in the comments above, if a dependency has Singleton lifetime, it makes little difference if you inject it, but then end up not using it.

Even if you can't give a dependency like _service2 Singleton lifetime, I again agree with NightOwl888 that object creation in .NET is fast to the point where you almost can't measure it. And as he also points out, Injection Constructors should be simple.

Even in the rare case where a dependency must have Transient lifetime, and for whatever reason creating an instance is expensive, you can always hide that dependency behind a Virtual Proxy, as I also describe in the article about object graphs.

How you configure all that in Unity, I no longer remember, but if Unity can't deal with that, choose another method of composition, preferably Pure DI.

like image 63
Mark Seemann Avatar answered Sep 28 '22 06:09

Mark Seemann


As long as you're using Unit 3 or higher, you don't need to do anything special for resolving lazy.

You register your type like you normally would:

container.RegisteryType<IMyInterface>()...;

And then change the constructor to require lazy:

public class MyClass
{
  public Lazy<IMyInterface> _service1;

  public MyClass(Lazy<IMyInterface> service1)
  { 
    _serivce1 = service1;
  }
}

Then call whatever you method you need:

_service1.Value.MyMethod();
like image 24
Erik Philips Avatar answered Sep 28 '22 05:09

Erik Philips