Design Patterns – How to Keep Objects Decoupled Between Layers

designdesign-patternslayersobject-oriented

I think this is a common design problem, but I keep scratching my head every time I face it.

On one side, we have our API which sends or receives simple structures aimed to be consumed by web apps, mobile etc. We could potentially have multiple APIs aimed for different devices. On the other side we have our internal domain model which may or may not match the data store entities.

Let assume the following POJOs to assist the discussion.

@POST
public addBlogPost(BlogPostApi blogPost) { ... }

// api model
public class BlogPostApi {
  ...
}

// domain model
public class BlogPost {
  ...
}

// db model
public class BlogPostEntity {
  ...
}

First, we could use the same model in all three layers. While that could be a solution for very simple services, it's usually not a good idea since all the layers are implicitly coupled. So, I'll assume we want to use a different model object per 'layer'.

One approach I've seen widely used is to create adapters between layers. While that solves the problem, it creates an explosion of classes you need to maintain. In the (common) case when you add a new field to the data store which needs to get exposed on the UI as well, 3 POJOs + 2 adapters need to be changed. There's always the risk of forgetting to change one of those. This process could be automated slightly, with the use of an object mapper library.

Another approach I've heard is the use of interfaces. Two or more classes implement the same interface which exposes the get/set methods for 'common' fields. This removes the risk of forgetting to change something, but it creates coupling. Also, I find this use of interfaces wrong, since interfaces should expose functionality.

I'm leaning towards the object mappers. Does anyone know of a olution for this problem?

Best Answer

I think adapters is the right approach.

it creates an explosion of classes you need to maintain. In the (common) case when you add a new field to the data store which needs to get exposed on the UI as well, 3 POJOs + 2 adapters need to be changed

That's the effect of having a loosely-coupled system, but you're only describing the negative effect of the loose coupling. What happens when you want to add a new field to the data store, but you don't want to expose it on the UI? This design will allow you to support this use case. It also supports cases where you want to store things in the database differently than how they look in the domain model which is a fairly common need. For example, I like to have auto-increment numeric ids on all my database tables for foreign keys and join efficiency, but often the domain model may use some other unique field as its identifying field. With the three model approach I don't have to leak the db id to the domain layer.

Related Topic