News for hackers. Stuff that matters.
Re:Small functions considered harmful by agentultra on Friday August 11, 2017 @10:07AM (#14989762)
It seems like the author's idea of the term abstraction is limited to substituting procedures with functions (or worse, class methods). The claims that "all abstractions leak" and that adherence to DRY makes code "hard to follow" is what gives me this impression. This line of thinking happens if you think of code in procedural terms.

And if your sense of abstraction is to hide procedural side-effects behind function applications then yes... I can see where you might get the idea.

A real abstraction like lambda doesn't leak. Using Monads to compose side effects doesn't leak. These are mathematical abstractions and we use them all of the time: even in programming and even if you don't identify as someone who's any good at maths. Learning the lambda calculus, algebra, and first-order logic will take you much farther than thinking in procedural steps.

Composing more interesting functions from smaller ones removes so many errors that procedural code has: removal of superfluous bindings, a more declarative style, and it makes code more more easy to reason about during refactoring: using familiar tools from mathematics we can manipulate expressions and types. This is where abstractions really shine: you can manipulate higher-level expressions without caring about the details of those at the lower level. This only really happens if you care about purity in languages that don't do it for you and can reason using such tools.

Re:Small functions considered harmful by jerf on Friday August 11, 2017 @10:17AM (#14989858)
Arguably lambda, monad, etc. are generalizations, not abstractions: http://www.emu.edu.tr/aelci/Courses/D-318/D-318-Files/plbook...

Abstractions that don't leak aren't abstractions, as the essense of abstraction is the simplification and removal of detail. Monad is a generalization of a pattern seen in many places, so it doesn't have to "leak".

Re:Small functions considered harmful by agentultra on Friday August 11, 2017 @11:20AM (#14990545)
I don't think I'd argue with that.

To take the idea to its conclusion is that one can build abstractions on these building blocks. It's typical for software I write to be built up from small functions. The abstractions happen as higher-order functions build up to the domain level language until the implementation meets its specification.

A rather well-defined abstraction I admire is the OSI model [0]. A software system that emulates this model, built from solid generalizations like lambda and higher-order functions tend to be quite strong in the sense that reasoning about them can be done in isolation from layers below or above.

Procedural code, if not well contained and isolated, easily loses this ability and requires the programmer to enumerate the decision tables in their head and all of the possible effects that could be caused by different inputs... such a waste of time. I've been there, done that. Not for me. I like small functions as long as I have ways of composition by means of higher-order functions.

Re:Small functions considered harmful by taeric on Friday August 11, 2017 @10:22AM (#14989910)
I call shenanigans. Lambdas can easily lead to leaking call backs as your implementation.

Similarly, monadic style can leak if you are sloppy with it. Just see coffee in Haskel where the IO Monday has infected the entire codebase, and not just a boundary.

Re:Small functions considered harmful by ronjouch on Friday August 11, 2017 @02:04PM (#14992609)
Fun autocorrect barf: monad <- Monday. That being said, I hate IO Mondays too, they're the worst to start the week.
Re:Small functions considered harmful by emn13 on Friday August 11, 2017 @11:09AM (#14990426)
I kind of agree with you (I think), but I'd present (or think) about it differently to avoid terminological squabbling.

More specifically: I'm skeptical of the distinction that your referenced article attempts to introduce between generalizations and abstractions: that distinction feels after the fact, trying to retconn into existence some classification that just isn't that clearcut. Regardless of what's correct terminology here, emphasizing the distinction simply leads to semantic quibbling, not better programming practices. The criticism that "abstractions always leak" might apply equally to generalizations - or encapsulations. Whatever you're going to call it; the idea at some level is that you're never entirely free of implementation details.

To be clear: I agree the words may well have different connotations and even different meanings, but that does not imply that they are mutually exclusive: what's an abstraction from one angle may well be an encapsulation viewed from another, and a generalization in some other context. And perhaps some aspects of a given construct aren't relevant when you consider it to be an abstraction rather than a generalization; but I'm not sure it matters here.

Instead, I think it should be emphasized the there are two different ways of looking at the statement that "all abstractions leak":

- You can consider that any abstraction in an executing program is merely a way of thinking about something that's ultimately a real physical process; and that that physical process may well have relevant behavior that escapes the confines of your abstraction. For example, the abstraction that your mergesort is O(N log N) is in some sense leaky because more memory needs longer wires means slower access so it's false - in some sense.

- You can consider clearly self-consistent and completely rigorous mathematical concepts that might be used as abstractions as a kind of counterexample. Clearly, there are thus abstractions that do not leak. Mergesort is O(N log N) - not in physical time, but in # of operations. We sort of "define" the problem not to exist.

Frankly: I don't think the "physical process" view (while certainly valid!) holds much value beyond that of a cautionary tale. Rather than give up and say "it's impossible" the lesson should be that it's valuable to choose your goalposts. So, for instance: if you define a correct program that adds N numbers to be one that returns (say) the true sum in at most N milliseconds, you're going to run into trouble: you may not be able to guarantee you won't be swapped out; you may run into trouble if your numbers are absurdly large; and you can't rule out that asteroid impact that's about to destroy the computer. But you can carefully choose those goalposts such that if the program completes, and if (condition XYZ) then it returns the numerical sum.

Does that distinction seem pointless? I don't think so; because as it turns out in the real, physical process world this allows us to separate responsibilities. It's fairly easy to ensure a physical environment that will high likelihood (albeit not fully 100%) satisfy the requirements you pose. And by separating responsibilities like that, it becomes easier to avoid needlessly leaky abstractions, and those abound too. In short: you may not be able to make an abstractions that's reliably perfect, but you should be able to make abstractions that given certain preconditions are perfect. And that matters because it's easy to compose perfect abstractions, and it's not even hard to keep most of the complexity in the perfect and leak-free world.

In short: "all abstractions leak" is thoughtcrime that can all too easily hide lazily constructed, poorly chosen abstractions that don't compose well :-).

I prefer to think that it's inevitable that some abstractions leak, but if you're clever (and perhaps a little lucky) you can contain the leakiness such that other abstractions are leak-free. And if you want, call those latter abstractions: generalizations. But programming can choose to be almost all about those generalizations, not the leaky abstractions.

Re:Small functions considered harmful by agentultra on Friday August 11, 2017 @11:28AM (#14990635)
Thank you for posting this.

We see this a fair bit in formal methods of software construction. I can write a specification that proves that given a precondition a particular state will eventually result in a consequent state. The model is mathematically sound but it doesn't state when that transition will occur or how long it will take. And for the purposes of the specification it is likely not important!

The level of detail that is important should be deliberately chosen. A specification of a distributed system can choose to abstract away the details of the TCP protocol while still proving that the properties we do care about, consistency perhaps, are maintained.

Re:Small functions considered harmful by copyconstruct on Friday August 11, 2017 @04:36PM (#14993963)
Author here.

> "The claims that "all abstractions leak" and that adherence to DRY makes code "hard to follow" is what gives me this impression."

That's a simplistic -- and cherry-picked -- interpretation of my post, I'm afraid. DRY inherently doesn't make code harder to follow, but an explosion of ultra-small functions (sometimes done in the name of DRY) as advocated for by Fowler and Martin and their ilk most certainly makes the code a lot harder to read.

I'm afraid I'm not against abstractions either - I'm only questioning whether the bottom up form of thinking we generally tend to use is the best mental model around and whether it's doing us a disservice.

Re:Small functions considered harmful by marcosdumay on Friday August 11, 2017 @12:44PM (#14991698)
Abstract abstractions, that simplify things that aren't real don't leak when you design them well. Concrete abstractions, that simplify things you didn't create do always leak.

Only the second type is essential for programming, and many people do use only them.