Symfony2 Accessing a service from a non-service class - symfony

I want to access a service I've created (ServiceClass) from another class that I've created (ClassA). I've read a lot that the proper way to do this is to make ClassA a service and then inject ServiceClass, but class ClassA is not really a service in terms of functionality, it doesn't provide any global functionality, for me it's an Entity, so making it a service just so I can have access to other services doesn't seem right. Can anyone help me understand?

If it is an entity than it shouldn't need to know about any service. In ideal cases entities are just used to store data. You should rethink your class structure probably.
If you still want to go that way anyway, your only option is to declare it as a service or inject/set services when instantiating your class.
And yes, please provide code so we can suggest you what to do. This is just blind guessing because you provided very little info.

Related

Injection Dependencies Layers Application / Domain / Repository

In an application using the DDD concepts I am in doubt about who could inject (dependencies) into the constructor of a given class if there is any standard for it.
For example, between the Application, Domain, and Repository layers.
1) A ClientAppService (Application layer) that needs to inject user, should I inject UserApplicationService and from it call UserService (Domain) or inject UserService directly in ClientApplicationService?
2) In the ClientService (domain) should I inject UserService and from it call UserRepository or could I inject UserRepository directly into ClientService?
I'm concerned about cyclic reference if I'm injecting peer classes.
But I also think that I should not inject the Repository of another Entity, because often the methods of the repository have a rule in the service that must be called previously.
Has anyone ever had this question, how do you usually handle it?
Thinking about separation of concerns and allocation of responsibilities, you should inject exactly what your artifact depends upon. This may sound a little obvious, but it goes a little deeper.
Considering your (2) example:
In the ClientService (domain) should I inject UserService and from it call UserRepository or could I inject UserRepository directly into ClientService?
You probably should first ask yourself which capability does your ClientService depend upon?
If it (ClientService) cares about being able to find user from information it (ClientService) currently possesses, it should probably receive the UserRepository directly and be able to find the user on its own.
If it (ClientService) needs a user, but it doesn't possess the information needed to find the user (this information is currently on application layer level), maybe ClientService should receive the User domain object directly, with the repository being used straight from application level.
If it (ClientService) needs some kind of domain-relevant functionality from UserService as part of its operation, then, in that case, the UserService might be directly injected into ClientService.
Other possible discussion on this topic might whether you really need all those Domain Services of if you would be better calling rule-rich Entities/Aggregates straight from the Application Layer, it might make your overall design, injection patterns and boundaries simpler.
Also, many times, you might want to inject factories for your artifact rather than the instantiated ones directly.
Another point might be made about:
But I also think that I should not inject the Repository of another Entity, because often the methods of the repository have a rule in the service that must be called previously.
This might be evidence of some confusion inside your domain. The role of a repository should be around the lines of "finding your domain entity from the universe of possible entities". In that sense, a UserRepository enables you to find users from the users existing in your universe so it should be a pretty isolated operation and shouldn't depend on services or other entities. If a user exists, it should be "findable" (and persistable, as it goes both ways) from the UserRepository.
In that case, you shouldn't worry about "injecting UserRepository in ClientService" from a dogmatic point of view. If the operation in your client service needs to find and use a User Entity, it should be alright for you to do so. What you might worry about is whether your entities/aggregates are well designed or if you have some kind of misplaced responsibilities that might be triggering this "feeling" of "I shouldn't be injecting this into that".
Domain Entities and Value Objects almost never use constructor injection.
This is motivated by separation of concerns; the responsibility of the objects in the domain model is to manage their own in memory representations.
Other capabilities that they may need to do their work are passed to them as arguments.
The typical mechanism for this is the "domain service", described by Evans in chapter 5 of the blue book.
To sketch an example - suppose my order aggregate needs to update its quote when the line items change. I might pass in as an argument an interface that accepts a SKU and returns a Price. As far as Order is concerned, that lookup is happening "somewhere else". It doesn't care about the details. The implementation might load up another aggregate to look up its current state, or send a message to some remote system, or hard code an answer.
Domain Service implementations will often have injected dependencies on capabilities provided by the application or infrastructure layers.

Unity - Use concrete type depending on user choice

