I'm looking at architecting a new solution that is very modular by nature and would like to create a structure that supports that design to allow for easy future expansion, clear separation of concerns, licensing by module, etc. Most of what I've found on the web about modular or composite applications are UI-centric, focused on Silverlight, WPF, etc. In my case, I am developing a WCF service application that will be consumed by other developers working on various UI projects.
The goal of my project is to create a centralized source of business/domain logic to support several of our business applications that currently duplicate process, rules, etc. And while not every benefit of modularity will be achieved, I'd like to seize the opportunity to establish a framework that will leverage those parts we can take advantage of.
I've started the design by looking at the API exposed by the service application. It is clear that the services can be segregated along the modular lines that I was considering. For instance, I will have FinanceService, InventoryService, PersonnelService, etc. services that group my service operations to provide high-cohesion in the API while keeping the coupling low so clients only have to consume the services that are pertinent to their application.
It makes sense to me that I can then have separate modules for each of these services, such as MyApp.Finance, MyApp.Inventory, My.Personnel and so on. Cross-cutting concerns and shared types would be in the MyApp shared assembly. From here I get a little tied up.
(Oh, I should mention that I'll be using an IoC container for Dependency Injection to keep the application loosely-coupled. I won't mention which one because I don't want to open Pandora's box!)
In MyApp.ServiceHost, I will create a service host file (.svc) corresponding to each module, FinanceService.svc for example. The service host needs the name of the service which corresponds to the information in the configuration file that contains the interface defining the service contract. The IoC configuration is then used to map the concrete implementation of the interface to use.
1. Should the service layer implement the API and delegate to the modules or should the modules be self-contained (in that they contain everything related to that module, including the service implementation)?
One way of approaching the problem is to have a MyApp.Services "module" which contains the implementation of the service contracts. Each service class simply delegate to another class int eh appropriate module which contains the domain logic for the operation. For example, the FinanceService WCF class in MyApp.Services delegates to another interface which is implemented in the Finance module to carry out the operation. This would allow me to maintain a thin service facade and 'plug-in' the implementation to the service implementation and eliminate the need for the modules to worry about WCF, for instance.
On the other hand, maybe it's preferred to have each module self-contained in that it has the interface and the implementation. The service host refers to the service contract interface found in the module and the IoC is configured to use the appropriate implementation from the module as well. This means that adding a new module can be done with no changes to the service layer other than adding a new .svc file and IoC configuration information.
I'm thinking about the impact if I switch from standard WCF to a RESTful service interface or maybe go to RIA services or something. If each module contains the implementation of the service contract, then I have to make changes in every module if I change the service technology or approach. But, if the facade is its own module, then I only have to swap out that part to make a change. The modules would then have to implement a different set of contracts (interfaces), possibly defined in the shared assembly???
2. What is the best way to handle sharing resources between modules and/or dependencies between modules?
Take, for instance, a Receiving operation. At first blush it makes sense that this goes into the Inventory module as receiving goods is an inventory function. However, there is also a financial aspect in that we need to generate a Receipt and authorize payment.
On the one hand, I would expect to use some type of domain events / messaging to communicate the operation. The Inventory module raises a GoodsReceivedEvent which is handled by the Financial module to generate the Receipt and initiate the payment process. However, this means that the Financial module needs to know about the inventory items that were received. I can simply refer to them by ID but what if I need additional information for the Receipt, such as the name and/or description, unit cost, etc.? Does it make sense for each module to have their own version of an inventory item that is designed to suit the needs of that module? In that case, the Financial module would have to perform its own lookup of the inventory items when handling the GoodsReceivedEvent. Or do I now have to put my domain objects into a shared location (at which point I lose some cohesion)?
I used this example on purpose because I've worked a lot with various ERP systems and know they are designed with this type of modularity - I just don't know how. I also don't explicitly mention it above, but I prefer to follow Domain Driven Design principals in architecting the solution and believe that this type of modularity fits right into that area.
Any help getting my head wrapped around this is greatly appreciated.