4 ms·
The question becomes: when does hiding complexity improve your ability to reason about the code? When you trust the abstraction. For example, on the whole we t
by DougBTX 17y ago
The question becomes: when does hiding complexity improve your ability to reason about the code?
When you trust the abstraction. For example, on the whole we trust the filesystem abstraction, we rarley try to inspect the phisical location of the bits on the disk - the filename is sufficient, we can treat the fielsystem as a black box.
On the other hand, if you don't trust the code, you're going to want to read every line, and that's easier to do if all the code is in one method. An abstraction is a liability if you can't trust it.
Re testing: it's easier to trust a well tested function, so splitting up code to make it easier to test, and then testing it, will allow you to ignore it's implementation. Suddenly it isn't logic spread across six classes, but one class using some utility methods.
- chousuke 17y agoWhat kind of abstractions are the most trustworthy? In my experience, the ultimate in abstraction is anything that works solely with immutable data. This includes, obviously, pure functions, but also objects which have no mutable state. Such things are trivial to test and perfectly composable. It's easier to gain trust in them as you rarely need to know exactly what they do, only whether they appear to work or not. Obviously immutability alone is not enough for many abstractions, but I would still like to see it used more. The current object-oriented models seem to encourage encapsulating state, rather than encapsulating data, which seems to lead programmers to use mutable things even when they are unnecessary. Unless the abstraction requires it (eg. IO), I think any state held within an object is, in a way, leaky abstraction. As long as there is state within an object, it is not obvious whether you can, at any one time: 1) call its methods 2) hold a reference to it 3) delete it, or your reference to it (Mostly applies to non-GC languages) 4) Pass it as a parameter to something All these worries disappear with immutable values.
- wisty 17y agoPure functions have one problem - they don't have state, and sometimes you need state. What's needed is pure functions for logic, and dumb objects holding data, and function pointers.
- elblanco 17y ago> When you trust the abstraction I agree. I would also say that in cases where the abstraction doesn't make sense you have to know what's going on inside the box in order to trust it. In your example, the file system as an abstraction makes sense because once you understand that it's a tree, you are pretty much good to go. I remember working on some projects early in my career with a very senior developer who had a habit of making the strangest abstractions possible on a problem. For example, need to use a class to define a triangle? His constructor might take 7 arguments! The center of the triangle on the screen, and the distance from the center as well as the degrees of rotation from the center (with the bottom of the screen being 0 degrees). Oh, and actually, it didn't take 7 arguments, it took 4, but three were some special object type containing a tuple of radians plus a mishmash of other parameters and a coordinate on screen. Because he wanted to, you know, reuse that code again. So in order to build a triangle, I had to define a center point on screen (with 0,0 in the middle of course because that's how his code worked) and then calculate the coordinates of the three triangle points from the distance I wanted, then convert degrees into radians or some such....bah! I don't remember all of the details, this was a long time ago, but it was horribly obfuscated and made no intuitive sense. He explained that it was all to avoid some singular edge case that he had encountered once, and he thought it was a good trade-off because all of the new edge-cases it introduced were manageable. When I received this code (without documentation or useful comments), he was on vacation for two weeks. Naively, I assumed it was an easily understandable abstraction in that I could simply supply 3 coordinates in some order to the library and get a triangle. I spent a couple days trying to figure out the order I was supposed to issue the coordinates to get it to draw before giving up and just reading the code to figure it out. Worse yet, the internals were abstracted all to hell in a similar obfuscated fashion and I literally got nowhere in trying to figure it out. I actually just waited for him to get back to walk me through the code, peppering him with question like "do we really need to define the z coordinate as 0 all the time since the display is always 2d?" before proceeding on that work. Once I understood it, I just wrote some wrapper code to translate three normal 2d coordinates into his craziness to simplify my life. I ran into this kind of thing with his abstractions all the time. From the most insane string class you have ever seen to a home rolled virtual memory library that pickled objects onto disk, but all of your objects had to be built around a base class that was full of useless virtual functions that you had to implement.