IT:AD:DDD:Components/App.Domain.Repositories
Summary
The Application Layer Services are Facades that hide the complexity of orchestrating calls between Infrastructure Services and Domain entities and services, in order to keep Domain ignorant of the complexity required to make it happen.
But the Application Services should remain loosely coupled, an never tightly bind to any infrastructure service implementation, and instead, refer to them only by contract\interface.
ITracingService tracingService =
ServiceLocatorService.Current.GetInstance<ITracingService>();
tracingService.Log("Simply works by the magic of DI provided by an IoC such as Unity or Ninject");
tracingService.Log("even if only using the *interface* of the service, never mentioning the real implementation.");
But…developer teams being what they are, you can pretty much gurantee that given the chance to get to a concrete implementation of the contract, someone in the team will goof up and use the 'new' keyword and bind tightly to it – making the code unmockable, and tightly binding the Application logic to the Service implementation logic:
Log4NetTracingService tracingService = new Log4NetTracingService();
tracingService.Log("And your code would now be tightly bound to Log4Net till the end of time...");
tracingService.Log("...or someone caught it in a QA session.");
It wouldn't even be a case of if – but when.
Therefore, it is prudent to use two sets of assemblies for the services – one containing the contracts/interfaces, the other containing the implementations of those contracts.
This layer contains the assemblies that define the contracts, and contain no actual concrete implementations.
Minimal Dependencies
* As expressed more fully in IT:AD:Patterns:Minimal Dependency Cardinality, keep your Dependencies minimal: * Prefer .NET Client Framework over .NET Full Framework * Remove all extraneous References in your Assemblies. * Consider using .NET35 versus .NET40
For example, this Layer is not dealing with data storage (that's the Domain.Persistence's responsibility) so System.Data can/should be removed.
On the other hand, this time, System.Xml could be kept (see below).
Assembly References
The same rules apply to DDDD based applications as older architectures: Assembly should only reference Assemblies in layers below or sideways to the current layer – never upwards – in order to avoid circular references.
So, after removing extraneous References, the Domain Layer assemblies has References to:
- System.Xml
- You may Some of the services defined here will be used for communication by the Distributed Services Layer, although I would much prefer an object based signature, where the actual serialization is handled by the request method (JSON or Xml).
- XAct.Core
- it defines a lot of base interfaces that the other XActLib assemblies reference, and that it's safe to refence (XAct.Core is going to be used in every other assembly in your app…right?
## Service Contract Elements ##
This is where create the Service contracts/interfaces for the Services required to perform the Strategies that the Application Layer wished to implement.
Namely:
- ITracingService
- IAuthenticationService
- IAuthenticationManagementService
- IRoleBasedAuthorisationService
- IRoleBasedAuthorisationManagementService
- Auditing
- IContextService
- ICachingService
- ITransactionService
- IResourceService
- ValidationServices
- [TODO:Largish subject]
- ICommandMessageDispatchingService
- IExceptionManagementService
- IDataMappingService
- IMessageBusService
- IMessagingService
- INotificationService (not the same thing…one is a full message, ones more of a Toast service)
- IPerformanceService
The list above is just the beginnging – and it's already quite long.
The good news is that the above list is rather …conventional. Conventional in the sense that almost all apps should have most of these Services defined in them. And that's the good news: that common code can be refactored into library code.
And that's where XActLib can help out: it has a good start on the above services already implemented, and more being added all the time.
The Infrastructure Layer - Services page will delve deeper into which services are available already available for your use.
Pitfalls to watch out for
* It's very very tempting to save a lot of time in these services, simply sub classing the interfaces already defined in XActLib/.
- Don't. It's flattering that you like the lib – but it is vendor/3rd party code. And like all vendor code, whether Microsoft, Oracle, or XActLib, it has to be treated warily…and not drag a reference to such code throughout your app.
- In other words, although the following would be so much faster:
public interface IMyAuthenticationService : IAuthenticationService {}
public class MyAuthenticationService : WindowsAuthenticationService, IMyAuthenticationService {...}
you would have saved time coding, but would also be dragging a Reference to XAct.Security.Windows up to the Application Layer where it will be used. Not good.
So although I would like to make it all be RAD, I strongly suggest you take the time to wrap the Vendor's code as follows:
public interface IMyAuthenticationService {
*Copy Signatures from IMyAuthenticationService
void TheFirstMethod();
...
}
public class MyAuthenticationService {
private readonly IWindowsSecurityService _windowsSecurityService;
public MyAuthenticationService(IWindowsSecurityService windowsSecurityService){
_windowsSecurityService = windowsSecurityService;
}
void TheFirstMethod (){
_windowsSecurityService.TheFirstMethod();
}
...etc...
}
Yes, the wrapping takes longer, but at least you have a template to go from (the original interface's definition) and it's really a case of copy/paste. And as the classes are usually small (SOC, anti-god classes and other good reasons), it doesn't take very long.
And it's for your apps good. Protecting it from the likes of…well, anybody else. Including XActLib.