Replacement for Dependency Injection Container in Rails - ruby-on-rails

I have read dozens of articles about this and still have some questions.
How are services used in multiple parts of the system? For example, I have a permissions component that is used by several other classes during a request. Right now, I have made it a singleton. I have been using singletons as the entry point to portions of my domain (various services) that need to be reused during a request. This seems to be the only way I can access these services in different parts of the system without reinstantiating them or without throwing them in a global variable. In other systems, I would make it a normal class and set it's lifecycle to "request". The container would make sure that it is shared within the request and release it for garbage collection.
I have thought about using a service locator which stores services in Thread.current. But this feels like I'm getting desperate.
The main way I've seen that people accessing these dependencies is to wrap the dependency in a method:
class A
def some_dep
SomeService.instance
end
end
In tests, some_dep is overridden to return a mock or whatever. This seems like the best so far but still feels hackish.
My options for using services within a request seem to be:
1) Put them in a global variable / Thread.current.
2) Use a service locater.
3) Pass dependencies around manually (complete disaster).
4) Singleton.
Two questions:
1) What is the best approach for making services available to multiple parts of the system without reinstantiating?
2) What is the best approach for a class to manage those dependencies?
Note:
I understand that I can put reusable functionality into modules. IMO, however, modules are great for purposes of staying DRY but not for carrying state around the system (i.e. which tenant you're on in a multitenant application).

Related

Dependency injection - trying to avoid using a service locator

Following the guidelines I read in:
https://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container
I want to try and avoid using a service locator.
But on the other hand, I don't register all the types in the startup.cs file. I don't think this is right that all these internal types are referenced in the main startup.cs
I currently have a factory class that has a collection of builder classes.
Each builder class is in charge of creating a specific object.
I don't want to create all these builder classes in advance as I might not need to use them and creating them is a bit heavy.
I saw an example of how to achieve this in the link above. However the startup.cs class needs to know all these builders. I don't think this is appropriate, I'd rather have the factory class be the only one that is exposed to them. I was trying to understand if there is some kind of func/action method that I can inject from the startup.cs file into my factory class. This func/action will be in charge of creating/registering the builders and then I can activate this func/action within the class factory. I'd like this func/action to receive the interface/class/maybe name of the builder but using generics isn't working. I searched a lot and didn't find any solution so I assume this is not possible.
Seems I have 2 options:
1. Use service locator. This way only the factory class will know the builders. However if in the future, if I want to change the DI I need to "touch" the factory class (I'm contaminating the factory class). Wanted all the DI code to be located only in the startup.cs class.
2. Register the builders in the startup.cs but now the startup.cs is aware of the builders. This kinda couples the code, not really single role of responsibility
It would have been great to inject the factory class a func/action from the startup.cs that would do the registration but the factory class itself activates it.
Is this possible?
I want to try and avoid using a service locator
Great, because the Service Locator is an anti-patttern.
don't register all the types in the startup.cs file.
You should do your registrations in one single 'area' of your application: the start-up path. This area is commonly referred to as the Composition Root (the place where object graphs are composed).
I don't think this is right that all these internal types are referenced in the main startup.cs
No matter how you design it, the startup assembly is the most volatile part of the system and it always depends on all other assemblies in the application. Either directly or transitively (through another referenced assembly). The whole idea of Dependency Injection is to minimize the coupling between components and the way to do this is to centralize coupling by moving it to the Composition Root. By making types internal however, you are decentralizing object composition and that limits your flexability. For instance, it becomes harder to apply decorators or interceptors for those registered types and control them globally. Read this question and its two top voted answers for more information.
I don't register all the types
The concern of having a Composition Root that is too big is not a valid one. One could easily split out the Composition Root into multiple smaller functions or classes that all reside in the startup assembly. On top of that, if you read this, you'll understand that registering all types explicitly (a.k.a. "Explicit Register") is typically pointless. In that case you're probably better off in using DI without a Container (a.k.a. Pure DI). Composition Roots where all types are registered explicitly are not very maintainable. One of the areas a DI Container becomes powerful is through its batch-registration facilities. They use reflection to load and register a complete set of types in a few lines of code. The addition of new types won't cause your Composition Root to change giving you the highest amount of maintainability.
I don't want to create all these builder classes in advance as I might not need to use them and creating them is a bit heavy
Creation of instances should never be heavy. Your injection constructors should be simple and composing object graphs should be reliable. This makes building even the biggest object graphs extremely fast. Factories should be reduced to an absolute minimum.
TLDR;
Register or compose your object graphs solely in the Composition Root.
Refrain from using the Service Locator anti-pattern; Whole applications can (and should) be built purely with Constructor Injection.
Make injection constructors simple and prevent them from doing anything else than storing their incoming dependencies.
Refrain from using factories to compose services, they are not needed in most cases.

Refactoring large application for ObjectFactory.GetInstance to use nested containers

I have a large application which uses the old way of getting instances using ObjectFactory.GetInstance().
Now I want to move to application to the more correct way of injecting dependencies using constructor injection. However, it is almost impossible to convert all code at once (some static classes use ObjectFactory.GetInstance, other services do not have constructors with all dependencies, ...).
I was wondering if there is a way of replacing ObjectFactory.GetInstance calls with an replacement that uses the current nested container, e.g. replacing all ObjectFactory.GetInstance with Ioc.GetCurrentNestedContainer().GetInstance, to get it quickly up an running.
But how would I could I implement Ioc.GetCurrentNestedContainer to return the currently active nested container?
I can not inject IContainer in all these classes (some are static or have no corresponding
constructor), so they can not use constructor injection (yet).
DI is used in MVC, WCF, and Task based scenarios in this application.
Whilst I can't talk about WCF and task based scenarios, I can offer my recommendation for MVC (having spent time looking the options to a similar problem myself.
The solution to I've come across and ultimately settled for after seeing recommendations by StructureMap's creator, is to have a HttpContext bound nested container created on each request and stored within HttpContext.Items. From here you can reference the container by casting the instance stored within HttpContext.Items to an IContainer.
Infact, this is the same solution used within the StructureMap.MVC5 nuget package.
With this solution in mind, there's nothing to stop you replacing the ObjectFactory with with your own factory that returns the nested container from HttpContext.Items.
Update:
If HttpContext isn't available to you then the only other options I'm aware of is to create your own instance of the object factory that creates a new container and stores it in a Lazy<T> as suggested here and on the StructureMap's Google Groups page here.
I was going to suggest possiblity posting this question on the StructureMap Google Groups, but I see you've already done that. As an avid StructureMap user I'm keen to see what other suggestions arise from your post so I will be watching closely.

Multitenancy, help understand concept of WorkContext

While trying to understand how a multitenant environment works, I've came up to the concept of WorkContext.
Introduction:
In a multitenant environment Tenants are Clients which share similar functionality, and run under a single instance of a ROOT application. In order to be able to add tenant specific functionality I came across a conclusion that Dependency Injection is the right solution for my case.
Each tenant should have it's own IoC Container, in order to be able to Resolve its dependencies at runtime.
But when trying to implement the theory I have some troubles with the wrapping out all tenant specific data.
While digging the internet it seems that there must exist some sort of a TenantContext. So each tenant has it's own isolated Context.
The problem is that I don't understand the true LifeCycle of such a Context.
Question 1:
What is the lifecycle diagram of a tenant specific WorkContext, Where should I store it, When it should be created/disposed ?
NOTE: If the question 1 is provided, there is no need to answer the above one.
Suddenly I've found Orchard Project which seems to be a true masterpiece. Inside Orchard, the Context i'm talking about is called WorkContext.
I'm trying to understand the concept of WorkContext in Orchard Project. As far as I understand, here are some thoughts about WorkContext:
The WorkContext is a per-request lifetimeobject.
It is stored in HttpContext.Items (also there is a thread static implementation..).
It wraps the tenant IoC scope (ShellContext -> ShellContainer).
It is accessed through IWorkContextAccessor.
What I don't understand is:
Question 2:
Why do we need to include IWorkContextAccessor instance in route's DataTokens like this: routeData.DataTokens["IWorkContextAccessor"] = _workContextAccessor; ? Is this really necessary?
Kind of big question :-).
Firstly, WorkContext is more or less an abstraction of the HTTP context. A WorkContext lives as long as its work context scope lives (see IWorkContextAccessor that you can use to create work context scopes) so actually you can have multiple work contexts per request and you can have a work context independently of a request too (this happens in background tasks).
Such work contexts are thus externally managed contexts and thus somehow have to "travel" along with their scope until the latter is terminated: in Orchard the WC is either carried in the HTTP Context or in a thread static field (what is not good enough and should be changed).
Thus basically a work context scope is the lowest dependency scope commonly used. It also has a parent, the shell's scope: this is the shell context (or more precisely, its lifetime scope). You can access a shell's (what is most of the time equal to a tenant) context through IOrchardHost.GetShellContext(). Work context scopes are actually created from the shell context's lifetime scope.
This also has a parent BTW that is the application-wide HostContainer.
Most of the time you don't have to manage the WC yourself since the ambient WC around requests and background tasks are managed for you.
Regarding your second question: I'm not entirely sure about this but AFAIK passing the WCA to the routeData just serves as a workaround to be able to access it (and thus, Orchard services) from strange places like HTML helpers and attributes that are not resolved through the DI container.
Edit: also added this to the Dojo Library, redacted and improved: http://orcharddojo.net/orchard-resources/Library/Wiki/WorkContext

Grails: Services VS Groovy classes

Documentation says:
The Grails team discourages the
embedding of core application logic
inside controllers, as it does not
promote re-use and a clean separation
of concerns.
I have one API controller and a few Groovy classes in src/groovy folder. Those classes just implements my application logic so actions in API controller works in this way:
//index page
def index = {
render new IndexApi().index(params) as JSON
}
I'm curious - is there any reason to move my application logic from plain groovy classes into services ?
Actually services are not just about transactions. Services are great for zero-config injectable singleton components, and they can can be reloaded without restarting the whole grails environment, AND they can be discovered as artefacts and hence automatically exposed with remoting plugins.
If you want transactional behavior you should put your logic in the Services. Else you would have to take care about it yourself, which is not in the spirit of using Grails.
Being not a grails expert myself, I put my 'not transactional' classes outside the service layer, like builder classes, helpers, and other logic that is not transactional but used from the service layer.
There are three reasons:
It makes the controller smaller -> easier to understand and maintain
It makes you logic easier to test.
You really don't want to manage your transactions manually.
If you would put everything in the controller, you would need to create the Web runtime to be able to run any test. If your logic is outside, you can copy the data you need from the HTTP request and all the other sources and just call the code. So the logic isn't depending on HTTP sessions, requests or anything else you don't want to.
For example, to test JSPs, you need a HTTPRequest. For a request, you need a HTTPSession and a JSPWriter. Those need a session context. So just to be able to run a single test, you need to set up and initialize a whole bunch of classes. And all of those are interfaces and the implementations are private. So you must implement the actual methods (all 300 of them) yourself. And you better get this right or your tests won't test what you want.

What is the correct layer to configure your IoC container when using a service layer?

I have a medium sized asp.net MVC app. It consumes a service layer that handles all the repository use, calling domain services, etc. My controller actions are very slim -- they basically call a service class, get a response and show that respose. Most components are interface based with some poor man's DI. The app is growing, needs better testing support, and starting to call out for an IoC container.
Everything I read (such as this SO question) states that I should configure the IoC at the application root. This makes sense to me if I were using repositories right from my controller actions and needed DI at the controller level, but I'm not. It seems like I'd want my composition root in my service layer. I keep thinking that I don't want my web.config (or another config) at the UI layer even mentioning/seeing/hearing about a repository, credit card processor, etc.
Am I thinking about this the right way or do I just need to get over it?
I have the same situation as you and I tackle it as follows.
The general rule I use is what ever has a global.asax or something similar, it needs to execute the code that registers the IoC components. Another way of putting it is that you need to run it one for each different process that is running (i.e. the website is in one process and the service is in another).
In my case I do this once for the mvc website global.asax and again for the server. In this case the registrations that get made would be different between the service and the website.
In addition I do one more thing. Due to the fact that I reuse components between the mvc app and the service (i.e. logging) I have a third core component that registers the core IoC components for the system and this component is called by the both the website and services registrations. Hence I anything that is common between the service and the website go into the core registration and then anything that is different goes into the 'interface' specific registration.
Hope that helps.
You just need to get over it :)
Having your Composition Root in the application root doesn't require you to have a lot of DI Container stuff in web.config. You can if you will, but it's optional. What is not optional when putting the Composition Root in the application root is that you need to have some DI code in Global.asax.
You may find it irrelevant because your Controllers are so thin, but that's not the real point. The actual point is that you (the abstract 'you') want to postpone coupling classes until the last responsible moment. The earlier you couple types, the less flexibility you have.
If you couple classes in the service layer, you make an irreversible decision at that point. If it later turns out that you need to compose those services differently, you can't - not without recompiling, that is.
If there was a major benefit of doing it, I can understand why you would want to, but there isn't. You may as well wait composing all components untill you absolutely must do so - and that's in the application's entry point.
Coming from a Java perspective, I use the Spring framework for my IoC container. With it, the container really is application-wide. Although you can have different configuration files for different layers (a persistence config file, a services config file, a controller config file, etc), all of objects (beans in Java lingo) go into the container.
I think this still ok though because there is no coupling between classes as you mentioned. A view does not need to know about a credit card processor, just because they are in the same IoC container. These classes will receive (by injection) only the dependencies they need, and are not concerned with other objects in the container.

Resources