Hacker News new | ask | show | jobs
by Kon5ole 24 days ago
>ORMs being a forcing function for domain modeling is enough benefit for me that it outweighs all of their obvious limitations.

That was a surprising take!

I know only a few ORM's but it seems they end up just adding another layer of DTO objects that are entirely separate from the domain classes anyway. So best case the ORM is just a detour for a good domain model. Worst case it creates a weird database-contaminated domain model that's hellish to maintain.

So I would't say ORMs force domain modeling, or even help. Are you perhaps thinking of a particular stack where the ORM is just one part of it?

3 comments

Why is your database so different from your domain?
>Why is your database so different from your domain?

Usually it's due to one of these:

- The domain deals with a lot of things that are not in the database.

- The domain is one of many and deals with just a fraction of what is in the database.

- The domain deals with things stored in several databases.

- The database was designed in the 90s and the domain is new.

- It's not my database so I can't change it.

(Even for greenfield systems I don't think it's generally desirable that the database matches the domain model.)

It's not that your domain is different, it sounds more like you don't know how to use ORMs. ORMs don't have to manage migrations, they don't have to even write into the database. When dealing with a bad database design, it can be a legitimate tactic to use ORMs in read-only mode and have writes still as hand-rolled SQL. You can do database-first ORMs, as well as code-first, where the database design is king, not the POCO.

> The domain deals with a lot of things that are not in the database.

You can have non-serialized properties. You can even can over-ride serialization/de-serialization of individual properties

> The domain is one of many and deals with just a fraction of what is in the database

You can use different ORMs for different parts of your domain, you could even wrap multiple ORMs in a wrapper repo pattern if you want

> The domain deals with things stored in several databases

As above.

> The database was designed in the 90s and the domain is new

Tons of solutions for this, one easy one is using SQL Views, just ask Claude. The weird thing here is that I've now dealt with this IRL like 5 times and came to the opposite conclusion of you. I found wrapping a bad DB design with an ORM a great first step in fixing it, as the ORM effectively acts as an easy strangler pattern.

> It's not my database so I can't change it

You can still use ORMs, ORMs don't have to manage migrations. Though I feel sorry for you working somewhere you still have a DB guy gatekeeping the database design in 2026.

The point is, every one of your objections are pretty trivially solvable with many mature ORMs, because everyone else had the same problems two decades ago and instead of throwing up their hands and hand-rolling their SQL, the ORM tooling was improved.

>It's not that your domain is different

You have mixed the posts you are replying to - the domain being different from the database is stipulated here.

I was giving examples of how this typically happens, and the reasons are entirely independent of whether or not an ORM is being used.

I am fully aware that you can handle any mess using an ORM as well, which is why I was surprised at the original claim that ORM's force proper domain models. I haven't observed that so I was genuinely curious.

Separately from that I have to say your suggestions of things to do to force an ORM into the situation are bad ideas. The complexity of custom serialization, various mapping hooks or attributes to bless individual properties will lead to pain and misery down the line.

Just accept the extra layer of DTO's. They're a detour over pure SQL but are at least easy to maintain and hold no surprises. They say there's a special place in hell for people who write SQL triggers and I think people who override ORM serializers are welcome there. ;-)

No thanks.

DTOs are one of the big code smells of a code base that does little but will be full of boilerplate. As soon as you see an automapper or a folder of DTOs you know you're in for some serious pain.

On the plus side you also know you can reduce the codebase by about 75%.

>DTOs are one of the big code smells of a code base

I actually agree but think serialization overrides are even worse, and the code smell that causes both of them is the ORM. ;-)

That doesn't sound at all like any ORM I've ever used. I've struggled in the past because The ones I've used are actively hostile to laying out data in the database in a way not proscribed by the ORMs philosophy. Heck of the ORMs I've used, one didn't support parameterized joins and the other didn't support joins at all.

---

It's not usually a DB guy gatekeeping, it's that multiple apps use the same database so layout changes are costly.

To be fair, there are a lot of lousy ORMs. Research and test well before adopting.
Except for the "multiple ORMs" part which is a level above it, it applies to the only one I've used extensively: Django for python. It has standard defaults, but just about everything overridable, and because models are python objects you can add methods or properties for extra data. There's even ways to define your own field types (the "serialization/de-serialization of individual properties"), which a decade ago people were using to provide json fields through libraries long before it was officially supported.

...and Django was like this 15 years ago when I first started using it. The core design hasn't changed, it just sounds like most other ORMs don't really know what they're doing.

>and Django was like this 15 years ago when I first started using it. The core design hasn't changed, it just sounds like most other ORMs don't really know what they're doing.

Django is an opinionated web framework that uses an ORM, not just an ORM.

Django can by all means be a great way to make a web site (I have little experience with it) but if you have a db that is accessed by various systems written in Java, dotnet, erlang or whatever else I suspect the smooth sailing of Django can run into headwinds quickly and the python plumbing you have to deal with then quickly becomes an issue in itself.

But I admit it's just a guess.

Most commonly ime the application domain may only be some small fraction of the database which is designed/optimised for a much broader dataset.
I doubt domain logic would ever be in 2NF. My domain logic certainly doesn’t have pivot tables of IDs for join lookup
> I know only a few ORM's but it seems they end up just adding another layer of DTO objects that are entirely separate from the domain classes anyway.

Entity Framework in particular has come a long way in this regard. Particularly owned & complex entities, value converters, etc.

https://learn.microsoft.com/en-us/ef/core/modeling/

> Worst case it creates a weird database-contaminated domain model that's hellish to maintain.

CQRS is good for this because it forces you into using a different write and read model. My write models are domain objects and my read models are DTOs that feed the UI and via projection I can shape them without issue.

Mh, in NHibernate when properly modelled, your Domain classes usually match the database/tables, so there is no need to have additional DTOs