Do I need a persistence model when using gorm in a clean architecture setup?

Viewed 263

In a clean architecture approach to software the entities are the innermost layer and should not depend on something like an ORM.

For convenience I would like to use an ORM in my project and gorm seems to be a popular library. In the gorm docs the recommended way to use it is by having the gorm.Model struct included in the structs you want to persist in the database.

When trying to use gorm in my project and following clean architecture I thus end up with a mapping layer which maps my entities to and from a persistence model specific to gorm in order to keep the gorm dependency out of my entities. This seems to eradicate all the benefits of using an ORM and in e.g. this blog post is explicitly warned about.

It seems to me avoiding the mapping layer while following clean architecture can only be achieved by using a less invasive ORM or even just a sql extension like e.g. sqlx where I can use my entities directly?

1 Answers

I have a feeling this question is better suited to Software Engineering SE but I will make an attempt at answering.

The short answer to your question is: Yes.

If you want to follow Clean Architecture to the letter, the thing to do is build domain models that don't depend on your persistence layer at all. With gorm, that necessitates building a domain <-> persistence model mapping layer and all the added complexity that comes from that. Gorm will still make querying and saving that persistence model easier than creating your own queries, and compared to ORMs in other languages that I've experienced, it's still fairly lightweight.

Technically you do not need to have gorm.Model in the model structs. Having an ID int field, plus any of the CreatedAt, UpdatedAt, DeletedAt fields that you want is enough (this is what gorm.Model gives you). But invariably you will be adding other artifacts that are to do with how gorm does things, so you do not escape this dependence if the gorm package isn't present in your model structs.

BUT

This begs the question of whether following Clean Arch to the letter is the right decision for your project. Like all design decisions, it bears tradeoffs and makes more or less sense according to the scope and complexity of the system being built. If you foresee challenges that your project will run into that Clean Arch can mitigate then the extra investment now will pay off. If, on the other hand, aspects of the architecture are there to mitigate problems you're unlikely to run into in your particular situation, then you may be more forgiving. The conclusion to the blog post you linked makes an argument along the same lines:

NHibernate provides the best set of trade-offs between the implementation complexity and the overall purity. There still will be ORM concerns leaking into your domain model, however. But I think it’s a low price for all the benefits you’ll get out of it: speed of development, rich functionality, and separation of concerns.

Related