Most engineers who say they want an ORM, really want query composition.
What’s a good solution for that without a classic ORM?
Flyweight: An ORM for SQLite
71–80 of 105 posts
Re: Flyweight: An ORM for SQLite
#72Earlier quoted context omitted.
That is an atrocity on so many levels. For one, you're creating a hard coupling to a specific flavor of SQL. And that's not too mention the fact that you're taking an otherwise purely data object and embedding persistence logic into it - a horrifying abuse of OO.
> you're creating a hard coupling to a specific flavor of SQL You're just trading one coupling (specific flavor of SQL) to another (your ORM.) Assuming your application is layered correctly, when you write your own queries, all of your SQL queries are in a single place and can be updated. BUT: If you're using an ORM, and you let your data bound objects leak into all layers, the coupling is much much much harder to fi…
Adding persistence logic to a data object adds all kinds of bloat - it has to have a connection to the database, which now makes unit testing a pain in the neck and introduces all kinds of weirdness around serialization. Now it has a bunch of CRUD methods, so developers have to know which methods are for business logic versus persistence. Also, data objects with persistence logic aren't really suited to be published in a shared library as clients should not access your database directly.
All around, it's just a really terrible idea.
Re: Flyweight: An ORM for SQLite
#73Earlier quoted context omitted.
That is an atrocity on so many levels. For one, you're creating a hard coupling to a specific flavor of SQL. And that's not too mention the fact that you're taking an otherwise purely data object and embedding persistence logic into it - a horrifying abuse of OO.
Many/most ORMs (the ones that follow the ActiveRecord pattern) do this as well though. I prefer to avoid mixing concerns and use datamapper-based ORMs myself, but what GP wrote is fundamentally not that different than what a lot of ORMs do.
Re: Flyweight: An ORM for SQLite
#74Earlier quoted context omitted.
Many/most ORMs (the ones that follow the ActiveRecord pattern) do this as well though. I prefer to avoid mixing concerns and use datamapper-based ORMs myself, but what GP wrote is fundamentally not that different than what a lot of ORMs do.
I'd dispute "most", as it does not match my experience across a number of languages. Yes, active record sorta does it but, as best I recall, those methods are all implemented generically as mixins, so not actually a part of the data object. This seems to be advocating for data specific queries to be added to each class.
I don’t disagree with the overall point you’re making, I’m just pointing out that it’s very common
Re: Flyweight: An ORM for SQLite
#75Earlier quoted context omitted.
> you're creating a hard coupling to a specific flavor of SQL You're just trading one coupling (specific flavor of SQL) to another (your ORM.) Assuming your application is layered correctly, when you write your own queries, all of your SQL queries are in a single place and can be updated. BUT: If you're using an ORM, and you let your data bound objects leak into all layers, the coupling is much much much harder to fi…
Not at all - in most architectures, your data objects know nothing about how they are being stored, instead delegating that to a repository class or something similar. Adding persistence logic to a data object adds all kinds of bloat - it has to have a connection to the database, which now makes unit testing a pain in the neck and introduces all kinds of weirdness around serialization. Now it has a bunch of CRUD meth…
That's not what you do if you write your own queries. That's what a novice does after learning object oriented programming.
For a more accurate example, look at things like Hibernate / NHibernate / Entity Framework and lazy loading. They inherit from classes at runtime and will transparently run queries as business logic navigates relationships on an object graph. It's "not wrong," but it can lead to all kinds of problems and painful refactors. (But it's totally "worth it" in prototypes, one-offs, and throwaway code.)
If you don't do lazy loading, Entity Framework still requires that you pre-declare which relationships you will traverse. It's intended that your business logic uses Entity Framework APIs to say what part of the object graph it will use. (Thus tightly coupling your application to your ORM, which means your trading tightly coupling to a database to tightly coupling to a framework / library.)
But, keep in mind that the ORMs I mentioned tie the objects to the database connection. It isn't quite as intense as "Adding persistence logic to a data object", but they do track that, if you modify an object, it can only be saved on the transaction that it was loaded from; or if you're using lazy loading, lazy loading only works if the transaction is still open.
If you build a layer around your data access code that fully shields your business logic from your ORM, you've "done it right." But, at that point your ORM's value becomes negligible, because from the perspective of your business logic, it doesn't matter if your data access layer has hand-optimized SQL or an ORM; but you've lost one of the real selling points of an ORM, which is that you can easily do your data access from within your business logic. Which is why I say that the biggest mistake is assuming you should, or shouldn't, use an ORM.
Re: Flyweight: An ORM for SQLite
#76Re: Flyweight: An ORM for SQLite
#77const fights = await db.fights.get({ cardId: 9, titleFight: true }); translates to select * from fights where cardId = 9 and titleFight = 1; Confession: something about ORMs has never clicked with me.. none of them ever seem simpler than SQL.
You're coming at it from a slightly wrong angle. You are completely right that for queries, there's really no gain, you just end up having to learn both SQL and whatever your ORMs DSL is. Where ORMs are useful is once you have your objects. The usefulness of an ORM is being able to say: user.email = 'new@example.com' user.groups.append('admin') user.save() Also being able to work on your data in objects or structure…
That example you give here doesn’t require an orm, though. In ColdFusion world they use(d to use?) a pattern called dao, data access object.
Re: Flyweight: An ORM for SQLite
#78const fights = await db.fights.get({ cardId: 9, titleFight: true }); translates to select * from fights where cardId = 9 and titleFight = 1; Confession: something about ORMs has never clicked with me.. none of them ever seem simpler than SQL.
This is expanded when migrations are brought into the project.
We can train the data model to have a single management point, that being the file where the ORM classes are defined.
Re: Flyweight: An ORM for SQLite
#79const fights = await db.fights.get({ cardId: 9, titleFight: true }); translates to select * from fights where cardId = 9 and titleFight = 1; Confession: something about ORMs has never clicked with me.. none of them ever seem simpler than SQL.
I tend to agree, I'm more partial towards Micro-ORMs, ideally with a 'natural' DSL; something that is a good blend of 'SQL'-ness and 'target_language'-ness.
I can think of SlickDb (Scala), Linq2Db (C#), Ecto (Elixir) was good if definitely 'elixir-y'... IDK what other languages have such magical things; I know all of the above lean heavily on certain language features to provide their magic.
In the case of SlickDb, while I don't write Scala I read a lot of it, and could always understand what it was doing. In the case of Linq2Db, it just plain has a DSL that is 'close enough' to SQL. I love it and have saved multiple teams from EF with it. Ecto, as mentioned above... it wasn't -bad- but definitely walked the line of 'just write SQL' to me. (I'll admit however I am at best a good elixir app -maintainer-...)
In general,
- 'object tracking' is bad; I have yet to see a good use case where it doesn't wind up masking scope of modifications in the long run.
- 'overly native' DSLs are usually bad; the closer a DSL is to the 'metal' of SQL, the less likely you are to be surprised by the generated SQL (e.x. the 'surprises' of linq2Db tend to be far fewer than in, say, Entity Framework)
- If your language doesn't have a good DSL-providing MicroORM... try to find a basic MicroORM that just takes SQL, and write tooling around it.
Re: Flyweight: An ORM for SQLite
#80Earlier quoted context omitted.
You can compose SQL queries with subqueries. My experience with ORMs is that they’re a minefield of performance cliffs. It’s easy to accidentally generate suboptimal SQL or introduce additional round trips unless you’re very careful about the code you write, at which point you might as well write SQL directly and be at the mercy of one less black box.
If you compose SQL with subqueries you tend to do less composition in general (because you are restricted in what you can compose), and you are more at the mercy of the query planner, which is its own black box. I'd rather simply understand how my ORM generates queries, and then use the ORM to get the full power of my language of choice in creating the right SQL queries.
Depending on the ORM this may be be far from trivial. Despite being a C# dev rather than a DBA I can say that I have a better understanding at least one DBMS's query planner than what Entity Framework will generate for certain queries [0].
I'll note that -good- MicroOrms can make 'subqueries' in a fairly composable way.
I think with a manual SQL, you can still make a 'good' mini-DSL with subqueries, but it will take some thought to do well. Actually, with -extremely- thoughtful design it can be far more performant and productive, but IMO the complexity would need to show ROI to be worth it.
But in -either- case, in the long run the restrictions help with perf and maintenance. Whether it's hand-written mini-DSL or a good MicroORM DSL, you have a much better mechanical sympathy for what you're doing to the DB, and it becomes easier to write Table designs that are performant.
> and then use the ORM to get the full power of my language of choice in creating the right SQL queries.
Now you have to learn an ORM, a Query planner, -and- how to make them play nice.
[0] - There has been more than one shop where I was the 'EF Expert'... take that as you will.