I have a small app (Win Forms) where I have two different repositories (SQL Server and Redis) both implementing a interface IFilterRepo.
I also have a service class that depends on the IFilterRepo. The client (the Win Form) call the service to access filter data.
I want the client to have two radio buttons where a user can choose which repo to use. And here comes my dilemma. How should I tell the service which concrete class to instantiate as IFilterRepo? I mean, ALL Unity registrations and references to it shall be done in the composition root. Is that "rule" really possible in this case?
This is a common question, and the answer is generally to use an Abstract Factory.
Here is a good article on the subject (I link this all the time, but I didn't write it):
http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/
As noted in the article, you can make the factory part of the composition root, so that calling container.Resolve() inside the factory doesn't violate that rule.
Edit
You would register different implementations of the service using a name (string):
http://msdn.microsoft.com/en-us/library/ff648211.aspx
myContainer.RegisterType<IMyService, CustomerService>("Customers");
And then your factory would resolve by that name:
public IFilterRepo Create(string myName)
{
return myContainer.Resolve<IFilterRepo>(myName);
}
Edit 2
The question you asked in your last comment is a bit much to answer here, but in brief: your factory itself would implement an interface, and would be resolved and registered via the container.
As a general matter, I would not recommend accessing a repository directly from the code behind--I would at least look at having a layered architecture (or better, an Onion architecture, which works very well with DI).
Finally, I have not done WinForms development in years, but I don't think it fits perfectly with using a container/Composition Root, since you don't have full control over the lifecycle of your objects (you can't inject services into your form constructors). The same is true of ASP.Net Webforms. So you may have to use property injection for your factory and other services needed in your form, or just resolve the factory directly via calling a static instance of the container (container.Resolve()). This is imperfect, and goes against the idea of having a Composition Root, and more toward service location.
You might google keywords "Unity WinForms" and/or "[OtherDIFramework] Winforms" to get some ideas of how to structure your code.

Dependency Injection - What is the best approach?

Scenario
Talk about Symfony2. I have an entity with his setters and getters. One of this setter is a bit particular, because have to retrieve some related object, do something and write back ralationship.
What came in my mind, for retrieve those objects, is to use the entity manager and repository related to my entity.
Problem
I haven't the possibility to access Entity Manager directly from entity. One possible solution is to inject the E.M. into this entity but, as far I know, dependency injection is not recommended for entity.
Possible solution
Write a service, inject into it E.M., use service into entity.
Please pay attention to this: I can't instantiate my entity elsewhere because a Bundle (SonataAdmin) is responsible for doin' that.
Is this a good way to do it, or exists a better method?
Let's say you're working with the Entity 1. You need to get entity 2.
I would create a service, with a function which get Entity 1 as a parameter. Give E.M. to this service, and get Entity 2.
Entity file isn't made to such a thing, services are here to help you.

Understanding Symfony2 services

I'm quite new to Symfony 2 and I'm moving to advanced topics like services. When should an object be a service?
For example, say that you have a facade object for making a call to a REST service. This class needs a username and password. Would it be correct modeling that class as a global service? Even if it's used only in a portion of the whole project?
# app/config/config.yml
parameters:
my_proxy.username: username
my_proxy.password: password
services:
my_proxy:
class: Acme\TestBundle\MyProxy
arguments: [%my_proxy.username%, %my_proxy.password%]
Definition taken from the Symfony2 glossary:
A Service is a generic term for any PHP object that performs a specific task. A service is usually used "globally", such as a database connection object or an object that delivers email messages. In Symfony2, services are often configured and retrieved from the service container. An application that has many decoupled services is said to follow a service-oriented architecture.
I think your example is a perfect candidate for a service.
You don't want to copy construction code to all places you need your API client. It's better to delegate this task to the dependency injection container.
This way it's easier to maintain (as construction happens in one place and it's configurable).
It's also more flexible as you can easily change the API client class without affecting code which uses it (as long as it implements the same interface).
I don't think there's a golden rule. But basically all classes implementing a task are good candidates for a service. Entities on the other hand are not as they're most often just data holders.
I always recommend Fabien's series of articles on the subject: http://fabien.potencier.org/article/11/what-is-dependency-injection
Yes, because this will spare you the configuration part. You're not going to fetch the username and password and give it to the constructor each time you need this class.

How to access 'templating' service not in controller

Ok, so the problem is:
I've got some 'order' entity, and it has 'status' property. On changing status, i wanted some other objects to be informed of this event, so i've decided to use Observer pattern. One of the observers notifies clients via email. Now i want to render Email text's from some of the twig templates. As i get from the Book, rendering templates in controllers are done with 'templating' service.
So the question as it follows: How can i access 'templating' service in my Observer class?
Specification:
I was advised, to implement my Observer as a service, but i'm not sure 'bout that. I've tried to solve this problem, and here is my options:
Use Registry. Solution that is straight and hard as rail. I guess it misses the whole point of DI and Service Container. Huge plus of this solution, is that i can access all common services from any point of my application.
To pass needed services from the context via constructor, or via setters. This is more like in Sf2 spirit. There comes another list of problems, which are not related to this question field.
Use observers as a service. I'm not really sure 'bout this option 'cos, in the book it is written, that service is a common functionality, and i don't think that observing entity with number of discrete properties is a common task.
I'm looking for a Sf2 spirit solution, which will be spread over whole project, so all answers with an explanation are appreciated.
As with any other service in a Symfony2 project, you can access it from within other classes through the dependency injector container. Basically what you would do is register your observer class as a service, and then inject the templating service into your observer service. See the docs for injecting services.
If you're not familiar with how Symfony handles dependency injection, I'd suggest reading that entire chapter of the documentation - it's very helpful. Also, if you want to find all the services that are registered for application, you can use the console command container:debug. You can also append a service name after that to see detailed info about the service.
Edit
I read your changes to the question, but still recommend going down the DI route. That is the Symfony2 spirit :) You're worried that your observer isn't common enough to be used as a service, but there's no hard rule saying "You must use this piece of code in X locations in order for it to be 'common'".
Using the DIC comes with another huge benefit - it handles other dependencies for you. Let's say the templating service has 3 services injected into itself. When using the DIC, you don't need to worry about the templating service's dependencies - they are handled for you. All you care about is telling it "inject the templating service into this other service" and Symfony takes care of all the heavy lifting.
If you're really opposed to defining your observer as a service, you can use constructor or setter injection as long as you're within a container-aware context.

Resources