3 ms·
> Not only are the components doing things their own ways, they’re trying to hide what they’re doing as “implementation details”. The fact that a database query
by TravHatesMe 7y ago
> Not only are the components doing things their own ways, they’re trying to hide what they’re doing as “implementation details”. The fact that a database query requires a database connection never was an implementation detail.
In my opinion this is an implementation detail. A service exposes an interface for CRUD-type operations. The implementation could be any kind of datasource, whether it be a database, RESTful API, filesystem, or mocked data in-memory. Did the author imply that the consumer should be choosing the data source? What about caching? That might be an implementation detail as well -- is it a remote managed cache, a file-persisted cache, or in-memory? what about expiry/invalidation?
This might introduce additional accidental complexity but in my experience building an OOP system correctly has its benefits. An honest question: can FP solve this in a cleaner fashion, with less accidental complexity?
- js8 7y ago> An honest question: can FP solve this in a cleaner fashion, with less accidental complexity? I think the answer is yes, here's my earlier comment which I think is relevant: https://news.ycombinator.com/item?id=18661931 https://news.ycombinator.com/item?id=18661931
- dnautics 7y agoYes. I currently have an FP system where in dev and test the interface kicks to an in memory multi state machine, and in lab and prod it goes to libvirt (which has costly network transactions) the modules implements the same API, and are swapped out at compile time.... It gets even better, in test the implementation partitions over checked out sessions so that acceptance tests can be concurrent with each test having its own view of the universe in spite of having a single state agent.
- lazulicurio 7y agoYou might not care about the implementation for a single call that only hits the happy path, but as soon as you are making more than one call or having to deal with failures the implementation definitely matters. And I think that FP makes it easier to build composable abstractions on top of the underlying code. While in theory composability and encapsulation are orthogonal concerns when using OOP, in practice (for at least Java and C#) I find that there's often tension between the two.
- vvanders 7y agoPerformance/memory is the ultimate leaky abstraction. Once you also lay out perf as a requirement in your abstractions it can really help mitigate these types of problems.
- skybrian 7y agoI'm curious, how do you do that? I don't know of any languages the cover performance in their abstractions, only informally via documentation.
- vvanders 7y agoVHDL/Verilog does but you're not going to write many apps in that. At a high level: 1. Brute force with automated tests. Great if you have known datasets and platforms. 2. Work from most constrained hardware first. Easy to say, hard to do. Back in the X360/PS3 days almost everyone screwed this up and developed for X360 first. 3. If you need to do N of the same things fast, use an contiguous array. If you want to enforce that make the array part of your API. CPU prefetchers are amazing and love predictable memory patterns. 4. Rust is one of the few languages that bakes semantics into the language that line up well with modern architectures. Specifically Rust can automatically apply restrict semantics. It also forces you to think about ownership upfront in a way that tends to be performance friendly.
- skybrian 7y agoYes, these are all good performance tips, but you're still testing the system as a whole. Performance leaks across the abstractions.
- marcosdumay 7y agoAs a rule, FP is great for separating concerns in independent code. So you can have a great data-access layer, and a completely abstract data layer that doesn't care about the access layer at all. OOP systems nominally do that separation too, but FP usually makes those layers clearer and more independent. A reduction in total complexity is another, completely unrelated thing. I honestly do not see accidental complexity on your description. Any system will have to deal with all that stuff, OOP and FP will just do it in different parts of the code.