Plain old .Net classes

time to read 6 min | 1042 words

Frans Bouma commented on my post about persistance ignorance, which I feel deserve a post in reply.

First, let me define the term POCO or PONO, it means Plain Old C# (or .NET) Object. The term comes from the Java world, where it is used to describe objects that are not encumbered with frameworks (like EJB, for instnace). A good example of a non-POCO class would be the WebForm1 class. It cannot be usefully utilized outside the ASP.Net envrionment.  Persistance ignorance is not having the entity class involve in its own persistance (or in persistance at all).

Persistance ignorance is not always nice to have, Castle Active Record, which I am using in my current project, is certainly not Persistance Ignorance, it explicitly puts the responsabilities for persistance on the class (and handle it in the base class). Active Record make it much easier to work with NHibernate. The important thing about Active Record is that I can decide that I want this and that class to be ignorant of their persistance, and handle it seperatedly, even to the point where their assembly do not reference the Active Record assembly. This is no minor thing.

Now let me get into Frans' comment (note: I edited the comment to concentrate on the stuff that I want to bring to discussion and to reply to. You can read the full comment here):

Persistence ignorance is as useless as POCO is as a term. A POCO class isn't persistable unless some post-compile or runtime-magic is added to the class. This is often overlooked by some of the vocal 'POCO or bust' people, and it gets really annoying. Because, it really matters WHAT is added to the POCO class: O/R mapper A adds different magic than O/R mapper B. [...]

So swapping O/R mappers will change the behavior of your application [...]
So is this 'persistence ignorance' really existing? No. Not only is the database part of your application, if you want it or not, it also makes up a huge part of your application's execution time, so your application spends a lot of time inside the DB. Ignoring that doesn't make it go away. In fact, ignoring that makes you vulnerable for bad performing applications which you could have avoided with simple thinking and proper architectural decisions.

I agree with everything that is said here, except the bolded part (emphasis mine). Because to my way of thinking, even with all the conditions that Frans mentions, persistance ignorance is important. It is important because my business logic isn't cluttered with other respnsabilities, it is important because we don't have mixins in .Net, and I got only one base class, and I am already using it. It is important because I may use types from other assemblies, including stuff that the author never though would ever be persisted.

Everything that Frans says is true, but it is not true for the object itself. The object is blissfully unaware that it is persisted, or how it is persisted. A good runtime-magic is mostly transperant, and do not require much thinking about in most cases. I was surprise to learn by just how much, to tell you the truth.

Persistance Ignorance has another point in its favor, if you classes are open for persistance ignorance, they are open for other extensability points as well. Validation being the key stone here, but I have done some interesting things with this recently, NHibernate Search, for instance.

If a POCO class ends up with 60% plumbing code for databinding, xml, helper code for producing strongly typed filters, prefetch paths etc. and 40% BL code, what's so great about having to write that 60% of the code by hand? Isn't that tying your code to some persistence framework as well?

If a POCO is 60% plumbing, it is not a POCO, period.

I mean: dyn. proxy using POCO frameworks also force you to write your code in a given way.

Yes, you are forced to use virtual methods. I would have love to remove this restriction, but the CLR won't let me. I consider this a failing of the CLR. That said, it is not a burden, IMO. The most insightful part is this:

After all, the core issue with this is that what POCO people really want is a place to write their own code without having to comply to a set of rules forced upon them by a 3rd party library they use the POCO classes with. If that can be solved, one way or the other, you've solved the problem.

And that is exactly what I like having the POCO option. Because it means that the designer of the tools let me have a lot more freedom than I would have otherwise. Again, take a look at WebForm1 as an example of a non POCO class, just try to work with it without also having the UI instansiated, and try having that outside a request, etc.