4 ms·
In many cases speaking of the foolike nature of a value is not dissimilar to speaking to the primeness of an integral: Is a value prime? And now here's is an al
by geocar 7y ago
In many cases speaking of the foolike nature of a value is not dissimilar to speaking to the primeness of an integral: Is a value prime? And now here's is an algorithm for determining whether this value is prime.
The motivation for many splitting out a prime-testing function is that primality testing is hard to do efficiently, not that there are many kinds of primes or many kinds of integrals. Indeed, in some languages "primes" is a builtin (p:), or a trivial derivation {(2=+⌿0=(⍳⍵)∘.|⍳⍵)/⍳⍵} for some domain, and that's the only domain our application is concerned with so is-prime is a (⊣∊primes) -- is foolike-ness like that?
Nothing is being abstracted here, and nothing is gained by indirection: Does this is-prime routine even deserve a name?
Sometimes the foolike nature has nothing to do with the value: Is an apple foolike? It isn't today, but it might be tomorrow! (That's numberwang!) Is this account locked (go check the disk!)? Sometimes we encode that the account is locked by putting an asterisk in the password field -- this won't match any hashes, so the login will always fail, and a "is_locked" routine might start exactly this way: def is_locked(x): return x.password.contains(42) but in the future we want to be sure that this isn't a _copy_ of a locked account or there's a synchronisation issue, so we go check and then def is_locked(x): return x.userid in locked_accounts
Nothing is being abstracted here either- we're still only talking about giving this algorithm a name (or maybe delaying the discussion about which algorithm gets this name). So why don't we just say 'something in x.can instead of x.can('something')? Because the former means set membership and the second may be able to not reify the set. Proxies like __in__ might help, but it's not just the syntax: Our language has let us down (clearly, not enough laziness! time to haskell all the things!), and so we cheat: The locked button sets a flag on the user object, instead of adding a user to the real list of locked users.
But what if our language were smart? Why wouldn't we write x.userid in locked_users?
> Whereas the following code has meaning:
And yet it is wrong! It has a nasty security bug in it that you will never find, and the next guy will never find. Fools and children would argue endlessly that something was wrong with the ticket or user story that led to this code, or demand that they didn't have enough experts on the team, but no matter how smart you are (or you think you are), you'll write a piece of code that is so short it cannot possibly be wrong and yet it is.
Code hiding (whether you call it indirection or abstraction) also hides bugs, and yet few of us have the time or attention to stare at the bits blurry with a steady hand and a magnetised needle, so there'll always be some amount of code hiding. The real trick (if there is one) is to do as little of it as is possible.
- Y_Y 7y agoI very much enjoyed this poem. All the same I think you may have thrown out the abstraction with the bath water. > Does this is-prime routine even deserve a name? Absolutely. If you saw it over and over you might start just reading it as "is-prime" instead of going through the process of mentally interpreting it each time. But what about similar-looking functions with similar functionality? You want a programmer to go and make you a promise that it has the meaning (if not the implementation) you're thinking about. That promise is the same as "code-hiding".
- geocar 7y ago> But what about similar-looking functions with similar functionality? Even though we're unlikely to need this construction more than once: def is_prime(x): return x in primes(x) This one (or one just like it) appears quite common: def is_in_set(x,y): return x in y But Guido already noticed that! That's why he made an "in" operator in the first place! As soon as our routines become too generic, we're just making APL without arrays, and that's why taste matters so very much. > That promise is the same as "code-hiding". If I can see the implementation at the same time as its usage, then the code is not hidden. Ipso facto. But to expand more on what I mean by this, consider that close() is hiding code: You get all of the bugs in the C library; in the Kernel; all in code you cannot see either because it is locked/compiled, or because it's in a different file you didn't bother to read. And so on. And yet the world didn't stop spinning, and many people use close() every day without knowing or dealing with a myriad of bugs and weird corner cases[1]. So it is that even if code hiding is sometimes bad, it is sometimes less bad than other things we could be doing. [1]: Ha ha, only serious. http://geocar.sdf1.org/close.html http://geocar.sdf1.org/close.html
- xorcist 7y agoYou just summarized what must be years of my life.
- jrochkind1 7y ago> Nothing is being abstracted here either- we're still only talking about giving this algorithm a name I would say giving something a name that summarizes it so you can refer to it by the name as shorthand (and in code, "referring to" means "using")... is in fact exactly what "abstraction" is, it's possibly almost a good working definition of "abstraction" in fact.