Do all the things like ++ or -- rants, post your own rants, comment on others' rants and build your customized dev avatarSign Up
From the creators of devRant, Pipeless lets you power real-time personalized recommendations and activity feeds using a simple APILearn More
Search - "orm"
I’m surrounded by idiots.
I’m continually reminded of that fact, but today I found something that really drives that point home.
Gather ‘round, everybody, it’s story time!
While working on a slow query ticket, I perused the code, finding several causes, and decided to run git blame on the files to see what dummy authored the mental diarrhea currently befouling my screen. As it turns out, the entire feature was written by mister legendary Apple golden boy “Finder’s Keeper” dev himself.
To give you the full scope of this mess, let me start at the frontend and work my way backward.
This function allows the user to better see the rows in the API Calls table, for which there is a also search feature — the very thing I’m tasked with fixing.
It’s worth noting that above the search feature are two inputs for a date range, with some helpful links like “last week” and “last month” … and “All”. It’s also worth noting that this table is for displaying search results of all the API requests and their responses for a given merchant… this table is enormous.
This search field for this table queries the backend on every character the user types. There’s no debouncing, no submit event, etc., so it triggers on every keystroke. The actual request runs through a layer of abstraction to parse out and log the user-entered date range, figure out where the request came from, and to map out some column names or add additional ones. It also does some hard to follow (and amazingly not injectable) orm condition building. It’s a mess of functional ugly.
The important columns in the table this query ultimately searches are not indexed, despite it only looking for “create_order” records — the largest of twenty-some types in the table. It also uses partial text matching (again: on. every. single. keystroke.) across two varchar(255)s that only ever hold <16 chars — and of which users only ever care about one at a time. After all of this, it filters the results based on some uncommented regexes, and worst of all: instead of fetching only one page’s worth of results like you’d expect, it fetches all of them at once and then discards what isn’t included by the paginator. So not only is this a guaranteed full table scan with partial text matching for every query (over millions to hundreds of millions of records), it’s that same full table scan for every single keystroke while the user types, and all but 25 records (user-selectable) get discarded — and then requeried when the user looks at the next page of results.
What the bloody fucking hell? I’d swear this idiot is an intern, but his code does (amazingly) actually work.
No wonder this search field nearly crashed one of the servers when someone actually tried using it.
#2 Worst thing I've seen a co-worker do?
Back before we utilized stored procedures (and had an official/credentialed DBA), we used embedded/in-line SQL to fetch data from the database.
var sql = @"Select
Id = @ID"
In attempts to fix database performance issues, a developer, T, started putting all the SQL on one line of code (some sql was formatted on 10+ lines to make it readable and easily copy+paste-able with SSMS)
var sql = "Select ... From...Where...etc";
His justification was putting all the SQL on one line make the code run faster.
T: "Fewer lines of code runs faster, everyone knows that."
Mgmt bought it.
This process took him a few months to complete.
When none of the effort proved to increase performance, T blamed the in-house developed ORM we were using (I wrote it, it was a simple wrapper around ADO.Net with extension methods for creating/setting parameters)
T: "Adding extra layers causes performance problems, everyone knows that."
Mgmt bought it again.
Removing the ORM, again took several months to complete.
By this time, we hired a real DBA and his focus was removing all the in-line SQL to use stored procedures, creating optimization plans, etc (stuff a real DBA does).
In the planning meetings (I was not apart of), T was selected to lead because of his coding optimization skills.
DBA: "I've been reviewing the execution plans, are all the SQL code on one line? What a mess. That has to be worst thing I ever saw."
T: "Yes, the previous developer, PaperTrail, is incompetent. If the code was written correctly the first time using stored procedures, or even formatted so people could read it, we wouldn't have all these performance problems."
DBA didn't know me (yet) and I didn't know about T's shenanigans (aka = lies) until nearly all the database perf issues were resolved and T received a recognition award for all his hard work (which also equaled a nice raise).7
Biggest challenge I overcame as dev? One of many.
Avoiding a life sentence when the 'powers that be' targeted one of my libraries for the root cause of system performance issues and I didn't correct that accusation with a flame thrower.
What the accusation? What I named the library. Yep. The *name* was causing every single problem in the system.
Panorama (very, very expensive APM system at the time) identified my library in it's analysis, the calls to/from SQLServer was the bottleneck
We had one of Panorama's engineers on-site and he asked what (not the actual name) MyLibrary was and (I'll preface I did not know or involved in any of the so-called 'research') a crack team of developers+managers researched the system thoroughly and found MyLibrary was used in just about every project. I wrote the .Net 1.1 MyLibrary as a mini-ORM to simplify the execution of database code (stored procs, etc) and gracefully handle+log database exceptions (auto-logged details such as the target db, stored procedure name, parameter values, etc, everything you'd need to troubleshoot database errors). This was before Dapper and the other fancy tools used by kids these days.
By the time the news got to me, there was a team cobbled together who's only focus was to remove any/every trace of MyLibrary from the code base. Using Waterfall, they calculated it would take at least a year to remove+replace MyLibrary with the equivalent ADO.Net plumbing.
In a department wide meeting:
DeptMgr: "This day forward, no one is to use MyLibrary to access the database! It's slow, unprofessionally named, and the root cause of all the database issues."
Me: "What about MyLibrary is slow? It's excecuting standard the ADO.Net code. Only extra bit of code is the exception handling to capture the details when the exception is logged."
DeptMgr: "We've spent the last 6 weeks with the Panorama engineer and he's identified MyLibrary as the cause. Company has spent over $100,000 on this software and we have to make fact based decisions. Look at this slide ... "
<DeptMgr shows a histogram of the stacktrace, showing MyLibrary as the slowest>
Me: "You do realize that the execution time is the database call itself, not the code. In that example, the invoice call, it's the stored procedure that taking 5 seconds, not MyLibrary."
<at this point, DeptMgr is getting red-face mad>
AreaMgr: "Yes...yes...but if we stopped using MyLibrary, removing the unnecessary layers, will make the code run faster."
<typical headknodd-ers knod their heads in agreement>
Dev01: "The loading of MyLibrary takes CPU cycles away from code that supports our customers. Every CPU cycle counts."
Me: "I'm really confused. Maybe I'm looking at the data wrong. On the slide where you highlighted all the bottlenecks, the histogram shows the latency is the database, I mean...it's right there, in red. Am I looking at it wrong?"
<this was meeting with 20+ other devs, mgrs, a VP, the Panorama engineer>
DeptMgr: "Yes you are! I know MyLibrary is your baby. You need to check your ego at the door and face the facts. Your MyLibrary is a failed experiment and needs to be exterminated from this system!"
Fast forward 9 months, maybe 50% of the projects updated, come across the documentation left from the Panorama. Even after the removal of MyLibrary, there was zero increases in performance. The engineer recommended DBAs start optimizing their indexes and other N+1 problems discovered. I decide to ask the developer who lead the re-write.
Me: "I see that removing MyLibrary did nothing to improve performance."
Dev: "Yes, DeptMgr was pissed. He was ready to throw the Panorama engineer out a window when he said the problems were in the database all along. Didn't you say that?"
Me: "Um, so is this re-write project dead?"
Dev: "No. Removing MyLibrary introduced all kinds of bugs. All the boilerplate ADO.Net code caused a lot of unhandled exceptions, then we had to go back and write exception handling code."
Me: "What a failure. What dipshit would think writing more code leads to less bugs?"
Dev: "I know, I know. We're so far behind schedule. We had to come up with something. I ended up writing a library to make replacing MyLibrary easier. I called it KnightRider. Like the TV show. Everyone is excited to speed up their code with KnightRider. Same method names, same exception handling. All we have to do is replace MyLibrary with KnightRider and we're done."
Me: "Won't the bottlenecks then point to KnightRider?"
Dev: "Meh, not my problem. Panorama meets primarily with the DBAs and the networking team now. I doubt we ever use Panorama to look at our C# code."
Needless to say, I was (still) pissed that they had used MyLibrary as dirty word and a scapegoat for months when they *knew* where the problems were. Pissed enough for a flamethrower? Maybe.9
I worked once in a company which had this tourist app which should show places on map of the city. Unfortunately it slowed the App down to load more then a couple of places. Their solution was to limit the number of loaded places to teb and prohibited zomming out. I made it handle thousands of places at the same time. Main reason for the Performance issue was, that they sent all data they had about places big, big json objects with large text blobs) to the frontend. This part was easy, I instead sent only the data needed for the map like coordinates and icon type obviously. But still the backend struggeled hard with many objects from the DB, because they built a really shitty orm or what ever this was supposed to be: every line of data retrieved from the DB was immideatly wrapped in some class wich direved from another class which had some magic methods in it which caused some absurd loops over all other obejcts and even more DB queries in unexpected moments and also in the fucking constructor. So it turrned out that the map issue was only the top of the iceberg, since using any data from the DB was extremely expensive. The hard part was to understand the insaness of this abnormination and find the bottlenecks.8
Look at that. The very fucking smart colleague spent 40 days implementing a repository pattern (WHEN WE'RE USING AN ACTIVE RECORD ORM), breaking stuff left and right. Does he use that fucking pattern at the very least?
Of course he doesn't. And along the way he's making sure to create conflicts with the stuff he broke (and I'm fixing). By the time I fix the merge conflicts of one commit, he pushed 6 of them.9
A gigantic codebase of several tens of millions of loc [prolly hundreds of mill's as we don't see all of it] in java EE.
Very complex business logic where bells have their own whistles with their own bells with .... You get it.
Very fine-tuned performance to make app so performant that the only bottleneck becomes the db. The beefiest rds instance becomes too laggy [orm, so sqls are immutable]
Client moves to rewrite the whole thing in PHP. Motivation: lower TTM
When used properly No-SQL databases are an incredible resource but my employer keeps hammering them in problems which could better be solved by traditional SQL databases in an attempt to be more "hip" and "cool".
This causes huge PITA in making the database work properly with the ORM we're using and waste of time since we're force to emulate basic features which are already exists in almost any SQL database (i.e. relational integrity) using No-SQL storage.1
It probably will be an unanswered question, but let's try.
Does anyone know of a large project using onion / hexagonal/ ddd or similar architecture with free access to the source code...
Or an example of said architectures that goes beyond "trivial dumb example".
The new recruits need... A lot of brushing up (I'd be for electro shock treatment and other stuff, but somehow HR thinks I'm joking).
As said, most examples I found are too basic. On the other hand, if I write now a good example, I'd need to do it in either my free time (nope, just nope) or jiggle it in somewhere in company time (aka it will be never finished nor be in a useful state).
Anything would be helpful.
Most welcome would be an example with a focus on Adapter / Ports, e.g. abstraction of HTTP client usage / ORM etc.
Got a chance to work again on a Spring project after a few years of working with JavaSE.
All these horrible memories started rushing back. SpringJPA and its dark magic that only works unintuitively and under very certain conditions...
Ooooh boi. Now I remember. I remember it all.
Why do developers enjoy being squeezed into frameworks and enjoy spending half of a day figuring out how to make the application code compatible with the said framework rather than just writing code that they have full control over...? Masochists much?9
Fuck sequelize, the bloody query generated by the "ORM" give diferent result on the same DB if you trie it on dBeaver (works fine) vs node (shit results).
order DESC have 0 effect on sequelize, but it appears on the logger as part of the query.
I just want to go to sleep ffs.7
I'd like to learn go while building a web backend. but I'm not how should I start it. I mean, should I use any framework?
I'd like to use MongoDB, so a mongoose like ORM/library would be awesome8
SQLAlchemy is such a bloated piece of crap. Even without the fact that many consider ORMs an anti-pattern, this library is extremely janky, salty and uncomfortable to work with.7
Whenever I see an ORM that supports creating and transforming objects in bulk, I can't help but think about the poor misdirected users who forced it to do that. It's an Object-Relational Mapper. It maps objects. The whole concept isn't designed for bulk operations, the point is that you add logic to each and every record and convert your operations to SQL so that you never have to keep a lot of them in memory.4
I identified the need for a product akin to an ORM that maps an algebraic type system such as that of Rust to a key-value database (my situation dictates lmdb but I'd like to abstract away the store). Can you recommend prior art for me to research?4
How to deal with having to work on a very boring task?
I work as android dev in a company where there are around 40 of android devs in total. When I was working on frontend architecture and UI related tasks everything was perfect and I loved my job.
But now for the next couple months all of us have to work on migrating all of our db layer models and business logic related to them to a new built in house ORM library and its a total trainwreck.
Everyone is confused, the task is very boring and obscure and deadline is around 2 months. Just to clarify: one guy did 50% of migration and it took him couple years. Now they are throwing roughly 20 devs at the problem thinking they can do this in 1-2 months.
One week already passed and TBH I havent even started working on this, I just picked up a task and now Im trying to wrap my head around this. Its so boring and obscure and expectations are so unrealistic that I want to kill myself.. Thinking of just taking my 2 weeks vacation to escape this shit or even quitting my job if this goes on longer than a month or two.3