I have a situation that I can't use mocks with DataObjects.NET due to "create", "update" and "delete" operations are embedded to the Entity derived classes that is supposed to be used as domain model items in the project.

I would like to know if DataObjects.NET has best practices concern TDD? (and specific questions) How can I separate database operations from domain objects?

asked Oct 25 '10 at 06:19

alex_razv's gravatar image


edited Oct 25 '10 at 06:22

Alex%20Yakunin's gravatar image

Alex Yakunin

One Answer:

Sorry for quite long delay with answer to this post - I understood I should finish and publish this comparison before answering it. Please read it - all the conceptual differences touched here are covered in it.

Let's review the questions:

  1. I would like to know if DataObjects.NET has best practices concern TDD? - Yes.
  2. How can I separate database operations from domain objects? - It's a bad idea: In fact, you're going to test "your" DAL, which actually isn't yours, and is already tested.

Now - a deeper explanation:

How to test Domain objects based on our Entities?

The answer is simple:

  • Test everything except persistence itself. Rely on fact that automatic saving, lazy loading and everything else we provide work as expected. We write our own tests for such parts of the framework, so may be 99% of your own tests related to persistence won't add anything new.
  • Write persistence related tests only if you feel there can be a problem at our side This might help you to isolate the problem (btw, frequently it's not @ our side even in such cases); the reproducible problem is normally resolved much faster than the one requiring deep investigation. Finally, you'll be sure it won't appear further (btw, we write a test for any approved issue as well).

The basis for this recommendation is simple: TDD doesn't imply all the dependencies must be tested. Likely, no one would even think about adding tests for classes from System or NUnit.Framework namespaces. So using ORM framework but testing its persistence engine is the idea of this kind.

How can I separate database operations from domain objects?

I'd rephrase it as "Can I design for persistence ignorance (PI) with DO?".

As you might suspect, you can't do this with our Entities.

If you really need this, the only good option here is to provide a POCO/PI facade. In relatively simple cases (I mean the ones that are normally shown in DDD as repository pattern samples) books this is relatively simple as well, but when complexity grows up, this becomes more and more complex. General solution we're thinking about will require several man-months of coding.

The comparison I gave @ the beginning of this post explains pros and cons of separating persistence from Domain models pretty well. We believe it's generally a bad idea - especially, in complex cases (i.e. when models are large and interaction is complex). I remember earlier I asked if there are any big app implementing PI - at least, in form of abstraction from ORM - and, as you may find, there are no good examples.

Of course, that's just my own opinion based on our own software design experience (we deal with really big models). As you see, I also wrote that we're thinking about supporting POCO/PI - obviously, not because I consider these practices as good. There are actually two reasons behind this:

  • The idea of insisting that widely recognized brand (POCO/PI) actually isn't attractive is bad, independently of reasons. It's much better to support it than fight with it.
  • We'll implement this in a way helping to solve one more issue: currently N-tier scenarios with DO imply DO must be available @ every side (or you must use WCF Data Services or any other similar facade). Obviously, this isn't good in cases when client must be lightweight. So we'd like to solve tier connection problem as well - in general and transparent way.

Likely, the solution will be ORM-agnostic. That's good, since N-tier connection problem isn't solved well by nearly any ORM framework now; well-known products trying to address it include WCF Data Services, WCF RIA Services and CSLA.NET, but all of them have serious limitations. E.g. both WCF Data Services and WCF RIA Services make you using their own generated entities on the client (btw, this means you can use any Domain model @ the server - client won't see it anyway); both frameworks can't transmit arbitrary LINQ queries (bad, if UI is rich). CSLA is even worse - the limitations it applies are much wider.

So we seriously consider this option, and moreover, we know how to do this well. But since currently this isn't implemented, you should care about this by your own - e.g. by implementing repository pattern by your own. Personally I dislike this idea as well - mainly, because it doesn't work with complex models. On the other hand, it's easy to understand and implement (with DO as well), and that's the reason people like it.

But first you must think if you really need this. Remember that:

  • You're exchanging design simplicity to pattern conformance. You'll need to provide a facade for nearly any feature we already implemented.
  • If you need this for N-tier scenarios, think about WCF Data Services and the way shown @ our own WCF sample. They're much simpler.

answered Nov 08 '10 at 11:35

Alex%20Yakunin's gravatar image

Alex Yakunin

edited Nov 08 '10 at 11:36

Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

powered by OSQA