“Just use SQL”, they say. “No need for ORMs”, they add. And they may be right, but… Let's look on how this can lead to accidental complexity piling on, derailing our initially simple problem.
From a backend engineer, that writes SQL for a living, sorry this is Utter garbage.Try doing group by, rownumber, dense rank, lead, lag,pivot in JavaScript . But I am so happy because of article like this, I will always have a job. And the beginners that read this article will never learn system design in their life. And will be replaced by AI early in their careers.
I’d suggest reading the full article, as it’s not against using SQL. It’s showing how blindly following blank statements like “Just do X” can escalate with accidental complexity.
I saw such things happening in numerous projects. Not only with SQL.
I read this, and I read your article In Defense of ORMs.
I am somewhat in that camp of ORM-haters that you are trying to address, but I don't think that we necessarily disagree - I suspect we may be using different definitions of what an ORM is. And maybe I'm wrong and being too narrow!
But, in my mind, ORM is a framework that tries to map object identity & lifetime back to the database. You know the classic ActiveRecord type pattern where if I have a User object and call `setEmail`, it's doing the SQL UPDATE transparently in the backend. I _do not_ hold that just any database utility framework is an ORM.
I gladly use utilities that can codegen type-safe systems around my database schema while hating on traditional ORMs, because like you I'm all-in on type safety and avoiding stringly-typing things.
I started programming in the end of last century, using spaghetti PHP/SQL. Than I felt in love to ORM. Created half dozen of them. Until I started questioning myself why? And later why not?
Today I'm against ORM for 80% of the real world cases. I identify myself with your article. I had the same struggle, until I understand that when you change from ORM to SQL, you really need to stop thinking in sql builders and focus on pure SQL. Your proposed example is the typical one, where you forget that YOU should write the SQL, not write code to than write the SQL. Let me explain with an alternative solution to the same problem:
function filterUsers(filter?: UsersFilter): Promise<User[]> {
Without using any query builder, I can filter by email and/or username, using equal or like. The query uses template literals to build the sql with the correct parameters.
If I pass NULL for email or userName, the sql ignores it. Magic!
With that in mind, is possible to build any query using only sql.
If you're interested, I would like to expand this conversation.
To avoid complexity and keep using SQL you need something like a hybrid between ORM and SQL, something like SqlP https://dev.vvveb.com/sqlp
Yup, there are also tools like JOOQ, Dapper, etc. Also, modern database SDKs are quite accessible in terms of mappings. So there's a middle ground.
In the follow-up, I'll try to explain what I'm building with Pongo, which can be a similar example.
From a backend engineer, that writes SQL for a living, sorry this is Utter garbage.Try doing group by, rownumber, dense rank, lead, lag,pivot in JavaScript . But I am so happy because of article like this, I will always have a job. And the beginners that read this article will never learn system design in their life. And will be replaced by AI early in their careers.
But Slava Ukraini.
I’d suggest reading the full article, as it’s not against using SQL. It’s showing how blindly following blank statements like “Just do X” can escalate with accidental complexity.
I saw such things happening in numerous projects. Not only with SQL.
p.s. Also, why so mean? 🤔
I read this, and I read your article In Defense of ORMs.
I am somewhat in that camp of ORM-haters that you are trying to address, but I don't think that we necessarily disagree - I suspect we may be using different definitions of what an ORM is. And maybe I'm wrong and being too narrow!
But, in my mind, ORM is a framework that tries to map object identity & lifetime back to the database. You know the classic ActiveRecord type pattern where if I have a User object and call `setEmail`, it's doing the SQL UPDATE transparently in the backend. I _do not_ hold that just any database utility framework is an ORM.
I gladly use utilities that can codegen type-safe systems around my database schema while hating on traditional ORMs, because like you I'm all-in on type safety and avoiding stringly-typing things.
That's a good point. Probably we use a mix of both, ORMs for basics and SQLs for advanced where we need performance boosts.
I started programming in the end of last century, using spaghetti PHP/SQL. Than I felt in love to ORM. Created half dozen of them. Until I started questioning myself why? And later why not?
Today I'm against ORM for 80% of the real world cases. I identify myself with your article. I had the same struggle, until I understand that when you change from ORM to SQL, you really need to stop thinking in sql builders and focus on pure SQL. Your proposed example is the typical one, where you forget that YOU should write the SQL, not write code to than write the SQL. Let me explain with an alternative solution to the same problem:
function filterUsers(filter?: UsersFilter): Promise<User[]> {
return connection.execute.query`
SELECT userName, email FROM users
WHERE COALESCE(email LIKE ${filter.email}, TRUE)
AND COALESCE(userName LIKE ${filter.userName}, TRUE)
`;
}
// USAGE:
filterUsers({email: "foo@bar.com", userName: "%foobar%"})
Without using any query builder, I can filter by email and/or username, using equal or like. The query uses template literals to build the sql with the correct parameters.
If I pass NULL for email or userName, the sql ignores it. Magic!
With that in mind, is possible to build any query using only sql.
If you're interested, I would like to expand this conversation.
Great article!