3 ms·
I'll make a stronger case to Keep it Simple: even if you have infinite computing resources and memory, implementing the simplest possible thing is far easier fo
by akkartik 12y ago
I'll make a stronger case to Keep it Simple: even if you have infinite computing resources and memory, implementing the simplest possible thing is far easier for other programmers to understand than the ugly generalized 'abstractions' most of us come up with 99% of the time. That 'cognitive bottleneck' will remain no matter how far back you push the resource bottleneck, and it will keep an anti-abstraction ethos competitive.
(Now, the Forth way isn't the one I would choose to be easy to understand: http://yosefk.com/blog/my-history-with-forth-stack-machines.html http://yosefk.com/blog/my-history-with-forth-stack-machines..... But that's a separate story..)
- eru 12y agoActually, if your language is designed right, abstractions become much cheaper, especially conceptually. As an example, I find a call to `map' or `filter' much easier to understand than a (C-style) `for' loop. Part of your point still stands: the `for' loop is harder to read and write specifically because it is more general. `for' loops can do all kinds of wacky things.
- akkartik 12y agoYeah. When I said 99% I wasn't just including what the language provides. That usually lies in the 1%, even for 'bad' languages. Generalization there is usually justified. No, I was thinking of the functions and interfaces we create atop the language and standard library.
- loup-vaillant 12y agoLanguage, standard library, or custom module boundaries, it's the same problem: there are 2 kinds of generality. The first kind is exhaustiveness. Being general by accounting for all special cases. That one is complicated, and rarely worth doing beforehand. The second kind is genericity. Being general by ignoring all the special cases. That one is often simpler and more solid than any special case. Parametric polymorphism (or generics, or templates) are like that: ignoring the specifics of the parameters limits what you can do with them, making the generic thing simpler. The layer at which you choose to apply exhaustiveness or genericity is irrelevant in my opinion. C++ often leans towards the exhaustiveness end of the spectrum despite being a language, for instance.
- akkartik 12y agoInteresting. My take was that language, standard library and third-party libraries are part of the same state space, just organized by the amount of use they receive. Since user-space libraries receive less hammering (many have just one user) they're usually still in the "adding exceptions" phase and haven't yet attained (and perhaps never will attain) the simplicity on the other side of complexity when the requirements stabilize. I think that maps to your distinction, except that I don't believe in 'exhaustiveness'. The state space of a program isn't some fixed thing for most programs. It evolves and grows in response to what we want it to do, which dimensions we choose to generalize along and where we stay stable. I think it's equally reasonable to view the evolution of special cases as equally exhaustive at every point, it's the boundaries of the state space (requirements) that is growing in strange ways.
- mhink 12y agoSo can calls to "map" and "filter", if your language allows side effects. Not that I'm trying to be all dogmatic about referential transparency- more like, without it, is there a large benefit to functional style vs. procedural style?
- eru 12y agoYou are right about side effects. From all I've heard people in impure languages have begun to embrace the notion of restricting side effects voluntarily.
- SomeCallMeTim 12y agoThe existence of poor designers isn't a good reason to never design. In fact, the more design you do, and the more you're exposed to, the better you can get at design. And the better the design, the easier it is to understand. An "ugly generalized abstraction" is pretty much by definition not a good abstraction. Moreover, a good abstraction is simple. It's easy to understand and it's easy to manipulate. [1] But you need to practice to get better, so it may take a few ugly monstrosities before you can start creating masterpieces. [1] Granted 99% of the code I've encountered in Java qualifies as ugly abstractions; Java's nature seems to encourage poor abstractions. Or attract poor developers. Or both. But even in Java it's possible to create beautiful and easy to understand abstractions.
- akkartik 12y agoOh man, that word 'design'. You have a problem and you think, "I should design a good solution." Now you have two problems. I was deliberately avoiding the d-word because it is vague enough that I'm not sure there's anything useful around there. The good designers are all good at designing within some domain. Jonathan Ivy, Christopher Alexander, Ralph Lauren, they all had their specialty. You wouldn't ask Ralph Lauren to design a rocket ship. Software is even wider a set of domains than meatspace. So I'm not sure you get better at design by 'practicing design'. That's just a set of vague words like 'simple', 'good', 'beautiful', 'abstraction', 'decoupled', 'coherent', 'cohesive', etc., etc. I think you get better at design by better understanding a domain. You get better at design by avoiding premature design.
- aidenn0 12y agoAbstractions that never leak are extremely rare. Because of this, trying to write a general purpose abstraction is very hard. A special purpose abstraction only needs to not leak for its intended purpose which is a lot easier to get right.
- lmm 12y agoI want more examples before I accept this Even the original "law of leaky abstractions" post did not have any good examples; using UDP rather than TCP will not save you if you pull out the network cable, and micro performance differences like the AND A = C example are rarely relevant.