Ayende @ Rahien

Hi!
My name is Ayende Rahien
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 5,949 | Comments: 44,548

filter by tags archive

EffectusIsolated features


Continuing in my exploration of the Effectus code base, which originated from my Building a Desktop To-Do Application with NHibernate article on MSDN Magazine, I wanted to talk today about separating features into individual pieces in the application.

Each feature in the Effectus application is built as an isolated unit, that has little to do with any other features. This is very clear when you look at how they are organized:

image 

Sidenote: In each feature, the component parts are named the same (Presenter, View, Model). This is intentional, since it make it that much harder to mix stuff from other features.

Every feature has a pretty rigid structure, defined by the application, and trying to reuse stuff between features is frowned upon and avoided, even if doing so can reduce duplication. As a good example, the Model for both CreateNew and Edit features are identical, but they are two different classes with no attempt to merge it up.

The reason for this is quite simple, treating each feature as an isolated unit bring us great benefits, we can have different developers working on different features without the chance of stepping on each other toes, it is very hard for one feature to break another, deploying new features is easier to handle, etc. Trying to apply DRY and consolidate common pieces of code would introduce dependencies between features, and that is a bad idea.

But what about communication between features? What about when one feature needs to call another?

As it turned out, it is quite easy to turn a lot of the inter feature communication into an indirect calls, using pub/sub. We gain the independence from dependencies using pub/sub, while maintaining the feel of a well integrated product for the user. For the rare cases of one feature calling another, I create a simple Call(“FeatureName”) mechanism (in the code, this is Presenters.Show(name) method) that all us to just explicitly invoke another feature, maybe with some initial arguments. A more complete implementation will handle even that using pub/sub, probably with an integrator class that would dispatch the appropriate event to start and invoke the feature(s) that want to handle it.

You can read more about the architecture principles behind this system in: Application structure: Concepts & Features

More posts in "Effectus" series:

  1. (21 Dec 2009) Isolated features
  2. (20 Dec 2009) Fatten your infrastructure
  3. (19 Dec 2009) Building UI based on conventions

Comments

David Perfors

So in light of the Concepts & Features article... Does the namespace Effectus.Model contain the Concepts?

alberto

Component naming makes sense, altough it makes Resharper navigation a bit slower.

Josh

I know this is a minor detail about how you are doing things, but obviously in a larger application you would have more than one Edit screen.. would you do a deeper nesting of your directories to be more like:

-Features

-Contact

  -Edit

-Company

  -Edit

or go the route of

-Features

-EditContact

-EditCompany

brainboost

Maybe I missed something but i have no idea how to test presenters. Granularity of IPresenter's too low to mock it and most valuable properties like Model don't allow to apply IoC in easy manner. Am i wrong?

Jason Y

"Trying to apply DRY and consolidate common pieces of code would introduce dependencies between features, and that is a bad idea."

What I hear you saying is:

  1. It is generally bad to have one feature depend on another.

  2. It is also generally unhelpful for features to reuse a common codebase (e.g. the Model for the CreateNew feature and that of the Edit feature are identical instead of reusing a common BlahModel). I assume this would be because, even though they may happen to be identical at different times (as a broken clock is right twice per day), it is generally not true that they shall be the same--i.e., they are the same by accident, but will likely vary by design--and should therefore not share code in common. Is this correct? Am I making sense?

Rafal

@Jason - you are making sense and I like the clock analogy. In "business logic" layer code reuse is a bad thing because it means logic reuse, which introduces hidden dependencies between functions that would be unrelated otherwise. If you have large applications you want to keep everything as local as possible, so you don't have to analyze the whole codebase to make changes to a single function. Ayende has chosen a wise, however somewhat bloated, approach to isolating features. I'd rather use script/DSL files to contain higher-level functions, each feature in its own file, but the method is not that important. Another aspect is the organization of the code - IMHO the static code structure defined by packages/classes/inheritance is good for infrastructure code, but not so good for business logic. For the logic its much better to group source according to business functionalities provided - for example by business processes supported by application.

Harry

Nice code and explanation. I agree with brainboost that adding unit tests to the project will be very beneficial to us. ;=)

Ayende Rahien

David,

Nope, a concept in Effectus is showing screens with data bound to them.

Ayende Rahien

Josh,

I don't like deep hierarchies, so I would probably go for the second version.

OTOH, if I have a LOT of features, I would have Features\Contact\EditContact at some point, just to make sure that everything is arranged in a way that I can work with.

Ayende Rahien

Brainboost,

var presenter = new Presenter();

presenter.OnSave();

etc...

They are basically POCO classes, so you don't really need to do much to test them

Ayende Rahien

Jason,

Yes, you are making absolute sense

Nima

I'm a fan of your features/concepts architecture and I really like their isolation but I'm thinking that how I can apply it on a real project that I'm working on.

We have "create and edit documents" scenarios among the features of our application.

These scenarios contains a complicated approach and a simpler approach according to user preferences (we have two forms -a full form against a summary form-for each scenario and we are using the same form to create and edit )

The questions is how we can isolate these features so that we don't have to change all forms if there's a new piece of data should be added to them.

One thing that comes to my mind is to use a user control on our views but I'd like to have your opinion on this matter.

Thanks again

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. The RavenDB Comic Strip (3):
    28 May 2015 - Part III – High availability & sleeping soundly
  2. Special Offer (2):
    27 May 2015 - 29% discount for all our products
  3. RavenDB Sharding (3):
    22 May 2015 - Adding a new shard to an existing cluster, splitting the shard
  4. Challenge (45):
    28 Apr 2015 - What is the meaning of this change?
  5. Interview question (2):
    30 Mar 2015 - fix the index
View all series

RECENT COMMENTS

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats