[HN Gopher] The Law of Leaky Abstractions (2002)
       ___________________________________________________________________
        
       The Law of Leaky Abstractions (2002)
        
       Author : skm
       Score  : 68 points
       Date   : 2024-03-06 19:47 UTC (3 hours ago)
        
 (HTM) web link (www.joelonsoftware.com)
 (TXT) w3m dump (www.joelonsoftware.com)
        
       | Bostonian wrote:
       | Should have (2002) in title.
        
       | simonw wrote:
       | I love this essay so much. I read it 22 years ago and it's been
       | stuck in my mind ever since: it taught me that any time you take
       | on a new abstraction that you don't understand, you're
       | effectively taking on mental debt that is likely to come due at
       | some point in the future.
       | 
       | This has made me quite a bit more cautious about the abstractions
       | I take on: I don't have to understand them fully when I start
       | using them, but I do need to feel moderately confident that I
       | could understand them in depth if I needed to.
       | 
       | And now I'm working with LLMs, the most opaque abstraction of
       | them all!
        
         | Legend2440 wrote:
         | >And now I'm working with LLMs, the most opaque abstraction of
         | them all!
         | 
         | You put a black box around it to fit it into the world of
         | abstractions that traditional programs live in.
         | 
         | But I'd say the most interesting thing about neural networks is
         | that they do not have any abstractions within them. They're
         | programs, but programs created by an optimization algorithm
         | just turning knobs to minimize the loss.
         | 
         | This creates very different kinds of programs - large, data-
         | driven programs that can integrate huge amounts of information
         | into their construction. It's a whole new domain with very
         | different properties than traditional software built out of
         | stacked abstractions.
        
       | avgcorrection wrote:
       | > Back to TCP. Earlier for the sake of simplicity I told a little
       | fib, and some of you have steam coming out of your ears by now
       | because this fib is driving you crazy. I said that TCP guarantees
       | that your message will arrive. It doesn't, actually. If your pet
       | snake has chewed through the network cable leading to your
       | computer, and no IP packets can get through, then TCP can't do
       | anything about it and your message doesn't arrive.
       | 
       | The argument is disqualified at this point. The whole world is a
       | leaky abstraction because <freak meteor hit could happen>. At
       | this point your concept is all-encompassing and in turn useless.
       | 
       | There are assumptions: this computation will finish eventually
       | [assuming that no one unplugs the computer itself]. This does not
       | make things leaky.
       | 
       | There are leaky abstractions I guess but not all are. A garbage
       | collector that can cause memory errors would be leaky. I don't
       | know anything about garbage colletors but in my experience they
       | don't.
       | 
       | Then someone says that a garbage collector is leaky because of
       | performance concerns (throughput or latency). That's not a leak:
       | that's part of the _abstracting away_ part--some concerns are
       | _abstracted away_. To abstract away means to make it something
       | that you can't fudge or change. To say that "this is
       | implementation-defined". An abstract _list_ is an abstraction in
       | the sense that it has some behavior. And also in the sense that
       | it doesn't say _how_ those behaviors are implemented. That's both
       | a freedom and a lurking problem (sometimes). Big reallocation
       | because of amortized _push_? Well you abstracted that away so can
       | you complain about it? Maybe your next step is to move beyond the
       | abstraction and into the more concrete.
       | 
       | What are abstractions without something to abstract away? They
       | are impossible. You have to have the freedom to leave some things
       | blank.
       | 
       | So what Spolsky is effectively saying is that abstractions are
       | abstractions. That looks more like a rhetorical device than a new
       | argument. (Taxes are theft?)
       | 
       | EDIT: Flagged for an opinion? Very well.
        
         | mjw_byrne wrote:
         | I tend to agree. "All nontrivial abstractions are leaky"
         | reminds me of other slightly-too-cute rules, such as "full
         | rewrites are a mistake" and "never parse JSON manually".
         | 
         | I wouldn't call TCP leaky because it can't deliver data across
         | a broken network cable, for example. It's abstracting away
         | certain unreliable features of the network, like out of order
         | delivery of packets. It's not abstracting away the fact that
         | networking requires a network.
        
         | bxparks wrote:
         | I unflagged you by vouching for you. I found your post
         | difficult to understand and couldn't figure out what you are
         | trying to say, but I agree it was not deserving of a flag.
        
           | avgcorrection wrote:
           | What was difficult about what I wrote?
        
         | lpapez wrote:
         | I don't agree with your opinion, but I see how it can be seen
         | as being perfectly reasonable and there really is no need to
         | flag you (unflagged).
        
         | joeyjojo wrote:
         | I suppose it should be considered where the abstraction
         | actually exists. If the abstraction exists in logic or
         | mathematics (ie. a triangle is a 3 sided polygon) it probably
         | doesn't make much sense to consider the ramifications that
         | thought occurs in a physical brain that can fail. On the other
         | hand if the abstraction is physical (ie, hardware), then the
         | fact that it is bound by physical law is obviously implicit.
         | Software encompasses both physical and logical abstractions, so
         | you need to pick a lens or perspective in order to actually
         | view its abstractions.
        
         | samatman wrote:
         | > _There are leaky abstractions I guess but not all are. A
         | garbage collector that can cause memory errors would be leaky.
         | I don't know anything about garbage collectors but in my
         | experience they don't._
         | 
         | Garbage collectors are a rich source of abstraction leaks,
         | depending on what you do with the runtime. If you color within
         | the lines, no surprises, the garbage collector will work.
         | Unless it has a bug, and hundreds of GC bugs, if not thousands,
         | have shipped over the decades; but while a bug is an
         | abstraction leak, it's not a very interesting one.
         | 
         | But go ahead and use the FFI and things aren't so rosy. Usually
         | the GC can cooperate with allocated memory from the other side
         | of the FFI, but this requires care and attention to detail, or
         | you get memory bugs, and just like that, you're manually
         | managing memory in a garbage collected language, and you can
         | segfault on a use-after-free just like a Real Programmer. It's
         | also quite plausible to write a program in a GC language which
         | leaks memory, by accidentally retaining a reference to
         | something which you thought you'd deleted the last reference
         | to. Whether or not you consider this an abstraction leak
         | depends on how you think of the GC abstraction: if you take the
         | high-level approach that "a GC means you don't have to manage
         | memory" (this is frequently touted as the benefit of garbage
         | collection), sooner or later a space leak is going to bite you.
         | 
         | Then there are finalizers. If there's one thing which really
         | punctures a hole in the GC abstraction, it's finalizers.
        
       | evanmoran wrote:
       | If you like this, my other favorite essay by Joel is Making Wrong
       | Code Look Wrong:
       | 
       | https://www.joelonsoftware.com/2005/05/11/making-wrong-code-...
        
         | o11c wrote:
         | The problem is that it completely ignores the correct solution,
         | which is "use types; we invented them for a reason".
         | 
         | HTML fragments should _never_ be stored in strings.
        
           | mason55 wrote:
           | One problem is that there's a major lack of language support
           | to make this easy.
           | 
           | IMO, every ID should be its own type. You shouldn't have a
           | bunch of objects that have an ID of type string, you should
           | have a User object with an ID of type UserID and a Post
           | object with ID of type PostID, and then the compiler solves a
           | lot of problems for you. Or make it so your functions that
           | interact with the outside world accept a String, but they
           | only return ValidatedStrings, and your internals only accept
           | ValidatedStrings (and there's only one way to turn a String
           | into a ValidatedString).
           | 
           | But in any kind of language with structural typing (e.g.
           | TypeScript) this doesn't work, by definition. You can call a
           | string a UserID and you can call it a PostID but if they're
           | both Strings then you can assign them to each other.
           | 
           | And in Java, the concept of a typedef-like operation doesn't
           | exist at all (I can't speak for .Net).
           | 
           | There's a whole class of bugs that go away if you allow for
           | easy, nominal typedefs, but it's actually not easy to do in
           | most statically typed languages.
        
       | mjw1007 wrote:
       | I never liked the way he used TCP as an example here.
       | 
       | I don't think it's sensible to think of "make it reliable" as a
       | process of abstraction or simplification (it's obviously not
       | possible to build a reliable connection on top of IP if by
       | "reliable" you mean "will never fail"). "You might have to cope
       | with a TCP connection failing" doesn't seem to be the same sort
       | of thing as his other examples of leaky abstractions.
       | 
       | TCP's abstraction is more like "I'll either give you a reliable
       | connection or a clean error". And that one certainly does leak.
       | He could have talked about how the checksum might fail to be
       | sufficient, or how sometimes you have to care about packet
       | boundaries, or how sometimes it might run incredibly slowly
       | without actually failing.
        
         | joe_the_user wrote:
         | Indeed, his discussion seems to involve a confusing of a leaky
         | network protocol and a leaky abstraction. Perhaps he wanted to
         | meta-illustrate his concept by having his discussion itself be
         | leaky.
        
         | lcuff wrote:
         | I like the idea of TCP as a leaky abstraction because it points
         | out the difficulty of engineering the abstraction we really
         | want. It would be wonderful for TCP to be a guaranteed
         | connection abstraction, but it turns out in today's world, the
         | abstraction of a reliable connection is TCP + a network
         | administrator + a guy with wire snips + solder
         | (metaphorically). Maybe down the road, AIs and repair bots will
         | be involved, and the guaranteed connection abstraction might
         | become real or much much stronger. Although it gets more
         | complicated because if a message takes hours to deliver, is
         | that going to work for your application? Yes if you're
         | archiving documents, no if you're trying to set up a video
         | conference call or display a web page.
         | 
         | TCP is problematic in modern circumstances (think: Inside a
         | data center) because a response within milliseconds is what's
         | expected to make the process viable. TCP was designed to
         | accommodate some element of the path being a 300 Baud modem,
         | where a response time in seconds is possible as the modem dials
         | the next hop, so the TCP timeouts are unuseable. QUIC was
         | developed to address this kind of problem. My point being, the
         | abstraction of a guaranteed _timely_ connection is even harder.
         | 
         | I think Joel could have expanded his thoughts to include the
         | degree of leak. SQL is a leaky abstraction itself, yes, but my
         | own take is that ORMs are much leakier: Every ORM introduction
         | document I've read explains the notation by saying "here's the
         | sql that is produced". I think of ORMs as not a bucket with
         | holes, but a bucket with half the bottom removed.
        
           | anonymous-panda wrote:
           | > but it turns out in today's world, the abstraction of a
           | reliable connection is TCP + a network administrator + a guy
           | with wire snips + solder (metaphorically).
           | 
           | I think you've misunderstood the abstraction. In fact, TCP is
           | not leaky because there's wire snips or cable cuts. In fact,
           | BGP will route around physical failures. But aside from that,
           | it abstracts all the various failure modes as a single
           | disconnection error. A leaky abstraction would be when you
           | need to still distinguish the error type and TCP wouldn't let
           | you. A 100% reliable connection is physically impossible in
           | any context (and an intrinsic concept of distributed systems
           | which every abstraction is leaky over including the CPU bus)
           | so if that's your bar then all tech will be a leaky
           | abstraction. It is at some level but not in a way that's
           | helpful to have a fruitful discussion.
        
       | BoiledCabbage wrote:
       | Young people should probably know that (as far as I recall) Joel
       | more or less invented tech blogging as a form of
       | advertising/recruiting for your company.
       | 
       | Namely either listing out the process/perks that a good
       | engineering team should have and how conveniently his company has
       | it. Or describing interesting and challenging problems they
       | solved and how you can join them and solve problems like that
       | too.
       | 
       | I don't recall anyone popular doing it before him and it's pretty
       | much industry standard now. (Although, feel free to chime in if
       | that's wrong. But popular being a key word here),
        
       | williamcotton wrote:
       | Cannot everyone get the sense that how we currently build
       | software is one gigantic leaky abstraction?
        
         | Legend2440 wrote:
         | Worse; it's a stack of abstractions on top of abstractions on
         | top of abstractions. You're at least 10 layers away from the
         | hardware, possibly more.
        
           | williamcotton wrote:
           | I don't necessarily see that as the problem. Assembly is a
           | great abstraction over machine code. Languages that compile
           | to these bytecodes are a good abstraction. Garbage collected
           | languages are a good abstraction.
           | 
           | Web applications are not a good abstraction. Auth, storage,
           | route handlers, tests, deployment, et al, are all cobbled
           | together like chocolate ice cream and jalapenos on an
           | uncooked bed of salmon and root beer.
        
         | Veserv wrote:
         | Every abstraction leaks. A good abstraction for your domain is
         | stable in your domain and only leaks outside of your domain. A
         | great abstraction is separable allowing you to only drop down
         | the abstraction level where needed and allowing the rest of the
         | code to continue using the abstraction where the leaks do not
         | matter, and layered allowing you to only drop down as much as
         | needed and making it easy to rebuild parts of the upper layers
         | on a new foundation.
        
       | highfrequency wrote:
       | > "All abstractions leak, and the only way to deal with the leaks
       | competently is to learn about how the abstractions work and what
       | they are abstracting. So the abstractions save us time working,
       | but they don't save us time learning."
       | 
       | Very nicely worded. But I would also add that:
       | 
       | 1. An abstraction can often be manned by one person, so when it
       | leaks only one person needs to understand it deeply enough to fix
       | it.
       | 
       | 2. The article seems to miss the _iterative_ nature of
       | abstractions. Over time, the goal is to iterate on the
       | abstraction so that it exposes more of the stuff that matters,
       | and less of the stuff that doesn't matter. Perhaps all
       | abstractions leak, but some leak way less often and save much
       | more thinking in the meantime than others. Rather than lamenting
       | the nature of abstractions we should focus effort on making them
       | as practically useful as possible.
        
       | glial wrote:
       | This is well-written. I might suggest that what makes pure
       | mathematics special is that abstractions in pure math are not
       | leaky, unlike in (nearly?) every other domain.
        
         | mturmon wrote:
         | Didn't downvote, don't entirely disagree, but maybe it would be
         | OK to say that the leaks can be made more apparent:
         | 
         | "The integral reverses the derivative" + ++ *
         | 
         | + Up to an arbitrary additive constant
         | 
         | ++ Provided the derivative exists
         | 
         | * And we hope you don't have concerns about the existence of
         | the real numbers
        
       | an1sotropy wrote:
       | I first learned about "leaky abstractions" from John Cook, who
       | describes* IEEE 754 floats as a leaky abstraction of the reals. I
       | think this is a good way of appreciating floating point for the
       | large group of people who's experience is somewhere between
       | numerical computing experts (who look at every arithmetic
       | operation through the lens of numerical precision) and total
       | beginners (who haven't yet recognized that there can't be a one-
       | to-one correspondence between a point on the real number line and
       | a "float").
       | 
       | * https://www.johndcook.com/blog/2009/04/06/numbers-are-a-leak...
        
       | cloogshicer wrote:
       | I've long been having a hunch that we're currently in the "wild
       | west of abstraction".
       | 
       | I think we're missing an essential constraint on the way we do
       | abstraction.
       | 
       | My hunch is that this constraint should be that abstractions
       | _must_ be reversible.
       | 
       | Here's an example: When you use a compiler, you can work at a
       | higher layer of abstraction (the higher-level language). But,
       | this means you're now _locked into_ that layer of abstraction. By
       | that I mean, you can no longer work at the lower layer
       | (assembly), even if you wanted to. You could in theory of course
       | modify the compiler output after it 's been generated, but then
       | you'd have to somehow manually keep that work in sync whenever
       | you want to re-generate. Using an abstraction kinda locks you
       | into that layer.
       | 
       | I see this problem appearing everywhere:
       | 
       | - Use framework <--> Write from scratch
       | 
       | - Use an ORM <--> Write raw SQL
       | 
       | - Garbage collection <--> Manual memory management
       | 
       | - Using a DSL <--> Writing raw language code
       | 
       | - Cross platform UI framework <--> Native UI code
       | 
       | - ...
       | 
       | I think we're missing a fundamental primitive of abstraction that
       | allows us to work on _each layer_ of abstraction without being
       | locked in.
       | 
       | If you have any thoughts at all on this, please share them here!
        
         | ihumanable wrote:
         | Lots of abstractions have an escape hatch down to the lower
         | level, you can put assembly in your C code, most ORMs have some
         | way to just run a query, etc.
         | 
         | I think the question I have is, what benefit does this provide?
         | Let's say we could wave a magic wand and you can operate at any
         | layer of abstraction. Is this beneficial in some way? The
         | article is about leaky abstractions and states
         | 
         | > One reason the law of leaky abstractions is problematic is
         | that it means that abstractions do not really simplify our
         | lives as much as they were meant to.
         | 
         | I think I'm just struggling to understand how this would help
         | with that.
        
           | cloogshicer wrote:
           | It would help because you could tackle the problem at hand
           | always at the right layer of abstraction.
           | 
           | If a certain aspect of the problem can be solved easily in a
           | higher layer of abstraction, great! Let's solve it at that
           | layer, because it's usually easier and allows for more
           | expressiveness.
           | 
           | But whenever we need more control, we can seamlessly drop
           | down to the lower layer and work there.
           | 
           | I think we need to find a fundamental principle that allows
           | this. But I see barely anyone working on this - instead we
           | keep trying to find higher and higher layers of abstractions
           | (LLMs being the most recent addition) in the hopes they will
           | get rid of the need of dealing with the lower layers. Which
           | is a false hope, I feel.
        
         | titzer wrote:
         | I work on programming languages and systems (virtual machines).
         | A key thing with a systems programming language is that you
         | need to be able to do things at the machine level. Here's a
         | talk I gave a year ago about it:
         | https://www.youtube.com/watch?v=jNcEBXqt9pU
        
         | eschneider wrote:
         | That's not really true of, at least C compilers. Because
         | compilers have ABI's and fixed calling conventions, it's
         | straightforward, documented, and not uncommon (depending on
         | your application area/deployment target) to drop down to the
         | ASM layer if you need to do that.
         | 
         | It's definitely one of those things that makes C nice for bare
         | metal programming.
        
           | cloogshicer wrote:
           | Interesting, I'm curious though, once you do drop down to the
           | ASM layer, how do you ensure that this code doesn't get
           | overwritten by new compiler output? Or is this something you
           | somehow include in the compile step?
        
             | zro wrote:
             | In my experience (admittedly limited) you include the
             | assembly in the compile step. Your linker hopefully puts
             | everything together so you can talk to yourself
        
         | Veserv wrote:
         | No, reversible abstractions are just one kind of abstraction.
         | For instance, a machine code sequence to a linear sequence of
         | assembly instructions is a reversible abstraction. Not every
         | machine code sequence is expressible as a linear sequence of
         | assembly instructions, but every linear sequence of assembly
         | instructions has a trivial correspondence to a machine code
         | sequence.
         | 
         | However, consider the jump to a C-like language. The key
         | abstraction provided there is the abstraction of infinite local
         | variables. The compiler manages this through a stack, register
         | allocation, and stack spilling to provide the abstraction and
         | consumes your ability to control the registers directly to
         | provide this abstraction. To interface at both levels
         | simultaneously requires the leakage of the implementation
         | details of the abstraction and careful interaction.
         | 
         | What you can do easily is what I call a separable abstraction,
         | a abstraction that can be restricted to just the places it is
         | needed/removed where unneeded. In certain cases in C code you
         | need to do some specific assembly instruction, sequence, or
         | even function. This can be easily done by writing a assembly
         | function that interfaces with the C code via the C ABI. What is
         | happening there is that the C code defines a interface allowing
         | you to drop down or even exit the abstraction hierarchy for the
         | duration of that function. The ease of doing so makes C highly
         | separable and is part of the reason why it is so easy to call
         | out to C, but you hardly ever see anybody calling out to say
         | Java or Haskell.
         | 
         | Of course, that is just one of the many properties of
         | abstractions that can make them easier to use, simpler, and
         | more robust.
        
         | jerf wrote:
         | Abstractions work by restricting the domain of what you can do,
         | then building on those restrictions. For example, raw hardware
         | can jump anywhere, but structured programming constrains you to
         | jump only to certain locations in order to implement if, for,
         | functions, etc. It is precisely those restrictions that bring
         | the benefits of structured programming; if you still frequently
         | dipped into jumping around directly structured programming
         | would fail to provide the guarantees it is supposed to provide.
         | CRUD frameworks provide their power by restricting you to CRUD
         | operations, then building on that. Immutable data is
         | accomplished by forbidding you from updating values even though
         | the hardware will happily do it. And so on.
         | 
         | Escape hatches under the abstractions are generally there
         | precisely to break the abstractions, and break them they do.
         | 
         | Abstractions _necessarily_ involve being irreversible, or, to
         | forestall a tedious discussion of the definition of
         | "irreversible", necessarily involve making it an uphill journey
         | to violate and go under the abstraction. There's no way around
         | it. Careful thought can make using an escape hatch less pain
         | than it might otherwise be (such as the ORM that makes it
         | virtually impossible to use SQL by successfully hiding
         | everything about the SQL tables from you so you're basically
         | typing table and column names by dead reckoning), but that's
         | all that can be done.
         | 
         | One thing to do about this is that just as in the past few
         | years the programming community has started to grapple with the
         | fact that libraries aren't free but come with a certain cost
         | that really adds up once you're pulling in a few thousand
         | libraries for a framework's "hello world", abstractions that
         | look really useful but whose restrictions don't match your
         | needs need to be looked at a lot more closely.
         | 
         | I had something like that happen to me just this week. I needed
         | a simple byte ring buffer. I looked in my language's repos for
         | an existing one. I found them. But they were all _super_
         | complicated, offering tons of features I didn 't need, like
         | being a writethrough buffer (which involved taking restrictions
         | I didn't want), or where the simple task of trying to
         | understand the API was quite literally on par with implementing
         | one myself. So I just wrote the simple thing. (Aiding this
         | decision is that broadly speaking if this buffer does fail or
         | have a bug it's not terribly consequential, in my situation
         | it's only for logging output and only effectively at a very
         | high DEBUG level.) It wasn't worth the restrictions to build up
         | stuff I didn't even want.
        
           | cloogshicer wrote:
           | > It is precisely those restrictions that bring the benefits
           | [...]
           | 
           | Wouldn't it be possible to say "ok, I'll take those
           | restrictions as long as they benefit me, but once I notice
           | that they no longer do, I'll break them and drop down to the
           | lower layer. But only for those parts that actually require
           | it"?
           | 
           | > Abstractions necessarily involve being irreversible, or, to
           | forestall a tedious discussion of the definition of
           | "irreversible", necessarily involve making it an uphill
           | journey to violate and go under the abstraction.
           | 
           | Why? Not being snarky, I'm genuinely trying to understand
           | this better.
        
         | samatman wrote:
         | > _Here 's an example: When you use a compiler, you can work at
         | a higher layer of abstraction (the higher-level language). But,
         | this means you're now locked into that layer of abstraction. By
         | that I mean, you can no longer work at the lower layer
         | (assembly), even if you wanted to._
         | 
         | Native-code compilers commonly allow emitting assembly
         | directly, but now your source code isn't portable between CPUs.
         | Many interpreted languages, even most, allow FFI code to be
         | imported, modifying the runtime accordingly, but now your
         | program isn't portable between implementations of that
         | language, and you have to be careful to make sure the behavior
         | you've introduced doesn't mess with other parts of the system
         | in unexpected ways.
         | 
         | Generalizing, it's often possible to drill down beneath the
         | abstraction layer, but there's often an inherent price to be
         | paid, whether it be taking pains to preserve the invariants of
         | the abstraction, losing some of the benefits of it, or both.
         | 
         | There are better and worse versions of this layer, I would
         | point to Lua as a language which is explicitly designed to
         | cross the C/Lua boundary in both directions, and which did a
         | good job of it. But nothing can change the fact that pure-Lua
         | code simply won't segfault, but bring in userdata and it very
         | easily can; the problems posed are inherent.
        
         | wvenable wrote:
         | Most ORMs give a way to integrate nicely with SQL if you need
         | to reach down to that layer and still use the rest of the ORM
         | features.
         | 
         | There is no silver bullet; everything is a trade off. Almost
         | all of the time, the trade off is entirely worth it even if
         | that gets you locked into that solution.
        
           | cloogshicer wrote:
           | > Most ORMs give a way to integrate nicely with SQL if you
           | need to reach down to that layer and still use the rest of
           | the ORM features.
           | 
           | Agreed, that's a good thing, in my experience.
           | 
           | > Almost all of the time, the trade off is entirely worth it
           | even if that gets you locked into that solution.
           | 
           | I wish this would match my experience.
        
             | wvenable wrote:
             | What's funny is that ORMs giving you directly access to SQL
             | is a leaky part of the abstraction but in this case that's
             | good!
             | 
             | I think being locked into a some abstraction is so common
             | place that you don't even consider it being a thing until
             | you have a problem with it. Look at your examples:
             | compilers, libraries, frameworks, etc. As an example, is
             | anyone truly upset that coding in Python locks you into the
             | Python ecosystem? Yet, I've used libraries/frameworks that
             | didn't win the war of popularity and I'm still
             | unfortunately committed. I think there's a bias at play in
             | how we look at these things.
        
       | titzer wrote:
       | Joel of course hits the nail on the head about the two major
       | things that cause abstractions to fall apart: performance and
       | bugs (or debugging). In programming languages we talk about
       | abstractions all the time--PL of course is all about
       | abstractions. A computational abstraction like a bytecode, source
       | language, or even machine code, can be proven be a proper (or
       | full) abstraction, meaning there is no way for implementation
       | details to leak in--you cannot observe the electrons flowing by
       | executing A+B, after all.
       | 
       | ...until you start measuring sidechannels, or the CPU or compiler
       | has a bug.
       | 
       | I think about this a lot when dealing with VMs; a complex VM
       | cannot hide its complexity when programs care about execution
       | time, or when the VM actually has a bug.
        
       | refactor_master wrote:
       | A car is an implementation meant to deal with a problem (the
       | weather), but never abstracts away physics or forces full buy-in
       | to some alternate reality. You can't just go around and say any
       | imperfection in an implementation is a leaky abstraction. That's
       | not how it works.
       | 
       | My shoe is not abstracting away the terrain, nor is it leaky
       | because it doesn't handle _all_ weather conditions. Well, it is
       | leaky, but not in that sense.
        
         | samatman wrote:
         | An analogy is an abstraction, and abstractions leak.
        
       | wvenable wrote:
       | I loved this essay when it came out but I've come to dislike how
       | "leaky abstraction" has become a form of low effort criticism
       | that gets applied to almost anything.
        
       | davesque wrote:
       | I feel like this article should be called "The Law of Bad
       | Abstractions." I often see this cited as a blanket rejection of
       | complexity in software. But complexity is unavoidable and even
       | necessary. A skillful engineer will therefore design their
       | abstractions carefully and correctly, balancing time spent
       | thinking forward against time spent implementing a solution. I
       | think Joel understands this, but it feels weird how he frames it
       | as a "law", as though it's something he's discovered instead of a
       | simple fact that arises from the nature of what abstractions are:
       | things that stand in for (or mediate interaction with) some other
       | thing without actually being that thing. What a surprise that the
       | stand-in ends up not being the actual thing it's standing in for!
        
       ___________________________________________________________________
       (page generated 2024-03-06 23:00 UTC)