views:

420

answers:

2

So as I understand it with good loose coupling I should be able to swap out my DAL with a couple lines of code at the application root.

I have 2 DAL written, Linq-to-sql and a JSon file repository (for testing and because I wanted to try out the System.Web.Scripting.JavascriptSerializer).

linq to sql will create entities instead of my business models. and feed them upwards through an IRepository which is using constructor injection at the application root.

my JSon layer doesn't have any autogenerated classes from which to deserialize so I'm lost as to a simple way to have it depend on an interface or abstract class and still function.

This question is based on the following assumptions/understandings:

  • I believe I would need the linq to sql layer to implement an interface so the application domain at compile time can dictate that the entity classes are going to have a place to read/write all the current model's fields
  • Any Business logic dictates a need for another set of classes with almost the same names and same properties in the model layer
    • Then conversion methods that take the DALs objects and translate them to business objects and back would be needed. (even if both sides are implementing the same interface this seems very inefficient)
      • This code is yet another place that would have to make a change if the model class or interface changed (interface, business class, view, dal entity)
  • Deserialization of any alternative DALs requires I create 'entities' with the same properties and fields in that layer(more duplication)

So to meet all of the flexibility/agility goals it appears I need an interface for each application domain/business object, a concrete class where business logic can live, and DAL objects that implement the interface (this means layers that don't autogenerate entities would have to be hand coded pure duplication).

How would I use loose coupling without a ton of duplication and loss of DRY?

+2  A: 

Not that I understand the problem correctly, but to solve duplicated classes you may use AutoMapper.

Note that you may apply mapping declaratively or using reflection, i.e. semi-automatically. For example see here - this is not about data layer, but shows how simple attributes can help to automate mapping. In that case MVC applies attributes, but you may invent your own engine that looks for [Entity("Order")] attribute and applies AutoMapper.

Also you cannot have 100% persistence independency with just "couple of lines". ORM selection plays big role here. For example Linq-To-SQL cannot use plain classes (POCOs) so it's not as easy to re-use them as with NHibernate, for example. And with Repository you're going to have many queries in the data layer; different ORMs usually have different query syntax or implementation (even Linq not always compatible between ORMs) so switching data access can be a matter of replacing data layer completely, which is not couple of lines (unless your app is "Hello, world!").

The solution with AutoMapper above is actually a kind of self-baked ORM... so maybe you need to consider a better ORM that suites your requirements? Why don't you use EF4, especially given that it supports POCOs now, and is very similar to Linq-to-SQL, at least with query language?

queen3
I didn't mean to imply just a few lines of code in the top, as the new data layer would of course have to be coded to the app domain per data layer, but with 2 already coded to the same interface/repostiory standards changing from one to the other should be a few lines of code at the application root. I don't have any experience with automapper or EF, so I'll check those out and see if they help. I was hoping to go without 3rd party libraries so EF may be preferable.
Maslow
also EF4 is not set for official finalized release until march, right?
Maslow
Yes but it's still worth looking at. For example, see http://blogs.msdn.com/adonet/archive/2009/07/22/customizing-t4-templates.aspx - basically you can use T4 templates to generate any models from EF models - this is what you need as far as I understand. If you can't use EF4, go for AutoMapper - I personally don't like EF anyway ;-) and AutoMapper is helpful not only for DAL.
queen3
+1 Many good points, particularly starting out with AutoMapper as a pragmatic approach.
Mark Seemann
+1 I've downloaded and started using Automapper, but I haven't figured out if there's some way I can use it to map a view to a dynamic type. I can create a run-time type that implements my interface though. Mark says I'll have to make to presentation models, I'll go that route for now as I am not sure of the ramifications of trying to use this beta code for something I hope to release personally before march, and projects at work.
Maslow
+3  A: 

Welcome to the beautiful and exciting world of loosely coupled code :)

You understand the problem correctly, but let me first reiterate what you are already implying: The Domain Model (that is, all Domain classes) must be defined independently of any specific Data Access technology, so you can't use auto-generated LINQ to SQL (L2S) classes as a basis for your Domain classes for the simple reason that you can't really reuse those together with other technologies (as you have found out with your JSON-based Repository).

Interfaces for each Domain object is not even going to help you, because to avoid Anemic Domain Models you will need to implement behavior in the Domain classes (and you can't put behavior into interfaces).

This means that to hydrate and dehydrate Domain objects you must have some mapping code. It has always been like this: in the old days we had to map from IDataReader instances to Domain classes, while now we need to map from Data (L2S) classes to Domain classes.

Could we wish for something better? Yes. Can we get something better? Probably. The next version of the Entity Framework will support Persistence Ignorance for exactly this reason: you should be able to define your Domain model as POCOs and if you provide a map and a database schema, EF will take care of the rest.

Until that arrives Microsoft doesn't have anything that offers this kind of funtionality, but NHibernate does (caveat: I have zero experience with NHibernate, but lots of smart people say that this is true, and I trust them on that). This is a major reason that so many people prefer NHibernate over EF.

Loose coupling requires lots of mapping, so I can only second queen3's suggestion of employing AutoMapper for this kind of tedious work.

As a closing note I do want to point out a related issue: Mapping doesn't necessarily imply a violation of DRY. The best example is when it comes to strongly typed ViewModels that correspond to a given Domain object. Don't be fooled by the semantic similarity. They may have more or less the same properties with the same values, but their responsibilities differ vastly. As an application grows, you will likely experience that little divergences sneak in here and there, and you will be glad you have that separation of concerns - even if it initially looked like a lot of repetitious work.

In any case: Loose coupling is more work at the beginning, but it will enable you to keep on evolving an application where a tightly coupled application would freeze in maintenance hell long before. You are in for the long haul, but instant gratification it ain't.

Mark Seemann
+1 lots of good ideas. Maybe someday soon i'll give EF4 or NHibernate a crack. going to do what I can with domain objects, and automapper
Maslow