by milliams on 9/12/24, 8:23 AM with 109 comments
by Avi-D-coder on 9/17/24, 8:25 AM
Attempting these design patterns is a common part of getting over OOP when new to Rust. The result: over-abstracted, verbose, unmaintainable C++/Java written as Rust. Every layer of indirection ossifies the underlying concrete implementations. The abstractions inevitably leak, and project velocity declines.
I have seen the same types and logic literally copied into three different repositories in the name of separation of concerns.
Luckily people usually get over this phase of their Rust career after a couple of failures.
If you’d like to skip that part, here are a few rules:
1. Always start with concrete types. Don’t abstract until you have at least two, preferably three, concrete implementations.
2. Separation of concerns is a myth.
3. K.I.S.S.
by attheicearcade on 9/17/24, 7:48 AM
At $work we’re slowly ripping out a similar system in favour of handlers calling database functions directly, such that they can put transactions in the right place across more complicated sets of queries. Code is simpler, data integrity is better.
by phamilton on 9/17/24, 5:52 AM
I'm all for the unit testing argument, but in an active SaaS business I've never seen the hypothetical database change where a well architected app makes it smooth. I have certainly moved databases before, but the performance and semantics changes dwarf the call sites that need updating. Especially in Rust, where refactoring is quite straightforward due to the type system.
by FridgeSeal on 9/17/24, 8:02 AM
Mixed feelings about this.
“Oh our http handler knows about the db”
Ok? Its job here is more or less “be a conduit to the db with some extra logic”.
It “knows about a lot of things” but it’s also exceedingly clear what’s going on.
The main function is fine. I’ll take a “fat” main function over something that obscures what it’s actually doing behind a dozen layers of “abstraction”. Nothing like trying to isolate a component when you’re fighting an outage and nobody can figure out which of the 16 abstract-adapters or service-abstracted launched the misbehaving task.
The original code might be “messy” but it’s at least _obvious_ what it’s doing, and it can pretty clearly be pulled apart into separate logic and IO components when we need to.
This all just feels a bit…over engineered, to say nothing of the insulting tone towards the other learning resource.
by dvt on 9/17/24, 6:01 AM
by seanhunter on 9/17/24, 3:18 PM
Tell me the thing that's in the headline first. I'm not going to read your article if you don't do this. It's not that I'm not intellectually curious, it's that I don't like being messed around.
by pistoleer on 9/17/24, 7:42 AM
Never needed to. Premature optimization.
> We have the same issue with the database
What issue?? Cross that bridge when you get to it...
> To change your database client – not even to change the kind of database, just the code that calls it – you'd have to rip out this hard dependency from every corner of your application.
I really doubt this is such a big deal... Bit of ctrl+f for that module and paste the new one. All database libraries have a "connect()" and a "query()".
I'm so far convinced that this article is written for people who have too much time to waste on things that will probably never happen just so they get to feel smart and good about something that's not even visible.
Imagine if we built bridges this way: yes, right now we have settled on a stone masonry design, but what if we want to move to steel trusses in the future???
Why can software engineers not accept that it is unreasonable to expect one single human creation to last forever and be amendable to all of our future needs? Cross the bridge when you get to it. Don't try to solve future problems if you're not 100% certain you're going to have them. And if you _are_ certain, just do it right the first time, rather than leaving an opening for a future person to "easily" fix it up. And sometimes? A new bridge has to be built and the old one torn down.
by SPascareli13 on 9/17/24, 4:28 PM
Now he's not here anymore, and posts in his linkedin about simplicity and how people overcomplicate things in software so much. This shows me that you should be careful when taking advice from other engineers, they learn and move on from what was previously a "best practice", while you might get stuck thinking it's worthy it because "that one very good engineer said it was how it should be done".
by pantulis on 9/17/24, 8:44 AM
by John23832 on 9/17/24, 2:54 PM
If you want to test, test at the integration layer using testcontainers[0] or something. Not everything has to resemble a Spring style dependency injection/inversion of control.
by 33a on 9/17/24, 3:39 PM
by belval on 9/17/24, 7:49 PM
by agubelu on 9/17/24, 9:28 PM
Hell is full of single-implementation abstractions.
by Kostarrr on 9/17/24, 5:40 AM
Total nitpick: For `CreateAuthorError::Duplicate`, I would return a 409 Conflict, not a 422 Unprocessable Entity. When I see a 422 I think utf-8 encoding error or maybe some bad json, not a duplicate key in a database.
by Kinrany on 9/17/24, 8:20 AM
The two main use cases are routing frameworks and tests.
Axum already has this, but it is married to HTTP a bit too much.
by keyle on 9/17/24, 5:39 AM
Hexagonal architecture brings order to chaos and flexibility to fragile programs by making it easy to create modular applications where connections to the outside world always adhere to the most important API of all: your business domain.
okay.by resonious on 9/17/24, 9:46 AM
And what's the point again? To make it so that you can switch out Postgres for MongoDB later? To make your web app now accessible over XMPP? It feels like a lot of work to enable changes that just don't happen very often. And if you wrote your app with Postgres, the data access patterns will not look very idiomatic in Mongo.
I think X11 in *nix land is an interesting example of what I mean. X11's client-server architecture allows a window to be "powered" by a remote machine as well as local. But it's dog slow. Straight up streaming the entire desktop frame by frame over VNC is usually smoother than using X11 over the network. I think we just haven't reached a point yet where we can develop good apps without thinking about the database or the delivery mechanism. (I know X11 isn't exactly new, but even with decades of advancements in hardware, X11 over the internet still loses to VNC)
by hi-v-rocknroll on 9/17/24, 6:14 AM
by atemerev on 9/17/24, 9:03 AM
by anacrolix on 9/17/24, 11:26 AM