In developing an n-tier application, I seem to have hit a scenario where one service say service A needs to consume a method in service B. I do not want to duplicate logic but it does not seem like I should not have services calling one another either. What is the best way to handle this situation without violating any rules? I am thinking about taking the common method out of service B and add to another class and have both services inherit from this class.
Dependency Injection.
Service A expects a well defined service to be injected into it that is expressed with an interface. This way Service B can be injected as well as any other service implementing the same contract.
Related
I have an MVC project which has two services an OrganisationService and an AgreementService, my problem is that some of the organisations belong to a group/parent structure, when this is the case I need to get all agreements that belong to any of the organisations within the group.
I already have a method in my OrganisationService that can return a list of all the ids for organisations within the structure:
IEnumerable<int> GetRelatedOrganisationIds(int id)
I could create a method in the AgreementService which accepts the result of this but then I would need to inject both services into my controller and call them in turn e.g.
GetAgreementsByOrganisationIdList(IEnumerable<int> organisationIdList)
Is it ok to inject the OrganisationService into the AgreementService so that it can do the work itself? For example the following method would call GetRelatedOrganisationIds internally:
GetAgreementsByOrganisationId(int id)
Another reason I would like to inject it into the AgreementService is that I would not need to remember to check if the organisation was in a group/parent relationship and look up the ids each time I wanted to get a list of agreements.
I also thought of creating an OrganisationGroupParentInformationProvider and injecting that into the AgreementService instead, I may have spent far too much time thinking about this one.... how would you do it?
Yes, it would be fine to inject one service into the constructor of another. However, you might want to consider creating an interface for OrganisationService and having your AgreementService depend upon that abstraction, instead.
Another approach would be to create a new service with dependencies on both AgreementService and OrganisationService, and have that new service carry out the responsibility. The new service would of course be injected into your controller.
For guidance, consider whether having it all under AgreementService would violate the Single Responsibility Principle and/or Interface Segregation Principle. If so, make a new service.
Is it ok to inject the OrganisationService into the AgreementService so that it can do the work itself?
That wouldn't be injecting it. That would be making it a dependency to it. Regardless, I would say the way you have it is a better architecture because it's more testable. By having the agreement service call the organizations service on its own it's certainly less testable because somewhere you're going to have to inject an instance of the organization service.
I have the following layers currently in my application:
API
AppService Layer
Domain Model
Repository
The lower (2) layers (domain and repository) offer almost total reuse across business needs so I thought of exposing at least my domain model as a service, possibly a WCF service. Basically the domain entity data, behavior, and persistance are reusable and I need a way to centrally expose this.
I have read the following (Sharing domain model with WCF service) and ones similar that indicate for good reason why not to expose domain entities directly via WCF. Most of the examples indicate to create data contracts to expose domain data and then have mapping mechnisms to map between the domain and DTO (Data Contract) data. So far so good.
If I have a method in my domain layer like below, how do I expose it via the new WCF service? I thought I would only expose DTOs and therefore how do I also expose the shared/common domain behavior I want to reuse across processes?
public int ProcessSomeRule(string param1, string param2)
If the answer is to create a method on the WCF service that acts as a proxy still not exposing the ProcessSomeRule method directly, I'm cool with that but that spawns another question. The purpose of this abstraction and creating a method on the WCF service named for example ProcessSomeRuleWCF(string,string) that just turns around internally and calls the domain method seems to still be coupled and not offer a pure abstraction. It will still be sensitive to signature changes.
I read that by not exposing the methods directly, we can make changes internally without having to modify the contract interface. OK, this sounds great by definition, but if my internal method needs an additional parameter and now has the signature `ProcessSomeRule(string, string, string), guess what? My contract interface method will now break because it's missing the 3rd parameter, so my interface has to change. Not sure how to do this and still make the abstraction worthwhile?
My repository in the same manner is generic and can be used across processes and I want to reuse this layer too. Currently my repository (UoW) Interface is injected into my AppService layer, so I have no idea how this would work if Repository layer was a WCF service.
Question: How do I expose the shared behavior of the domain and repository layers and what would the names of these new layers be called? Is the new layer exposing the domain named 'Domain Service' and sit between 'AppService' and 'DomainModel'?
Lastly, if I'm on the wrong path with any of this feel free to guide me back. Thanks!
How do I expose the shared behavior of the domain and repository
layers and what would the names of these new layers be called?
In the context of a hexagonal (ports & adapters) architecture, your domain layer would be encapsulated by application services thereby defining the core of your application. Application services implement use cases by delegating to aggregates and domain services and orchestrating access to repositories and infrastructural services. Next, you can "adapt" your application to infrastructure. Having a repository implement an repository interface declared in the domain layer is an example of this. The repository implementation serves as an adapter between the domain and the outside world. Similarly for WCF services, usually called open-host services in DDD, they adapt your application to a transport infrastructure. The WCF service, or ASP.NET WebAPI service, would be a relatively thin layer that delegates to application services. Again, the purpose of this layer is only to serve as an adapter. This layer does own the contract that it exposes publicly. In DDD this is referred to as the published language. In WCF, for example, it would be defined via DataContract and DataMember attributes. These contracts are how external systems will access your domain. Having a buffer between published contracts and the internal domain is important because they will likely change at different rates and have different consumer requirements.
Is the new layer exposing the domain named 'Domain Service' and sit
between 'AppService' and 'DomainModel'?
No, a domain service is part of the domain layer itself, sitting along with entities, aggregates and value objects.
I think to expose domain object as service is not difficult. but system is really combination service and UI. UI access service, and service can be implemented on different ways: DDD or database-central . so it maybe not a good idea to tell the service caller how we implement our business logic.
Good Night guys,
I'm starting a project in asp.net, where initially not use wcf service but I want to leave you prepared for a future implementation services wcf between aspx and business layer.
Question:
Can I reuse the interface of business for wcf services?
My idea is while there are no services, create an architecture where the aspx will call business layer through a factory. All business class will implement a interface.
Later we will have a service for each business, so I would like to know if it's a good idea and possible use the same interface implemented for each business for the wcf service.
Implementing the same interface, the factory would decide whether it would return an instance of the business or an instance of the service. What do you think?
WCF requires class and method attributes to be declared on your interface, so you end up muddying the waters a bit.
I'm actually not a huge fan of WCF because of that and some other reasons. Service Stack is quite nice and allows one to easily expose a business interface via HTTP.
I am designing a system and I have read many articles saying don't put business logic in your service code. And only put your business logic in your domain objects.
I am not hosting my service code anywhere and it is directly accessed by my presentation layer. In future, I might want to expose this service code via WCF IIS service.
But I don't understand why services should be light-weight?
What is the advantage of it? When will we ever replace our services? Please explain
The idea is that by having different layers in your application, it makes it reusable. For example, your Business layer may have a function to check out a book. Well you can take that function and have it be called from different layers. A Console app can call it, a service can call it, or a web page can call it.
Additionally, it is easier to test. You can trigger the method in a sample application that just calls your BLL, and you don't have to worry about having your service call it.
In my understanding, this is about adherence to the single responsibility principle. The general idea is that the single responsibility of your service layer should be the translation of service operations to domain operations. I.e. you write a service type which exposes a method representing a service operation with a service contract as an input. The service method translates the service operation to a domain operation, and lets the domain object(s) worry about the business rules. This way your type encapsulates the translation of service operation to domain operation and nothing else.
Note that I am assuming that 'service' code, in the articles you are referring to, refers to the service interface in a service oriented architecture.
I have a business layer that has some business objects/POCOs/entities/whatever. I also have some repositories for the data access. Up until this point, I've been accessing the repositories directly from my UI layer. I'm at a point where I actually need some more classes that aren't straight CRUD, so I'm going to create some business logic classes that will do the logic, and CRUD, and the repositories won't be accessed by the UI anymore (which should probably have been done from the start).
What should I call these classes? The only thing I can think of are service classes, but I have actual WCF services in this application, so that will make it confusing. The WCF services will also be using these classes, so having a service use a service class seems odd and confusing.
I use the "Service" naming convention as well. It's true the "service" has become a very overloaded term in the industry, but it makes the most sense. Developers reviewing the code should be able to determine the difference between a Application/Domain Service vs a WCF service, and while having a WCF service call other service classes may seem confusing, I think you'll find that it isn't. The idea of a service is that it is code that performs a function, and is available for use by other code. It might be an internal service, or it might be a service externally exposed via http or whatever. But the idea of what the code does is the same.
If your 'services' are orchestrating business logic using a number of domain objects, you're likely implementing the Facade Pattern - so perhaps you can name them with this suffix, eg OrderManagementFacade
From your description, it sounds like the WCF classes are actually implementing a service host. I typically name such classes with a "ServiceHost" suffix. It separates them nicely from the actual service classes.
So, for example, you would have your business logic in a class named "CustomerService" and the corresponding WCF class would be named "CustomerServiceHost".