4 ms·
> If you ever change your HTTP server Never needed to. Premature optimization. > We have the same issue with the database What issue?? Cross that bridge when
by pistoleer 2y ago
> If you ever change your HTTP server
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.
- lnxg33k1 2y agoIt is much easier to change applications that are designed properly, regardless of the premature optimization, using adapters and interfaces is costless, and give you priceless peace of mind
- pistoleer 2y agoIf only we could all finally agree on the definition of "proper design"!
- lnxg33k1 2y agoFor me, one that allows the application to be extended, maintained and understood easily
- sethammons 2y agoThe problem word, i think, is "extended." To me, that means adding functionality to the feature set, to others it may mean "changing the db" - and the two designs will be different.
- onli 2y agoSo as simple as possible, without unnecessary indirections and useless abstraction like interfaces that make reading the code hard, right? ;) There really are very different perspectives on what makes code easy to manage, and interfaces (especially ones used only for a single class) are a sure-fire way for me to make code unmanageable. But java enterprise coders disagree. That can clash hard.
- lnxg33k1 2y agoWhat is about interfaces that makes reading code hard? It is a contract, for me reading just a list of operations that are available without the concrete code, is even clearer/cleaner. Not sure java is bad for indirections, java is bad for boilerplate and lack of defaults, imho. But I usually don't use frameworks/stlib directly, so I create my own boilerplate that is reusable
- onli 2y agoIt's about the indirection. In the calling code, instead of knowing which specific object you are working with - and thus easily being able to check its implementation - you only know which interface it implements. Getting to the implementation can be very time consuming, especially in a system with hexagonal architecture or similar indirect patterns and dependency injection. While searching the code you then lose the context of the problem you were working on. So I'm not talking about having one or two sensible interfaces as a contract, but codebases where every class has at least one interface, for "decoupling". Pure hell.
- solidninja 2y agoIn my experience, using tools that do not support the "Go To Implementation" shortcut makes it hard. In IntelliJ, Ctrl+Shift+Click will take you to the possible implementors of an interface. Concrete example from work today - we have a trading application and there are many paths that lead to alerts of some kind. Alerts are usually raised inline with any business logic (as should be - they intrinsically coupled). Alerts however can be delivered differently - via SMS, other messaging systems and/or log messages. The different places where the alerts need to be generated do not _need_ to know how the alert is going to be physically delivered to its destination - they just need to generate it. Without an interface (or at least a type alias for a function) - it would make being able to say e.g. this alert is a direct phone message vs. a chat message in some channel because of the type it is - much harder.
- choeger 2y ago> using adapters and interfaces is costless, Hah, no, they're not. Every production app is read many, many times by several different developers, mostly to search for bugs. Reading across adapters, services, and interfaces make that much harder. Especially, if the architectural pattern was implemented slightly differently every time by various authors. Abstraction always comes with a price. Often, it is well worth to pay (or we would still code everything in C or assembly), but sometimes it's just a waste.
- solidninja 2y agoI'm always fascinated by the amount of comments that devalue separating concerns and reducing coupling by using traits and modules. Maybe if you're exclusively writing serverless functions you don't need much code anyway, but the idea that you can go and read a piece of code that deals with the database separately from a piece of code that deals with your HTTP request encoding (and see how they meet in the middle via a few method signatures) is a pretty powerful one in my experience.
- FridgeSeal 2y agoI don't think anyone here is seriously suggesting that separating IO and concerns is bad. I think people here are devaluing the "kind of approach" taken in these over-abstracted-architectures. The snippets of "improved" code in TFA have a lot of new line-noise, a lot of boilerplate and half-a-dozen "new" pieces of terminology, all in the quest to essentially separate IO and core logic. There's plenty of ways to perform this separation, many of them don't require replicating half the design-patterns from C# tutorial. I'm pretty partial to "functional-core, imperative-shell", I think that it achieves all the same advantages, with none of the new concepts, and far less line noise.
- globular-toast 2y agoThanks for providing an example of how to do the separation in a better way! Many of the other comments are just saying "this is stupid" because they've never built anything big enough to see why domain driven design exists. Abstract classes etc are just a means to an end, they are not the goal. Dependency inversion is the goal. It's good to know there are ways to do it in Rust.
- pjmlp 2y agoWhile I agree with the idea, they certainly have a development cost in complexity.