O/RM is like adding brain damage to your database
Tags: database, oop, architecture
Published: 2022-08-25 09:07:00

O/RM is the art of fitting a square peg into a round hole. Your SQL database is based upon records and relations, and objects are based upon OOP. OOP is little more than a [software development mass psychosis](https://dev.to/polterguy/oop-a-software-development-mass-psychosis-9n4) may I add - However, ignoring the facts that OOP basically destroyed everything that was good in this world, O/RM is still rubbish tech by itself, and the whole idea of _"mapping objects to database records" needs to stop_. Because at the end of the day O/RM is like adding brain damage to your database.

For instance, using the repository pattern makes it very tempting to _"save"_ your objects. Ignoring that the repository pattern is little more than a thin layer on top of CRUD, _"saving"_ your objects results in all sorts of difficult to solve problems. For instance, imagine two people editing the same record simultaneously. Let's create a class to illustrate the problem.

```
class Customer
{
   string Name;
   string Address;
   string PhoneNo;
}
```

Imagine John and Jane working on the same object at the same time. John updates the customer's `Address`, and Jane updates the customer's `PhoneNo`. They both start working on the object at the same time, and have therefor _"fetched"_ the object from the database. John updates the `Address` field, and clicks _"save"_. Jane updates the `PhoneNo` field, and clicks _"save"_. Since Jane got her customer object from the _"repository"_ before John saved it, the `Address` is now reverted back to its old value, the value it had _before_ John updated it. This is referred to as a _"race condition"_. Because the one to save the object last _"wins"_.

![ORM race conditions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3iwswz22p4ql3pikks57.jpeg)

To solve the above problem, requires what's referred to as database locking mechanisms. SQL Server for instance solves this by allowing users to create `RowVersion` columns on tables. This is called _"optimistic locking"_, and tends to propagate into the GUI, resulting in leaky abstractions, requiring the developer being forced to add tons of garbage code to his GUI layer, making sure objects are truly saved when the user tries to save them.

There are different versions of database record locking techniques, but they're all basically garbage, and requires tons of garbage code to propagate, all the way out into the UI and the human being actually editing records. You are now left with a software _"solution"_ where something as fundamental as updating a single field on a single database record possibly might fail, forcing the end user to _"revert"_ his changes, and _"reload"_ the original object. 25% of your code is now safe guarding code, trying to prevent the user from applying race conditions to your data, and this garbage code penetrates from your database, through your middleware, into the UI layer of your app.

Ignoring the fact that 98% of software developers don't even know how to apply database record locking, and simply ignores it, resulting in garbage data in your database - Even if you apply a _"perfect"_ piece of code safe guarding for such scenarios, you're still ending up with garbage code, where something as fundamentally as changing a database record might result in the end user having a modal form in his face.

> "We couldn't save your object, do you want to force it, reload the original object, or cancel?"

Most end users wouldn't even understand what to do here, and probably simply call in sick, staying home the rest of the week - Or bother some tech guy, who'd need an hour to simply figure out why the object couldn't be saved. Hence, the use of O/RM in your database layer, resulted in an end user having half his day destroyed, not able to do his job.

> We have a word for this, and it's called madness!

## The big joke

The big joke in this equation is that you _do not need locking if you respect the database for what it is_. Your database is a relational database system, and it allows for updating individual fields, on individual records, on individual tables. To type it out with code, imagine John's change resulting in the following.

```
update customers set Address = 'xyz' where ...
```

Then imagining Jane's change resulting in the following.

```
update customers set PhoneNo = 'xyz' where ...
```

__It's literally that simple__. You've now eliminated all sources for potential race conditions. You no longer need locking, and you can basically SHIFT+DELETE 25% of your codebase, ending up with orders of magnitudes more safe code. No more _"synchronisation code"_ in your UI layer, middleware, or database.

The technical term for this is _"record slicing"_, and implies doing _partial updates on records_. However, this is fundamentally incompatible with best practice O/RM design patterns, such as Active Records, Repository Pattern, etc, etc, etc. I realise that some O/RM libraries do implement this slicing technique, but then you're no longer using your O/RM library as an O/RM library, but rather a sadly implemented substitute for SQL, and it becomes a terribly implemented functional programming language, with a sub-optimal database serialisation layer, violating every single _"best practice"_ you were taught as you started using O/RM libraries. The reasons this is impossible to implement in O/RM without violating OOP best practices, can be described as follows ...

> Can I have half your object please?

When phrased such as above, it is easily understood. OOP is based upon classes and strongly typing. Supplying _"half an object"_ to OOP simply doesn't make sense, and is literally impossible. Hence, if you want to apply record slicing in your O/RM, you're no longer using your O/RM as an O/RM, but rather something else, and you're no longer using your OOP language as OOP, but rather like a badly implemented functional programming language.

If you want to see how we solved this in [Aista](https://aista.com), you can watch the following video where I demonstrate record slicing, completely eliminating the problem.

{% embed https://www.youtube.com/watch?v=6XD45PE7eYQ %}

If you want to study how [Hyperlambda](https://aista.com/hyperlambda/) solves this problem, you can register a one month trial cloudlet below, and reproduce what I did myself, by creating your own frontend in a couple of minutes implementing record slicing.

* [Register a free Low-Code backend CRUD generator here](https://aista.com/)