WCSF Application Architecture 5: Defining Modules
This article is part of a series;
· WCSF Application Architecture 1: Introduction
· WCSF Application Architecture 2: Application Controller
· WCSF Application Architecture 3: Model View Presenter
· WCSF Application Architecture 4: Environment Abstraction
Modularity Primer
One of the big pushes from the Web Client Software Factory was for Modularity – see the documentation online here for more information. This was for a number of reasons – supporting different teams working on the same web site but in different functional areas, clear separation of functionality, independent deployment, and more.
It is very common for systems to be considered “modular” in a horizontal fashion (e.g. logging frameworks, data access frameworks, or an application with both WebForm and WinForm UIs), but not so common for them to be split vertically. So what is a vertically modular application? Simply put, it is dividing an application into slices of functionality that span the architectural stack – from UI to Database.
In the previous posts in this series we have discussed a few concepts well worth knowing about in order to fully understand how we position the content of each module. I’d recommend checking back if you are not sure you know these concepts. You also need to know about the fundamental module types: Foundation Modules contain no UI elements, and Business Modules contain both UI and logic.
This post focuses on how the WCSF was designed to be used from the beginning – future posts will present ways to supplement, build on, or alter this basic approach.
A simple sample
To frame our discussions in this post lets magic up a simple module structure for a fictional web client application;
Here we can see 3 Business Modules (Customers, Accounts, and Orders) and a Foundation Module (Infrastructure) containing primarily Environment Abstractions. The Business Modules make use of a set of remote services and/or databases.
What makes a good Module?
So how did I decide to split this application into these modules? At the time of writing, this was the Wikipedia definition of “modular programming”;
“Modular programming is a software design technique that increases the extent to which software is composed from separate parts, called modules. Conceptually, modules represent a separation of concerns, and improve maintainability by enforcing logical boundaries between components. Modules are typically incorporated into the program through interfaces.”
The emphasis is mine, and is there to highlight what I think are some really key concepts of modularity. Namely they should be separate, there should be quantifiable boundaries between different modules, and communication across modules should be enforced using interfaces (or contracts).
Based on this knowledge, and experience of using the WCSF, let’s try and come up with some more concrete “rules of thumb” then;
1. Abstract application services into one or more shared “runtime” or “infrastructure” foundation modules.
2. Each business module should be separate: aim to minimise the communications between business modules if you want to avoid the spaghetti effect.
3. Align business modules with logical functional areas, which have meaning in your business domain.
4. Ensure that each sequence of pages (i.e. a Page Flow, or Wizard) is contained within a single module.
5. Allow multiple sequences of pages per module.
6. Partition according to the business services your modules consume; for example consider having a CRM module, and a Finance module, if these are two services managed elsewhere in your business.
7. Define business entities in a single module; if you need to refer to the private Invoice entity defined in the Finance module from your CRM module, have you perhaps got the boundaries wrong?
8. Consider the development process; if you have teams working concurrently on a system, are the modules you’ve chosen a logical split of work?
Do you have any more from your own personal experience? Shout up if so.
Finally, bear in mind that in spite of all this separation, modules must be related in some way – if they are really totally separate, why aren’t they just two different systems?!
10 Points of Pain
Great, modules are easy then? Well, almost! I’ll try and elaborate on some of the issues that can arise;
1. I don’t know where to put my User Controls and Custom Controls!
2. I’ve got spaghetti intercommunication between my modules using services!
3. I’ve so many modules I can’t find my code!
4. Where do I define my entities?
5. How do I reuse my company’s existing internal libraries?
6. I’ve too much code to organise in a single module!
7. My Application Controllers are too complex!
8. Which module should “own” communicating with my Web Service / database / flat file / mother-in-law?
9. I’m used to having separate projects for UI process, Business Logic, and so on – my developers are confused by having both in the same project, and we’re finding our layers are getting blurred!
10. My Architects are not happy bunnies; we like to be able to host our UI and business tiers separately!
In tried and tested fashion, let us address each of these in turn...
10 Instant Cures
1: I don’t know where to put my User Controls and Custom Controls!
This is really two questions: User Controls and Custom Controls tend to be handled differently.
For User Controls I would recommend putting them in the Shell module, perhaps in a sub-folder of the main web application named “Controls”. This ensures they are easily accessible to other modules. One really key point to consider here, though, is whether they should contain calls to business logic in their Presenters. I would encourage you to avoid this – Shell is not the place for this kind of thing. Instead, I would define properties and events on my control to allow it to be reused across my solution. Bear in mind this also introduces an additional dependency between modules and the Shell, which needs to be considered for deployment, versioning, etc. This is fine – the Themes, Skins, CSS and master page already dictate this, but do remember you must pay attention to it.
For Custom Controls I am assuming you would like to write (or already have) a control library to store them in. A really common mistake people make when first using the WCSF is to worry about putting everything in a module – this is by no means a dictation of the solution structure, and I would encourage you to avoid modules when they are not appropriate. In the case of a reusable control library I would use a standard C# project (or a compiled assembly), referenced from the Web project as usual. Just remember not to couple your controls to your business logic.
2: I’ve got spaghetti intercommunication between my modules using services!
Yikes. This is generally a sign that your module boundaries are not right, or that you’ve simply got too many modules. Watch this space for a post related to this shortly (sorry, but I’ll be saying that a lot in the coming paragraphs, I just don’t have the space!), but basically it boils down to you having two options;
1. Merge your modules into one. If it is really bad, and now you see that actually the two (or more) areas are not as separate as you first thought, this could be a good move.
2. Create a new “in between” foundation module in which to host the specific pieces of business logic that should be shared, moving it out of two business modules. Caution is advised; if the logic is completely core to the modules this could get misleading (e.g. moving LookupCustomer functionality out of the Customers module might be counter-intuitive).
I have to say, more often than not I’ve seen architecture diagrams start with many modules and end up with fewer. The fact of the matter is that factoring an application into modules is difficult.
3: I’ve so many modules I can’t find my code!
You’ve probably got too many modules. You shouldn’t create one module per page-flow, or one module per folder in a web site, or one module screen, etc. Modules should have substance to them, in much the same way that a class should. They should do everything required in a particular business area. Think about the comments under point (2).
4: Where do I define my entities?
This is a potentially tricky subject, as it depends on quite a number of variables. You basically have two choices; a) Define them with the “owning” module, or b) Define them in a shared C# project (e.g. named “Microsoft.Samples.Entities”), and reference this throughout your solution. Of course, this means your modules become tightly coupled to this entity definition project....... watch this space for a post on this.
5: How do I reuse my company’s existing internal libraries?
This is closely related to Custom Controls covered in point (1). Remember that not everything must be a module – in fact, the WCSF uses the Enterprise Library, and these are standard .NET assemblies (but could easily just be the source tree as C# projects included in the solution). So, when appropriate, import your company’s existing assets using a standard project or assembly reference. As I mentioned earlier, though, do make sure you don’t tightly couple your frameworks to your application logic.
6: I’ve too much code to organise in a single module!
There are two possibilities here. Firstly, you could consider splitting your module into smaller modules, if that really makes sense according to the guidelines in this post.
Secondly, this could be very closely related to issues #5 (“how do I reuse my company’s existing internal libraries?”) and #9 (“I’m used to having separate projects”). If it is framework code that you’re talking about, go ahead and pull it out into a separate project. If it is the business logic, data access, and so on, and you’re finding the volume of code and complexity seems unnatural to fit into a single project... I agree. Watch this space for a discussion on scaling the factory (from a volume of code point of view, not performance and scalability).
7: My Application Controllers are too complex!
So add more Application Controllers!! The WCSF creates a single controller per module by default, but there is no reason why you cannot create more if it becomes useful. For example, if you have a complex controller named “RegisterNewCustomerController” that handles flow for the registration process, you might also want to create a “RegisterNewPartnerController” that handles registering a partner organisation.
To do this, simply add a new C# class and interface to store your controller implementation and definition, and add a line to the module’s ModuleInitializer.Load method, just below that generated by the factory by default;
container.RegisterTypeMapping<ICustomersController, CustomersController>();
container.RegisterTypeMapping<IMyNewController, MyNewController>();
This allows you to use the [CreateNew] attribute as usual on your Presenters to get a reference to your new controller.
If you use this approach, do carefully consider how to factor your controllers. Remember that you might find it useful to use the controller as a facade to state as well, and therefore you must choose what to do if multiple controllers need the same piece of state. This is as much a convention decision as technical, but it is a decision that needs consideration.
8: Which module should “own” communicating with...
You may well find that your modules align neatly with your organisation’s approach to SOA, mapping a module to a Service with ease. But you might not!
Consider my sample module definition, and imagine that somewhere I store Customers’ addresses. Immediately you might assume this is something the Customers module needs. But what about our Orders module? It needs to know where to dispatch goods to!
So as a solution, I’ll let my Orders module call into this Address store too. Instantly my architecture starts looking a mess, as Orders and Customers read and write my “Customer Database”;
This breaks SOA principles (I’m thinking autonomous services mainly) which, although not strictly applicable to our modules, do provide some wisdom to this kind of situation. Now I can’t change my Customer Database implementation without reworking every module!
An alternative solution could be for the Customers module to expose an “Address” application service, meaning that Customers still owns the Address entity and service, yet other modules can access the data. If my database changes, only the implementation of the service (and hopefully not the interface defining its contract) in the Customers module needs to change.
Therefore, the recommendation here is;
Make sure a single module owns access to any given resource.
Of course, extrapolate this out too far and you could end up in Problem #2’s space (“I’ve got spaghetti intercommunication between my modules using services”). Alternatively, you might find that all your modules need almost all of your data... in which case watch this space for a related post.
9: I’m used to having separate projects
A lot of organisations are used to using projects to split layers, and in fact I think this is a really good way of working. Using a default out-of-the-box Business Module means that your business logic, entities, resource access, frameworks, and service definitions are all lumped in together in a single C# project, and this could lead to the boundaries between layers getting blurred. We want to separate concerns at the module boundaries (vertically) but not at the cost of layer boundaries (horizontal).
Watch this space for a post related to this...
10: My Architects are not happy bunnies
So what if you want to run your UI tier on physically separate hardware from your business logic tier? Or you already have a service layer containing all the application’s business logic that is used by an existing Windows implementation (no doubt you used the SCSF or Prism to build it J), and you just want to tack an extra web-enabled User Interface onto it?
Well this is a completely valid approach, and in fact the Global Bank Reference Implementation does exactly this, so be sure to check it out. I’ll also be posting more information on this architectural model soon.
Wrap-up
I hope that’s been useful to help you think about shaping modules in your application. As usual, do shout up if you have something to say, and stay tuned for the remainder of the series...
Comments
Anonymous
June 19, 2008
The comment has been removedAnonymous
July 03, 2008
Currently I am writing thesis around WebServices and SOA. I've decided to use WCSF and WSSF. Your WCSF architecture explanation just rocks. Can you please consider making short analysis of WSSF approach (or just your thoughts) and about efficient way of consuming WCF Services in WCSF. Thank you very, very much. THIS IS MY SHOUT! hehhe Best Regards! Keep us up to date!Anonymous
July 03, 2008
Montek; pleased you're finding it useful! I do have the intention of writing some thoughts on have a service layer approach with the WCSF, although realistically it will be a few weeks before I have time to write it up! So many things to do, so little time...! Hope you find it useful though. Oh, and good luck with your thesis! SimonAnonymous
November 20, 2008
This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF ApplicationAnonymous
November 20, 2008
This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF ApplicationAnonymous
November 21, 2008
This is part 5 of the WCSF Application Architecture series by Simon Ince this post explores the topic