Blog Stats
  • Posts - 99
  • Articles - 5
  • Comments - 39
  • Trackbacks - 108

 

DDD and SOA

Over the last few weeks Clemens Vasters and others have been downplaying O/R mappers and DDD in architecture.

In reading though a lot of their posts I am finding a lot of misunderstandings about O/R mapping and DDD.

http://friends.newtelligence.net/clemensv/PermaLink,guid,0fbf07a9-9e7a-4db4-a305-58250ac57a73.aspx

http://friends.newtelligence.net/clemensv/PermaLink,guid,92eaea8c-778d-4512-af03-d332785f65f5.aspx

I have read some good counter points from http://www.lowendahl.net/showShout.aspx?id=93 and from Jimmy Nilsson among others in comments ... just figured I would add a few of my own.

OR Mappers are a silver bullet solution in DDD

O/R mapping is not a silver bullet to solve your database access (though some people will tell you that it is). Mapping should be used only as a tool to handle the cases it is really good at handling (when I say good I mean it saves you 40 lines of code:)). A main feature that I look for in an O/R mapper is the ability to get around it when I need to, such as calling a sproc (especially if it support CRUD sprocs such as Wilson O/R). If you are familiar with DDD a general pattern that will emerge is common repository operations happening through your O/R mapper and specific operations that an O/R mapper might not be particularly good at happening through another method bypassing the O/R mapper. Of course since we have placed this within the repository we have also abstracted the concept away from the client code.

As for performance, there is a myth that sprocs are significantly mroe performant in comparison to dynamic SQL. This can be the case if the dynamic SQL must execute multiple round trips but in 99% of cases they will be identical or so close that the difference is meaningless (both are pre-compiled)

OR Mappers only work with direct table access

O/R Mapping does NOT only work with direct table mapping, but it works a lot better with it. Many O/R mappers, Paul Wilson's is a great example, support sprocs but many of the normal functionalities are taken away when being used in conjunction with sprocs ... that said let's look quickly at the reasons for using sprocs ... I generally hear two security and performance.

I generally disagree with the concept of using sprocs for security as I find it to be security through obscurity. There are some isolated cases where it can be applied in a good way but in general it serves little purpose and frankly if someone has hacked you (lets say a web app) to the point where they are in your database you probably have bigger security problems to worry about.

Take deleting a customer as an example:

With an O/R mapper having direct table access if I get access to it's connection I could feasibly delete the entirety of the customer table.

Using Sprocs I will generally have a DeleteCustomerById or similar proc that takes a customer id as a parameter. Someone will eventually figure out to use this. Other ideas have come up such as passing in a token that controls the privileges (again security through obscurity) as the application will at some point need to know about these tokens as well and we are assuming that the application has already been compromised.

That said, I do agree that there are some isolated places where using sproc based security is a good thing ... A key theme through this post is going to be using the right tool and thee are all nothing more than tools. To me a standard saying you will always (or always not) use stored procedures is one step above insanity.

Transactions are hard

Transactions are hard. Databases are doing a really good job with data concurrency management, especially with stored procedures. If you are loading and managing data as object-graphs, how do you manage transaction isolation? How do you identify the subtree that's being touched by a transaction? How do you manage rollbacks? What is a transaction, anyways?

Wow guess they don't read my blog as I have discussed recently 2 separate mechanisms for doing this (locking mementos for simple transactional behaviors and copy of object which offers the concept of isolation levels). Anyways most O/R mappers do not have their “own” concept of a transaction but instead delegate that work to the database. Generally a UnitOfWorkish pattern is used to know what has to be bundled into the transaction and a database level transaction is then used during the persist process. If the database level transaction fails one can either use one of the fancy methods I bring up to handle object graph rollbacks. Of course both of these things are thoughts OR mapping developers should be thinking about not people using OR mappers.

Reporting is hard

Reporting and data aggregation is hard. I'll use an analogy for that: It's really easy to write an XPath query against an XML document, but it is insanely difficult to do the same navigating the DOM.

This statement is actually accurate in many ways although things like Dlinq look quite promising for the future (XPath query type operations). As for reporting this is actually a quite common concern. Generally there are two separate uses for a system, the data input / everyday use and the back end reporting. Many times these two items do NOT even use the same data as it makes alot more sense to denormalize much of the data for reporting. That said, it is a common place where domain objects are not used because they don't make sense. This does take away some of the decoupling we have gained through the domain but reports are by their very nature heavily coupled to begin with.

http://domaindrivendesign.org/discussion/archive/reporting_from_database.html is worth a read.

Defining and resolving associations is difficult

  • Defining and resolving associations is difficult. 1:N is hard, because you need to know what your N looks like. You don't want to dehydrate 10000 objects to find a value in one of them or to calculate a sum over a column. That's work that's, quite frankly, best left in the database. I realize that some people worry how that leads to logic bleeding into the database, but for me that's a discussion about pureness vs. pragmatism. If the N is small, grabbing all related objects is relatively easy - unless you support polymorphism, which forces the mapper into all sorts of weird query trees. 1:N is so difficult because an object model is inherently about records, while SQL is about sets. N:M is harder.

    In most OR mappers this is actually quite easy for the first level relation (the same way you would do it by hand (select columns from table where fk=objectpk). This is why we give it the metadata above to handle this for us. We do in fact let the database do the work.

    What I found most interesting here was ... 1:N is so difficult because an object model is inherently about records, while SQL is about sets ... I find this interesting because although OR mapping deals with records, it also deals with a whole lot of sets.

    Services avoid coupling (autonomy) => Database schema and in-process data representation are disjoint and mapped explicitly

    This can also be done with OR mapping in fact I quite often use different schemas between my database and my domain. This also goes to the “changing schema“ comments as they can vary independently of each other.

    Not mentioned

    At no point is the fact that the OR mapping solution can immediately work with any database mentioned (even those with differing schema) as someone who deals with alot of systems that have this as a requirement this is a HUGE piece of functionality.

     

    The thought of the SOA methodologies being brought up as an alternative smells oddly like another “model” and anemic domain .. http://www.martinfowler.com/bliki/AnemicDomainModel.html I mean when we break it down we end up with a series of data transfer objects and a nice thick juicey service layer to handle everything. I thought we had already gone down this road and labeled it as an anti-pattern ..

    The basic symptom of an Anemic Domain Model is that at first blush it looks like the real thing. There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is very little behavior on these objects. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. Instead there are a set of service objects which capture all the domain logic. These services live on top of the domain model and use the domain model for data. - Martin Fowler

    That said SOA DOES have a place, as does DDD neither is always the correct answer and often the best answer is a combination of the two.

     


  • Feedback

    No comments posted yet.


    Post a comment





     

    Please add 8 and 6 and type the answer here:

     

     

    Copyright © Greg Young