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.

LIke Josh Rivers said in the comments of the previous post, I think we get the big picture but the level of abstraction of your posts is maybe too high. Or I'm too ignorant. But I think you will spread your message more easily with a little more of code/sample.

I like this idea ... but something is bugging when i see NewOrder folder in your project structure. Would you meant to have ExistingOrders, DeletedOrders, ShippedOrders, CancelledOrders etc., Is that viable to go by this approach? may be if Ordering System is what you intend to develop, then "NewOrder" is a feature or core functionality?. I also think features are implemented above on a basic functionality of the business requirements. I would develop a "OrderByPhone" feature for a "Grocery Ordering System" ... Or, may be we are confused with the term "Feature" ....we need to elaborate more ...

I think, what you intend say is something simliar to Procedure Oriented Programming paradigm. Each function carries its own purpose, may not be generic in nature. I see the same inheritance happening in your approach.

I like the concept but I find it hard to see how you could separate things so cleanly.

Here's an issue that I'm dealing with:

The website I'm working on involved a database full of bands who submit tracks (among other things) and manage them.

Next, we have a media player that allows users to play theses tracks and also include them in personal playlists.

Those are 2 distinct features to me, but share lots of stuff.

I think this is a great topic and hope you have lots more to say about it! I find project setup, organization, configuration to be the hardest thing to manage as a developer. The code comes easy, where to put the code is what takes up a lot of my time.

I'm digging this, and would love to see more concrete examples like this. For example, how is the pub/sub implemented? (I'm sure it uses Rhino, but how exactly do the features consume it, etc) Just go ahead and release the code already =)

On saying bye to layering, I agree. I've been keeping most of our solutions to three assemblies: [Company].[Project].Web (or Win, etc), [Company].[Project].Library and [Company].[Project].Tests. Only when I absolutely need to use part and only part of nnn.library elsewhere do I split it up. Publishing interfaces for 3rd party webservice consumers to use without also publishing implementation, for example. Anything else is just academic.

I thought you were going to say that! The bounded context is still something I don't grok in code and I think that's something I need to resolve soon. When discussing concepts at a high level I find it easy to see the bounded context but just don't know how to code it.

Is it the case that DRY competes with bounded context? Or is that being over DRY (arid?) is an anti-pattern and bounded contexts is a technique to fix it...

Hah. Not to speak poorly of the academics in the room, Patrick. ;) Maybe I overstated. I mean only that I've found I can still separate code without necessarily having an assembly for each little thing.

This is a possibility, but the more likely scenario is that you actually have different tables for each of your contexts. How you store the data and what data you store is unique to each context. So yeah - keep it simple, map one domain model class to a table, accept the fact that some data will be duplicated across bounded contexts, and lean on pub/sub to keep everything in sync.

It reminds me CAB the first time I saw it. But how do we address the required distribution for windows / smart / RIA / Client Ajax applications? We would still need to fit in some sort of a distribution and features would be splitted atleast for the UI (& its surrounding patterns).

Intrestingly, all these looks like lean SOA, just binded to a single platform :).

That sounds like a completely different world than I'm used to. I take it that the database is highly denormalized then? Duplication of data in the database always seems like quite a headache.

So pub/sub would mean that if a band renamed a Track, pub/sub would dispatch an event that this happened, and any publishers (eg: Playlists and their tracks) would subscribe to this event a rename their tracks accordingly?

As always, the answer is "it depends". In a large distributed system different bounded contexts often have their own data storage, and their own domain models. Pub/sub is used to handle business events that are being published by the different bounded contexts such that subscribers are able to receive those messages and act on them in a manner appropriate to their context / domain model. The notion of an order might exist in many contexts, but everyone has their own interpretation of what it means to them. If you are building a big system this introduces complexity up front but makes it much easier down the road. If it's a small system you might not want to go this route.

For your Track renaming scenario you could be storing all the data in the same database / tables, just using pub/sub to enable async behavior in your system - "TrackRenamed" is published, and the Playlist context/service/etc... subscribes to that and starts renaming tracks contained in playlists (assuming they're stored in a denormalized fashion to make reads fast, otherwise if it's just a foreign key relationship the track is already renamed :) Later on down the road when you have another part of the system interested in that event it's simply a matter of adding another subscriber for that message type.

I believe I need to read up on bounded contexts because that seems to be the main thing that's not clear to me (the implementation not the concept). Thanks for providing a direction for me to research further.