Component Oriented Design and why it be retired
The example on the right is from the new MVC Music Store sample, and it show a way of designing software that was quite popular in the end of the previous century and the early part of this century.
In part, it was wildly popular because of the type of infrastructure that was available to build software on. In you consider the time frame, that was the height of COM and the golden age of EJB. Both sets of infrastructure focused on stateless components manipulating “entities” that were just data holders.
The reason why there was such a focus on statelessness? Creating objects used to cost a lot at the time, especially since you needed a reference to those objects across servers, so you really had no better choice than going with this approach.
Why should this style be retired?
Well, let us consider what we have, tight coupling to the environment in which it runs and lot of explicit queries to the database. I could live with either easily, especially since the sample is intended to serve as a guide for beginners.
What really bothers me is that we now have the behavior related to working with our model scattered high and wide. Okay, that isn’t quite fair. Most of the logic in the system reside in the ShoppingCart component. What bothers me is that we have:
By that I mean, we have the controllers directly query the persistent DTOs that we have. This leads to situations such as this:
This is a controller method, I really don’t think that it should be concerned with the type of foreign keys and cascade relations that we have on the database. There is another issue here, that the sharp eyed among you might have noticed, there is no shared unit of work (data context in this case). Each different component is going to access the database through its own data context, meaning that you have multiple ways of getting the same persistent DTO back, through different connections, getting different instances, on the same request.
In short, the problem with component oriented design is that it separate data from behavior and lead to a scattering of the knowledge about the actual data structure and access pattern throughout the application.
I would much rather see behavior moved into the entities (upgrading them from persistent DTOs to actual entities), querying being centralized in a repository and a single unit of work that applies to the entire request.
Comments
Not to mention it would be much easier to test with query logic in query objects or a repository.
"The reason why there was such a focus on statelessness?"
Actually, it was for scalability. You cannot scale a middle-tier made up of stateful components. (If the component remembers state, it cannot be reused by another client, so you suddenly need as many middle-tier components as there are clients, even if they're doing nothing.)
This is middle-tier 101...
Marcel,
Not quite the same thing at all.
What I am talking about is a stateful entity, like ShoppingCart vs. stateless component ShoppingCart.
The stateful entity goes to the database after every request.
That the middle tier doesn't state is obvious, but we aren't discussing that.
Isn't the name "component-oriented design" also the synonymous pattern for IoC? Have to be careful we aren't confusing two concepts here.
Hi Ayende,
Well said! The scary thing is that it feels like a deja vu - wasn't there a thing called oxite which suffered on the same issues. No testability, No SoC & SRP, ...
Daniel
The controller actions are actually transaction scripts here. Not a bad thing in itself but u should be aware of it and of its downsides.
I would expect more from a sample app that aims at educating.
I wasted enough time on 2002 with DataSets because of such samples...
I always have to appreciate the intention behind people sharing their code and guidance even if their approach doesn't match my taste.
But Oren, you mention some worthwhile improvements, one of which was repository. The last really good guidance got on that subject was "just use query objects" from your blog. I haven't done that yet but would like to, is that still a good idea?
Thanks!
James
Although I kinda emphazise with you I feel an urge to ask: What do you mean by "component". Unless it´s clear what you mean by that I would not say something general like "component oriented design should be retired".
The reason is simple: I´m doing component oriented design all the time. And companies I´m training in doing it love it. It´s gives them productivity, it gives their designs flexibility, it simply is the foundation of any architectural thinking and planning.
But I guess such widely differing views on "component oriented design" are only possible if there are widely differing notions of "component".
So what exactly is your definition of "component"?
-Ralf
Ralf,
I am refering specifically, in this post, to the style that is shown in the post.
That style was popular some years ago under the name component oriented design, and this is how many people still refer to it to justify this sort of code
James,
Different guidance for different scenarios.
Here we have a mix of persistence & non persistence concerns.
When I spoke about query objects, I was talking about a problem with obese repositories.
It looks from the future post list that you are going to change this application to use Raven. Are you going to refactor it to use better programming practices at the same time?
Either way I am looking forward to this.
Dmitry,
The things that really annoy me, yes.
Total restructuring, no.
Jason,
Take a look at my reply for James
Hi Ayende,
I am new to MVCs and IoC. Could you please explain in slightly more detail. Here is how I understand it.
You are suggesting we code against interfaces. The classes that implement the interfaces will have all the logic for querying the database. Is this correct?
What I am not sure about is in the Controller (pseudo code), if we have:
IRepository repository;
var x = repository.GetCartItems();
return View(x.OrderBy(c=> c.OrderID));
The controller has logic to sort by a certain column in the DTO. Is it OK to do this?
Could you also please explain the difference between view specific models, data transfer objects and POCO objects?
Thanks!
Andy,
I'll have a post in a few days that discuss this in more details
I think this is a case where the developers aren't doing TDD. (I'm master of the obvious eh?).
See, the ongoing thing I see in places I work is 'deliver' but 'don't write tests'. Developers are just taught to produce - for whatever reasons, namely 'economy'. Churn out a solution quickly.
they want to use some magical database access 'generator'
which produces anemic data models
with no tests
I see job after job here in the states outsourced to someone who can 'do the same job at half the cost' and produce the type of code above, which is fine for the RAD 'show the customer quickly how good we are' but falls apart when the requirements expand.
It's a real issue in our dev shops.
They don't really know how to properly setup a DAL using poco. It's a 'dataset' mentality. There is no concept of 'Unit of Work' because it's not understood.
Everyone is stuck with anemic models because the blinders are on - data modeled solutions are typically chosen first, no domain driven modeled solutions. So they start with the database and create the tables, then have some 'wizard' generate objects vs. knowing the domain, creating the domain object and it's test, etc...
Lastly, mocking and testings are still primal, and although the masters all know how to do it isn't obviously enough for the everyday developer.
Ayende, to make up for the terrible injustice you've done to "component oriented design" please please do a follow-up "component oriented design and why you should be using it" ....... i.e., IoC ;)
Separating Data and behavior is SOA 101. You essentially can't do SOA and have interop without this separation.
The "anemic domain model" (as I think Fowler calls it) can work fine on large scale systems if done properly. The example as posted is obviously not done properly. This is a complete strawman IMHO, to post a poor example and use it as an argument for separating data and behavior.
I see your point, but really this has nothing to do with component orientated design...if anything this is 'lack of design'. From what I can tell, the MVC Music Store is just a beginners example of MVC. Why make such a big deal about? It is what it is, a simple example. What's next, deconstructing "Hello World"?
Nicholas,
Except that I am not talking about IOC here
ThatJoeGuy ,
I am finding it interesting how many people try to generalize my post.
I am talking about a very specific thing, I put up a code sample so it would be clear what I am talking about.
As for exasperating data and behavior, that may be what you need _on the wire_, it isn't what you want when you are actually executing code.
jmorris ,
Where do you beginners learn?
Apps like this are taken, as is, modified, and used. The architecture used is paramount, because it will be used in many apps.
And you can (easily) create a good architecture that a beginner can follow easily
I take that with a grain of salt: 10 years prof dev experiance, BS and MS CS/SE....Java, C/C++, C#, Web, Desktop, RIA, Mobile, blah, blah, blah...
My point was that you are naive and ignorant to many aspects of software engineering/development...you make many assumptions, such as this one: "Component Oriented Design and Why it Be Retired" and use and an example that has nothing to do with Component Orientated design/development.
Your using a beginners tutorial to prove your point; it's like going to the kiddie pool and proving to two years olds-"this is not how you swim, left me show you". Dude, it's an easy target...to easy: they wouldn't know anyways!
FWIW (if you read this far), I 100% agree with this statement:
"Apps like this are taken, as is, modified, and used. The architecture used is paramount, because it will be used in many apps.
And you can (easily) create a good architecture that a beginner can follow easily "
Yes, they are and yes it's a PITA when you have to explain to a manager, co-worker, whatever why it is bad...but, using a weak argument to validate this won't work. It's just an example at a simple level...geez, maybe in math 100 we should be teaching a 2nd year Calc class ;)
The code sample has nothing to do with component-oriented design. I agree with the semantics of your post, but the titles you choose sometime drive me crazy ;)
jmorris,
I am sorry, it was supposed to be "where do you THINK beginners learn", something went wrong in the journey from my head to my fingers
I have to agree that the samples that are shipped are considered by beginners as the bible/model code to be emulated. In our shop every single vb6 guy who graduated to dotnet only built off the samples or did what they saw in msdn.
So when can we expect a sample app done right, from you?
Kelly,
You mean that I am not outputting enough code for you?
Look at the future posts queue
You are certainly outputting more than your share of code. Your blog is extremely educational and helpful. However, blog posts do have their limitations. You can't expect a beginner to read through your last 2 years of posts to figure out how to get started with their next web app. A concise sample app that sets them in the right direction is much more useful in this scenario.
First, thanks for the post. I agree with the overall ideas behind it.
I think there is already a lot of info out there on repositories and there is not much more to say on the shared context.
What I'd really love to see in a follow up, is specifically: "I would much rather see behavior moved into the entities (upgrading them from persistent DTOs to actual entities)". Basically I just don't see that extra smell/improvement in those simple snippets, which is mainly the reason why I thought I'd get an aha! moment from this post. In other words, I have the feeling that this still maintains 'Component Oriented Software and entities that are nothing but a data bags to be manipulated stateless business objects' after repository + shared context, yet I don't see much further to move around / or a benefit in doing so.
ps. I keep reading every now and then about DDD and looking at different scenarios, and I think some concepts mentioned are great but there's just something to it that keeps eluding me. Maybe that's why the above doesn't end clicking to me.
Kelly,
You mean like Effectus?
ayende.com/.../...ing-ui-based-on-conventions.aspx
Like Alexandria?
ayende.com/.../my-secret-project-alexandria.aspx
Like Hibernating Forums?
ayende.com/.../The-Forum-Sample-Application.aspx
Like the 10 parts series in TekPub about how to build NHibernate applications?
Like MonoRail sample app?
ayende.com/.../...itoryltTgtSampleApplication.aspx
And those are only the things that I could pull out from memory. I have a LOT of sample apps, tutorials and guidance out.
Freddy,
Look at the future posts
My apologies. I did not know about those sample projects. Perhaps they deserve a link on the home page.
NHibernate Sample,
You mean... Effectus?
Which came out in ... December?
@Kelly
Dont hold your breath. I'm still waiting for the end-to-end NHibernate "best practices", "real world", sample app that Ayende promised in August that was supposed to be delivered by December. A app of this description could really drive sales of his product.
If you already built it Ayende I'm an idiot and can you provide a link?
...
Nice article. It would be interesting to see how you would rewrite it to have a cleaner design.
Also, I think this is the first time I have seen software development talked about in terms of centuries.
I enjoyed the article. I did find the title confusing, but I think I understand both what Ayende is conveying and the complaints you guys are listing.
My thing is this...We don't teach babies to run before they can crawl. It's a mandatory step (err...generally...unless this is some sci fi flick). I do not advocate giving 'bad' code to beginners; however, there is something to be said for breaking up the learning process into chunks.
Maybe the example application should have been done in phases. An initial beginner phase that eases newbies into MVC, and then a more thorough version that shows where the previous one fell short, while introducing advanced concepts like Repository pattern, IoC, etc....granted SoC is what's missing in this example and that's not necessarily an advanced concept, but still...baby steps.
I guess the short version of what I'm trying to say is this: I don't mind examples that skimp to a degree on best practices, but those examples ought to be mindful of their shortcomings and make mention of it so they aren't taken as the defacto and only way of accomplishing a given task.
With that said, the MVC community has been such that people take up projects and add things to them all the time. Nerddiner is a great example of that.
Maybe this is all a tangent. I'm no expert. I'm just a guy trying to figure all this stuff out.
Comment preview