I commented before that a feature is usually composed of several classes, running in different places and at different times, all working together to achieve a single goal. This post is meant to expand on this notion a bit.
Let us go back to the type of architecture that I favor right now. Note that this is a physical diagram only, without actually going into the details about how each of those is implemented.
Storage, for example, may be a relational database, a key value store, a distributed hash table or something else, depending on the requirements and constraints that I have.
More than anything, this diagram represent physical distribution and setup behavior. For example, you really want to backup all the storage servers, but an application server can just have a image made and that would be it.
The main reason for having a separation between web & app servers is mostly so we can place the web server in the DMZ and the app server in a more trusted location. But I digress.
I mentioned before that I don’t really like layering anymore, and that I tend to think hard before I create assemblies.
Here is a sample of some of the ideas that I have been working on lately. The idea is to formalize a lot of the notions that I talked about in my concepts and features post.
You can think about this as a logical extension to the way people build composite applications. We have the infrastructure, the idea of the base services that are being provided by the application, and then we have features.
Each feature is a complete story, which means that a feature will contain, in the same place, all the parts required to make it work. For example, as you can see in the project image, what we have is the Search feature, which contains some UI, the logic to control the UI on the client side and the server side, helper classes to manage that. In the Finders folder we have additional functionality that is specific for this particular feature.
The infrastructure knows that it needs to pull of of that together, so we base everything on conventions. For example, we have a routing convention for aspx pages, and for finding services or controllers.
From layering perspective, there aren’t any. Inside a feature, you can do pretty much whatever you want. There is usually some conventions around to help build things properly, but that is mostly about just getting things working, not to support layering. And I don’t have a problem with breaking the rules inside a feature.
Features that affect each other are rare. It usually only happen whenever we have to do things like “when you search for an order and you go to a particular order, we want to always go back to the search page, no matter how deep we went”.
Cross feature communication is done using pub/sub mechanism, most of the time.
Most of the ideas that I outline here are composite applications notions, just applied in a more general fashion. The end result is that you gain all the usual benefits from composite applications. You don’t step on another feature toes when you add stuff, and you have a stable base from which to work from. Each feature can be developed independently and is only worried about its own problems. The infrastructure is built during the first few features, but afterward it is mainly a stable platform on top of which we build.
I should note that notion is recursive. That is, we have a feature that keep getting expanded. At that point, we will probably treat it like the entire application, and build the infrastructure in place so we can drop additional features to the root feature. A common example of that would be to support additional authentication mechanisms for the Authentication feature.