[HN Gopher] Abstraction: Not what you think it is
___________________________________________________________________
Abstraction: Not what you think it is
Author : tempodox
Score : 152 points
Date : 2022-03-29 10:36 UTC (1 days ago)
(HTM) web link (www.pathsensitive.com)
(TXT) w3m dump (www.pathsensitive.com)
| jakelazaroff wrote:
| He's talking about what this article calls "anti-unification",
| but this Bret Victor post really changed the way I think about
| abstraction: http://worrydream.com/LadderOfAbstraction/
| avgcorrection wrote:
| Looks more like parameterization.
| adamkl wrote:
| Reading this makes me think of "stratified"[0] design, which I
| think is a good example of abstraction done right.
|
| [0] - https://medium.com/clean-code-development/stratified-
| design-...
| dgb23 wrote:
| The discussion about abstraction in this article is interesting
| and thought provoking. It's useful to think about the different
| things we call abstractions. Very much worth a read.
|
| But I feel like it tries a bit too hard to re-define what
| abstraction means ("only this subset of abstractions are real
| abstractions"), instead of just putting "abstract interpretation"
| next to it. This idea can stand on its own without trying to re-
| define the world.
|
| Secondly I understand the discussed notion of abstraction as a
| domain model, which is information (data and functions) _about_
| the world. I like the term model better here than "idealized
| mapping" because the former implies a bit more that there are
| assumptions about the data and usage context of said model (often
| implicit, unstated) and that it is incomplete.
| undecisive wrote:
| It reminds me of a concept I've been hearing a lot recently:
| Dictionaries do not define words. They tell you what a word is
| being used for, but nothing about a dictionary gives any moral
| or philosophical credence to any particular definition.
|
| In other words, the definition of a word depends on its real-
| world usage; dictionaries attempt to capture common usages, but
| no definition of a word can be considered the "true" definition
| more than any other used and understood application of the
| word.
|
| So in this case, calling these definitions "imposters" or "not-
| abstractions" is absolutely wrong. That said, I like the
| attempt to introduce names for different flavours of
| abstraction to make discussion easier. That's definitely
| useful. Just wish it wasn't off the back of incorrectly telling
| people that their use of the language is incorrect.
| fluoridation wrote:
| There's actually two different schools of linguistics:
| prescriptive ("language is this") and descriptive ("language
| is used like this"). A dictionary can be written in one or
| the other, or some mixture of the two. To say that all
| dictionaries are purely descriptive is incorrect.
| [deleted]
| brimble wrote:
| Even descriptive dictionaries imply a certain amount of
| prescription, as: "prefer using words as they are herein
| defined, if you care about others being able to understand
| you".
| fluoridation wrote:
| I would tend to agree. I've heard the "dictionaries
| _only_ record usage " argument before, and I've always
| found it unconvincing. The same people who argue for
| purely descriptive linguistics when you challenge a word
| usage of theirs for being ambiguous will turn around and
| correct you when you misspeak.
| [deleted]
| dgb23 wrote:
| Fully agreed! And this:
|
| > That said, I like the attempt to introduce names for
| different flavours of abstraction to make discussion easier.
| That's definitely useful.
|
| Is the real value of this article.
| [deleted]
| mcaruso wrote:
| From the article:
|
| > But we've had a pretty good definition of abstraction since
| 1977, originally in the context of program analysis, and -- I
| claim -- it actually translates quite well into a precise
| definition of "abstraction" in engineering.
|
| So I don't think the author is saying that all these other
| people are "wrong", but rather that this one particular
| definition seems to capture the underlying essence of what we
| intuitively think of when we say "abstraction", and the rest of
| the "hodgepodge of different concepts" break down if you
| analyze them a bit deeper (as the author did in the "Not
| Abstraction" section).
| dgb23 wrote:
| Yes and I don't agree that this is particularly fruitful. I
| might have completely misunderstood it but here we go:
|
| The common theme in the Not Abstraction section is: These
| things are used to build abstractions and are not necessarily
| abstractions themselves. This is not only nitpicking but it's
| also false. Programming language features like functions and
| interfaces are already abstractions, even in the narrow sense
| that the article describes. They are an idealized mapping to
| something concrete (register machines, vms etc.) and provide
| precision, soundness and are based on specification.
|
| Again, I very much like the core idea presented here, but I
| think it is completely unnecessary to make the claims about
| what is and isn't "true" abstraction.
|
| Take this quote:
|
| "Abstractions are separate from the code, and even from the
| abstract domain. It does not make sense to say that the
| bookTable function or anything else in this file "is" the
| abstraction, (..)"
|
| The function _is_ not the abstraction because abstractions
| are entirely conceptual? Is it a way to communicate an
| abstraction then? What about the actual machine code the
| compiler produces from that function, is there some
| abstraction?
|
| None of this helps me. The interesting part is that code is
| used to model information, it's not the world itself or even
| tries to be.
|
| Then this:
|
| "Feel free to call numbers an abstraction of the hardware,
| but be prepared to switch to this precise terminology when
| there's tension on the horizon."
|
| Simple abstractions that are not discussed are names and
| signs. These are abstractions in the very real sense and they
| are very simple on their own. But they are entirely
| contextual and are allowed to mean different things. For
| example the term "abstraction".
| agentultra wrote:
| I think you've misunderstood it.
|
| Let's design a system that allows us to run virtual
| computers on a single hardware platform. In some part of
| this system we need to map real hardware addresses to
| virtual ones in order to isolate the different virtual
| computers.
|
| Now you might need a way to take a real, logical address to
| a memory location on this machine and get a virtual
| address. You might have to run this system on many
| different hardware platforms and you only know the
| platforms you will run on _today_ (or the next few months).
| Almost without thinking about it you might choose to use a
| virtual method on a class to define a function signature
| for this operation. That way folks implementing this system
| for different hardware platforms can create a sub-class and
| fill in a concrete definition of the virtual method. Now
| users of the system can translate an address and don 't
| have to think about the underlying hardware platform
| they're running on! Abstraction!
|
| Only it's not an abstraction.
|
| If you attempt to formalize what it means to map a hardware
| address to the virtual address you will find it quite
| difficult because your interface provides no information
| about hardware addresses. In other words the virtual method
| does not put in all of the details of the concrete
| implementation and so we cannot maintain an invariant in
| our specifications that would ensure that we only translate
| valid addresses, or that translation is deterministic --
| properties that would be important for users of the
| abstraction to truly be able to ignore the underlying
| complex domain. If we _could_ write such a specification
| for this virtual method though, it would be very
| complicated, and that is a good sign this is not a good
| abstraction.
|
| Abstractions are often separate from the code because
| they're much more general than a single program. If we came
| up with a better abstraction in a formal logic like
| separation logic or using Hoare logic -- we might be able
| to prove that the properties we care about hold and
| therefore any program that implements this specification
| will have the same properties. And there might be several
| such programs!
|
| So what industry programmers are often saying when they are
| talking about "abstraction" is "indirection and vagueness."
| What this article is trying to show is that we can give
| precise definitions to our abstractions so that we can
| build new _semantic_ layers that have precise meaning: when
| I translate a hardware address I get a valid, deterministic
| virtual address and nothing else.
| dgb23 wrote:
| These are very useful properties to have. And I rather
| use an abstraction where these properties hold, rather
| than one that just takes care of some plumbing. There is
| a qualitative difference here.
| specialist wrote:
| Ya. My brain is all thumbs when trying to handle the philosophy
| parts of software.
|
| Both this OC and the wiki article on 'abstraction', wrt to
| software design (eg OOAD) make me think of generalization and
| specialization.
|
| --
|
| My own working definition of 'abstraction' vs 'mental models',
| because I lack more proper terms:
|
| - abstractions hide details, aka black box
|
| - mental models explain how something works, even if over
| simplified
|
| An example of a good (quite useful) abstraction is the initial
| Java Virtual Machine. Its 'interface' (per this OC) is quite
| good, meaning comparatively small impedance mismatch, and
| acceptable 'leakiness'. As we've seen over time, driven by
| optimization, that abstraction is necessarily bypassed or
| mitigated with JMM, FFI, unsafe stuff, intrinsics, direct
| memory, etc.
|
| Using an example of a mental model from my prior works, because
| I'm precaffeinated, and I can't think of a better example than
| Newtonian mechanics, already mentioned.
|
| I used to work in print production, like books and magazines.
| For bookwork, I created an algorithm for the folding of big
| sheets of paper into 'signatures' containing printed pages. My
| app accounted for folds, binding, and cutting. It revealed the
| manufacturing process, so there could be no mistake. It reduced
| an Illustrator-like application (ScenicSoft' Preps imposition
| app) to a simple form. This simplification was possible because
| I had invented a better mental model.
|
| --
|
| My working definition of abstraction doesn't jive with anyone
| else's. I'm open to alternate suggestions.
| https://en.wikipedia.org/wiki/Abstraction
| chousuke wrote:
| I think of things in terms of abstractions and models.
| Abstractions _generalize_ commonalities into a vocabulary
| that can be used on any entity that is covered by the
| abstraction. A sequence is an abstraction, but data
| structures themselves aren 't as far as software is
| concerned. Data structures can be sequences, but you can't
| _create_ a sequence.
|
| A (logical) model is a simplified representation of the real
| thing that is still _complete enough_ that it can be used to
| successfully reason about and accomplish goals with a system.
| A linked list datastructure is a real thing with a number of
| possible implementation details, but it still has a
| straightforward, concrete _model_ of what it is. It 's not an
| abstraction.
|
| A model does not have to be abstract at all; it can be very
| concrete, even if it in practice hides some underlying
| details.
|
| It seems common in software to either get lost in abstraction
| so that you forget the model, or consider the model so rigid
| that you miss useful, simplifying abstractions.
| specialist wrote:
| I really like your description of how models enable
| reasoning about the problem.
|
| Ya, abstractions vs models. I'll drop the "mental"
| qualifier, thanks.
|
| > _get lost in..._
|
| Totally. Too many times, the implementation comes to be
| treated as the model, completely obfuscating the client's
| actual problem.
| dustingetz wrote:
| The lambda calculus definition of abstraction as lambda i think
| matches the idea that abstractions are not found in code.
| Performance constraints IRL are the key operational gap that
| mathematical lambda does not account for - as lambda cannot
| effectively account for hardware execution and network - and the
| sole reason (AFAICT) that the implementing code of an IRL
| software system running on hardware cannot contain true
| abstraction, and thus as software practitioners we should not
| seek them. Instead, we should seek to minimize LOC which has
| direct tangible impact on costs and outcome.
| alfonsodev wrote:
| for me to abstract, is to elevate a concept to a parent category
| so that operations are interchangeable with other siblings.
|
| Wether to know if something is an abstraction, could be tested by
| asking, is this thing useful to operate with different child
| categories in just one place ?
|
| When you have an abstraction with just one child category, rather
| than useful is just confusing.
|
| For example if in your universe would exist just on type of
| Vehicle called Car, but you would use Vehicle abstraction.
| hzhou321 wrote:
| > Abstraction in general is usually said to be something which
| helps readers understand code without delving into the details.
|
| I agree with this. And to me, this means a good abstraction is
| necessary to be ambiguous. For example, number is an abstraction.
| But a type that is int32 is not an abstraction. In fact, we are
| not using a meta-layer that allow ambiguity is the reason that
| most abstractions force readers to be concerned with details in
| order to understand code.
|
| Math abstractions are good and rigorous. That is because math is
| never concerned with reality. As soon as you deal with reality,
| math is ambiguous from start to end. For example, what is one?
| Math throw away all the physical details, that is what allows it
| to be useful -- one can understand math without ever concerned
| with physical details.
|
| The current popular programming language are not suitable for
| abstractions. Our natural language are good for abstractions. But
| I think we probably can have something in-between, like what we
| come up with math.
| lalaithion wrote:
| What? How is int32 not an abstraction? There's no such thing as
| a "real" int32; it's just a bunch of metal in a box with
| electricity in it.
| Koshkin wrote:
| These are all very abstract statements. (And you are not
| wrong.)
| Koshkin wrote:
| I think of an abstraction as a map from a model space into the
| problem domain. (A map that is not necessarily injective, and
| sure enough not surjective.)
|
| I am sure category theory can say much about this.
| UncleMeat wrote:
| The whole point of the article is providing a rigorous
| definition rather than the wishy-washy stuff people usually
| use. This is independent of category theory. Cousot was working
| in a different space.
| Koshkin wrote:
| No, I thoroughly appreciate that, it's just that the
| functorial language of the "abstract nonsense" seems perfect
| for discussing modeling and abstraction.
| CoastalCoder wrote:
| A tangent about writing conventions: It pisses me off when a
| headline tells me that I'm understanding / doing something wrong.
|
| I realize this is subjective, but I hear it as the author
| arrogantly assuming that their insight or approach is objectively
| better than those of their entire audience. Without even knowing
| their audience members are. They just know they're more correct
| than you, and they're happy to advertise that.
|
| I'm sure it drives engagement, but it definitely reduce the
| chance of me reading the article.
| andrewingram wrote:
| I've come to think of an abstraction as a potentially lossy
| transformation of a model into one better suited to the task at
| hand.
| ncmncm wrote:
| ... to one _somebody hoped_ was better suited to the task. That
| hope is not necessarily realized.
|
| If it is not lossy, it is likely not to be providing net value.
| andrewingram wrote:
| You're not wrong.
| UncleMeat wrote:
| That's not true. Consider the problem of detecting null
| pointer dereferences. Bucketing points into "null" and "not
| null" is lossless w.r.t. this problem domain. This can be
| very useful. When you stick Top and Bottom into the possible
| options is where you get lossy behavior. That can be useful
| too, but it isn't strictly necessary.
| ncmncm wrote:
| Binning pointers into "null" and "not null" is, exactly,
| lossy.
| UncleMeat wrote:
| With respect to the domain it isn't.
| ncmncm wrote:
| The domain is, exactly, lossy.
| busyant wrote:
| Interesting. You've made me realize that models (in the
| scientific sense) are lossy transformations of reality.
| andrewingram wrote:
| Yeah, this is how I think about Newtonian Mechanics -- a
| useful abstraction.
| Koshkin wrote:
| Starting with "point particle." (By the way, theoretical
| mechanics has long been considered part of mathematics.)
| dTal wrote:
| Moreover, the _point_ of a model is to be lossy:
| https://en.wikipedia.org/wiki/On_Exactitude_in_Science
| arethuza wrote:
| Spherical cows being the obvious example - in some
| circumstances that might be a perfectly valid modelling
| assumption.
| nathias wrote:
| This is a fairly common sense notion of abstraction (abstraction
| as abstracting away the details of something), but I don't think
| its the whole picture. I'm studying abstraction and the best
| formulation of this aspect I found was abstraction as the degree
| of complexity encapsulation.
| prionassembly wrote:
| Yea, but this complexity is not inherent to code.
| nathias wrote:
| What do you mean? Of course it is, all code is leaky
| abstractions.
| Kalanos wrote:
| This is an abstraction: https://medium.com/towards-data-
| science/hypertuning-for-tens...
| smitty1e wrote:
| If asked, I'd've said: "Applied ontology[1]".
|
| When we code, we're philosophizing about information in some
| language (itself an applied ontology), for the decreasingly
| worse.
|
| Occasionally one arrives at a coherent, stable product.
|
| [1] https://en.wikipedia.org/wiki/Ontology
| userbinator wrote:
| _Its opposite is unification, which is comparatively never used
| in programming._
|
| Isn't that just what people usually refer to as "inlining"?
| Helloyello wrote:
| hathawsh wrote:
| The concept of abstraction is simple and clear when you think
| about programming as primarily the act of teaching other people
| (future maintainers, other contributors, and my forgetful self)
| rather than writing instructions for a computer. An abstraction
| is simply a grouping of human-level concepts. Good abstractions
| are generally easy to teach and learn.
|
| Some abstractions are more useful/helpful/powerful than others.
| The usefulness of an abstraction often depends on the domain.
| Much of the time, the best way to find out the right abstractions
| is to first create multiple things with no new abstractions, then
| decide that everyone will save time if you merge some of the
| concepts you created. It's good to use well-known, tested
| abstractions early on, but it's risky to create new abstractions
| prematurely.
|
| Sometimes a function, data structure, interface, or API happens
| to embody an abstraction very cleanly. When that works out, the
| abstraction is easy to teach and tends to be more useful. Most
| abstractions are a bit messier than that, though, which is why
| abstraction is really a human-level teaching/learning construct
| rather than any element of programming languages.
| theknocker wrote:
| Garlef wrote:
| > "Bad programmers worry about the code. Good programmers worry
| about data structures and their relationships."
|
| That's catchy. But:
|
| The practice of programming is about manipulating a special kind
| of data (code). And so: "Good programmers worry about code
| structures and their relationships."
|
| (Even more so in the age of devops, infrastructure as code, etc.)
| vjust wrote:
| You could fill pages on the subject of abstraction. While on the
| subject it would've been apt for the Author to quote or give a
| nod to the one of the pioneers in this field : Barbara Liskov,
| and the Liskov substitution principle. Not that I've anything
| against Joel Spolsky - but I'd read Liskov any day over Joel's.
|
| So easy to get wrapped up in all the syntactic sugar.
| layer8 wrote:
| What the article describes as the true meaning of "abstraction"
| is very close to (if not the same) as "interface contract", and
| it's correct that the important quality is to enable precise
| reasoning (of which "abstract interpretation" is one possible
| form) about the program behavior along that abstraction/interface
| boundary. Functions have an interface contract, classes have an
| interface contract, data types have an interface contract, things
| like REST APIs have an interface contract, and so on.
|
| The fact that some languages, as mentioned in the article, have a
| language feature called "interface" is somewhat unfortunate,
| because it makes unclear when someone says "interface" whether
| they refer to the language feature or to the more general
| meaning. (For example, every Java class has an interface-in-the-
| general-sense, just like every class has an implementation,
| regardless of whether the class happens to implement an
| interface-the-language-feature or not.) Prior to that, it was
| always understood that "interface" implies a certain contract,
| usually one that imposes conditions beyond the mere type
| signature of the respective entity.
|
| Incidentally, that's also one benefit of nominal typing (as
| opposed to structural typing), because it expresses the fact that
| the interface is usually more than its type signature, and
| therefore two entities having compatible type signatures are not
| necessarily compatible in terms of their interface contract, and
| thus shouldn't be implicitly convertible/assignable to each
| other.
| waffletower wrote:
| Abstraction is not what you think it is if you think it is not
| what I think it is.
| ChrisMarshallNY wrote:
| I don't mind the basic interpretation of abstraction that the
| article mentions, but I generally extend it to also mean that
| _code_ (not just the coder) doesn't have to deal with the
| underlying complexity.
|
| For example, I consider most SDKs to be abstractions.
|
| It's really just semantics, as I guess we could argue that the
| "classic" definition applies to code, as well as to coders.
| skybrian wrote:
| This seems like an ultimately doomed attempt to redefine the
| suitcase term "abstraction" to be something more mathematical.
| But you aren't going to change how people use the word
| "abstraction" by telling them they're using it wrong. If you need
| a more precise terminology, it would be better to come up with
| some different words or phrases and popularize them.
| Koshkin wrote:
| > _something more mathematical_
|
| It has been done. Category Theory (a.k.a. "abstract nonsense")
| has been pretty successful describing abstraction using the
| language of functors.
| pete_nic wrote:
| Non-developer here that likes to try to understand CS. I have
| latched onto this definition from Stanford:
|
| "But fundamentally, computer science is a science of abstraction
| -- creating the right model for thinking about a problem and
| devising the appropriate mechanizable techniques to solve it."
|
| http://infolab.stanford.edu/~ullman/focs/ch01.pdf
| btbuildem wrote:
| I've come to understand abstraction as a reduction of something
| complex into something symbolic that captures the bare minimum /
| absolute essence of the reduced thing, and not necessarily in an
| obvious way.
|
| In programming, it could be the boundaries of a concept
| independent of implementation. In visual art, it could be a few
| lines on canvas that evoke the spirit of the thing referenced. In
| jazz, it could be strange notes on the peripheries and askew of
| rhythm that by being what is not, circumscribe what is.
| SPBS wrote:
| Basically functions are not abstractions, the data structures
| that functions act on are the real abstractions. Because the data
| structures have been planned out in a particular way, functions
| can manipulate them as if they were manipulating concrete
| entities in the business domain. Here's a bunch of relevant
| quotes talking about that idea (credits to
| https://medium.com/webdevops/data-structures-548cbea9c520)
|
| "Bad programmers worry about the code. Good programmers worry
| about data structures and their relationships."
|
| - Linus Torvalds
|
| "Fold knowledge into data, so program logic can be stupid and
| robust."
|
| - Eric S. Raymond
|
| "Data dominates. If you've chosen the right data structures and
| organized things well, the algorithms will almost always be self-
| evident. Data structures, not algorithms, are central to
| programming."
|
| - Rob Pike
|
| "Representation is the Essence of Programming"
|
| - Fred Brooks
|
| "One of the key attributes of a "Good" representation, is the
| ease in which it is transformed into other valid information the
| computer can process."
|
| - https://www.cs.utah.edu/~germain/PPS/Topics/information_repr...
| dgb23 wrote:
| But this is more about shifting focus. You still need both,
| data and functions even if you make data richer and functions
| more general and simple. The latter still carry or encode an
| essential part about how you model information. Especially if
| we consider this quote here:
|
| "Syntax without representation is tyranny!"
|
| - Gerald Jay Sussman
| akomtu wrote:
| Functions are abstractions in time; data structures are
| abstractions in space. For example, the same abstraction looks
| like binary search when drscribed as a function and it looks
| like a binary tree when described as a data structure. What
| binary search looks like by itself is unthinkable to us because
| anything we can think about has to be projected to space or
| time.
|
| Edit. If the vertical axis is time and the horizontal plane is
| space, then the floating something in the middle is the
| 'abstraction', its shadow on the plane below is its data
| structure and its projection onto the vertical axis is its
| function. The need to compress everything into the
| 1-dimensional time is what creates those for-loops and ifs. The
| art of finding the right data structure is the art of finding
| the right angle at which the 'abstraction' drops a good
| descriptive shadow.
| Koshkin wrote:
| Computers indeed look more and more like black holes. It is
| not unexpected, then, that one feels the need now to talk
| about structurefunctions that live in spacetime.
| all2 wrote:
| We might call a structurefunction an object. Maybe if we
| made this programming paradigm _object oriented_ we could
| solve some real-world problems.
|
| [edit] spelling [/edit]
| mumblemumble wrote:
| And then a lisp programmer parachutes in and points out that
| functions are absolutely a kind of data structure, other
| functions can act on them, and whether they're part of your
| business domain depends on how you've defined your business
| domain.
|
| And then a data scientist with expertise in differentiable
| programming zooms in on a motorcycle to back them up.
|
| And then a mathematician with expertise in linear algebra time
| travels in from the 19th century to join the party, although
| they're admittedly a bit lost and confused and not much help in
| this particular conversation because they're not familiar with
| modern jargon.
|
| Which isn't to say that those quotes aren't valid or don't
| express concepts worth knowing and internalizing. But they're
| practical statements that apply to a certain way of looking at
| things. A very useful one, to be sure, but not the only one.
| The distinction between functions and data has a tendency to
| disappear upon close examination.
|
| (Almost as if the concepts of "function" and "data structure"
| were themselves abstractions.)
| Diggsey wrote:
| It seems like you missed the point the article was trying to
| make: an abstraction is a mapping from a complex world to a
| simpler world, which preserves the ability to perform many
| useful operations.
|
| Data structures can be used as part of an abstraction. So can
| functions. But neither one _is_ the abstraction.
|
| In the case of data structures, you might use a particular
| data-structure as the domain of the simpler world, but it's the
| mapping itself that _is_ the abstraction, and that mapping is
| not part of the code, it 's a conceptual thing that must be
| documented.
|
| All of those quotes say how important data and its
| representation is to a programmer, but that doesn't equate to
| saying data structures are abstractions, because abstractions
| aren't the only important thing. I'm not sure they're even the
| most important thing.
| macrolocal wrote:
| You could say that an abstraction is a decision about which
| details of the complex world are important, or even
| expressible. Problems are sometimes intractable just because
| the wrong decision's been made.
| atoav wrote:
| My feeling is that abstractions can also be (potentially)
| more. E.g. good abstractions are themselves composable in
| expressive and new ways, which gives programmers the
| ability to reach goals faster, easier and with less risk
| and maintenance cost.
|
| Building abstractions can be ery much like creating a new
| language.
| macrolocal wrote:
| Well, I bet Laplace's demon could get by just fine
| without them, and maybe even spot clever optimizations
| that a human never would. After all, there's no such
| thing as a free lunch. :)
| rajangdavis wrote:
| "It is better to have 100 functions operate on one data
| structure than 10 functions on 10 data structures." - Alan
| Perlis
| dustingetz wrote:
| "What is "data" without an interpreter" - Alan Kay
| https://news.ycombinator.com/item?id=11946764
|
| You've failed to account for the interpreter and the hardware
| it runs on that provides operational properties necessary for
| human use, i.e. performance
| Hinrik wrote:
| "Show me your flowchart and conceal your tables, and I shall
| continue to be mystified. Show me your tables, and I won't
| usually need your flowchart; it'll be obvious." -- Fred Brooks,
| The Mythical Man Month (1975)
| tromp wrote:
| > the data structures that functions act on are the real
| abstractions
|
| I think type level functions, like Functor or Monad, also
| qualify as abstractions.
| proc0 wrote:
| Functions are abstractions of the business logic. If they
| weren't then you couldn't use them over and over again. It's
| abstracting by exposing a simple interface that then does more
| under the hood, and this is repeated layer after layer, from
| functions to libraries.
|
| The decision of what a function will do over and over again is
| abstracting the layer below which if it weren't for the
| function, would have repetition of some kind. It's taking those
| repeated bits, and factoring out the different elements
| reducing them to a function call.
|
| That said, I understand where this perspective is coming from,
| and perhaps "refinement" is more descriptive of a more
| practical approach.
| jhgb wrote:
| > Basically functions are not abstractions, the data structures
| that functions act on are the real abstractions
|
| That distinction sounds mildly problematic when one can turn a
| data structure into a function.
| amelius wrote:
| But if you're writing a compiler, the program becomes the data
| ...
| the_af wrote:
| > _Basically functions are not abstractions, the data
| structures that functions act on are the real abstractions_
|
| Maybe, but this is not at all what the article is arguing,
| however.
| lobstey wrote:
| cannot agree on that. Here you got the OO ways of thinking by
| combining the data and code logic. However, it's totally
| legitimate to say functions wrapped up the procedures or
| transformations l.
| ncmncm wrote:
| Religious devotion to abstraction is a common failing in younger
| coders. Abstraction performs a valuable service when it reliably
| masks details irrelevant to your task. It is actively harmful
| when it conceals from you details important to your task.
|
| A common example of a harmful abstraction, in C and C++, is a
| typedef of a pointer to an opaque name. The typedef conceals,
| when you read code using it, that the type is really a pointer,
| and so subject to all the excess operations provided for pointers
| in those languages. But one thing every C and C++ programmer
| always needs to know about a type they are working with is
| whether it is a pointer.
|
| Every abstraction has an unavoidable cost. The value it provides
| has to exceed that cost for it not to be a liability. Usually the
| main cost is that it is not as comprehensively documented as its
| creator imagines (if at all), and the user cannot trust what it
| will do without tracing through and understanding what details
| and pitfalls it hides. The more comprehensive its documentation,
| the more time it takes to read and understand, and the more
| likely it is to be, or later become, inaccurate.
|
| Thus, part of the job of every programmer is to distrust
| abstractions. An abstraction works on cases it has been seen to
| work on, but often cannot be trusted otherwise. This is what
| makes Standard Library abstractions valuable: you have confidence
| the implementation has been verified to match the specification,
| and the specification (1) has been carefully designed to avoid
| pitfalls and (2) documents them, where it cannot. J. Random
| Abstraction in your local library rarely gets that much
| attention.
|
| Make your abstractions earn their keep.
| Koshkin wrote:
| There is something about pointers. Pointers are special. But
| there isn't, and they aren't. They are types (or values) just
| like any others. In C++, you can say either auto p{...}; or
| auto* p{...}; and I always use the former in order to make code
| as much "abstract" as possible.
| ncmncm wrote:
| Every abstraction has a cost. If it is not delivering more
| value than that cost, it is a net liability. Saying "auto p =
| " when you could say "auto* p = " saves you practically
| nothing, but costs the reader, potentially, a lot. Somebody
| reading the code who doesn't instantly understand without a
| bunch of poking around that p has reference semantics is at a
| marked disadvantage. You have stolen that advantage from that
| reader.
|
| There is a reason that the language permits "auto& r = " and
| "auto* p = ". That reason is, specifically, to help prevent
| errors. Failing to spend a single keystroke to help prevent
| errors is false economy.
| Koshkin wrote:
| Except auto& does not prevent errors, and it is a source of
| innumerable problems, because '&' is too easy to forget.
|
| auto* does not add anything to making code more reliable,
| either; it just makes code tied to a particular
| implementation detail (e.g. I could redefine things using
| my own pointer-like object, and the * would simply stand in
| the way for no good reason whatsoever.)
| fluoridation wrote:
| I think ncmncm is a total scrub, but I will say two
| things:
|
| First, both adding an ampersand after auto when you
| shouldn't have and _not_ adding it when you should have
| can lead to logic errors of different kinds. Sometimes
| either one is fine, sometimes you _have_ to use the
| correct one.
|
| Second, auto * vs auto by itself has no effect on the
| generated code, but it _can_ lead to a more robust
| source. Imagine that you get a pointer from some function
| and you perform some operations with it, assuming it
| actually is a pointer in a way that would be invalid if
| it wasn 't. If the function signature later changes to
| return a pointer-like object, you'd want the compiler to
| give you an error to know to fix that code. In other
| words, you should use auto if you really don't care at
| all if the value is a pointer or not, and you should use
| auto * if you're assuming it's a pointer.
| ncmncm wrote:
| It has always been permitted to not make your code as
| clear as it could be, and always will be. Each of us may
| choose to help the person reading our code, but not all
| of us care to.
| fluoridation wrote:
| >A common example of a harmful abstraction, in C and C++, is a
| typedef of a pointer to an opaque name. The typedef conceals,
| when you read code using it, that the type is really a pointer,
| and so subject to all the excess operations provided for
| pointers in those languages. But one thing every C and C++
| programmer always needs to know about a type they are working
| with is whether it is a pointer.
|
| Nah, I don't agree at all. Renamed generic pointers are
| actually an extremely useful signal. They say "you should not
| concern yourself with what this pointer points to. You should
| only be using it through the library's functions. Do anything
| else with it at your own peril". Also, no, C and C++
| programmers don't really care whether a value of some novel
| type is actually a pointer or not (C++ programmers much less
| so). They only care about what size it is to know how to pass
| it around and whether it needs to be cleaned up in some
| specific way. If I tell you that when you're done with a
| fluor_t you should pass it to release_fluor(), do you need to
| know whether fluor_t is a pointer or a struct, or whether
| release_fluor() is a function or a macro?
| ncmncm wrote:
| Anywhere it would have been useful to "rename a pointer", it
| would be more useful to wrap it in a type that defines
| exactly the operations intended, and none that are not.
|
| If users have to call release_fluor(), your abstraction has
| failed to earn its keep.
| fluoridation wrote:
| Are you talking about a C or C++ API? If C++ then yes, I
| agree that would not be an idiomatic API. If C, then no,
| that's a perfectly typical API for the language.
| ncmncm wrote:
| If you will need to release it, then you also need to
| know it is a pointer that would afterward refer to freed
| storage.
|
| Programmers understand that referents of pointers have
| lifetime that must be managed. Hiding that quality of
| your special-snowflake type does nobody any good.
| fluoridation wrote:
| >If you will need to release it, then you also need to
| know it is a pointer that would afterward refer to freed
| storage.
|
| You really don't. If the documentation says that after
| calling release_fluor(), the fluor_t that was passed to
| it can't be passed to get_fluor_mass(), it doesn't matter
| whether fluor_t is a pointer or not.
|
| I'm sorry, but you're just plainly wrong.
| ncmncm wrote:
| If you are relying on everybody who reads code that uses
| your type to have thoroughly scoured all the
| documentation, you are Doing It Wrong.
|
| Programmers understand pointers and pointer semantics:
| when they see a pointer, they know what is required of
| them. An opaque type that has pointer semantics you can't
| tell without reading up on documentation is, exactly, an
| abstraction that costs more than it delivers.
| MaxBarraclough wrote:
| > If you are relying on everybody who reads code that
| uses your type to have thoroughly scoured all the
| documentation, you are Doing It Wrong.
|
| As fluoridation indicated, this is the norm in C
| programming. By means of example, in the OpenCL C
| library, bitfields all use the same type. You have to
| consult a function's documentation to know what you're
| allowed to pass. [0]
|
| I do agree that the 'Ada-style' approach to types is far
| superior to the 'C-style', but _Doing It Wrong_ seems a
| bit strong, unless you want to condemn all C code.
|
| With the right library you can use the 'Ada-style' in
| C++. Specifically, using a 'strong typedef' library which
| prevents implicit conversions, such as [1], but not
| Boost's _strong_typedef_ which permits implicit
| conversion back to the underlying type. Unfortunately
| this kind of thing isn 't possible in C.
|
| > Programmers understand pointers and pointer semantics:
| when they see a pointer, they know what is required of
| them
|
| Not really. Should you call _free_ on the pointer once
| you 're done with it? The type alone doesn't tell you.
| You need to consult the documentation to know how you are
| meant to use the value, whether or not a pointer type is
| used.
|
| [0] https://www.khronos.org/registry/OpenCL/specs/2.2/htm
| l/OpenC...
|
| [1] https://github.com/foonathan/type_safe/
| fluoridation wrote:
| Okay. Have fun using C APIs without reading documentation
| and wondering why your programs keep crashing, I guess.
| What else can I say?
| ncmncm wrote:
| I know why programs _other people_ write keep crashing.
| They are coding them in C (or bad C++; but I repeat
| myself), and are relying on abstractions that conceal
| exactly that which they should instead expose.
| wvenable wrote:
| Maybe the data type isn't a pointer, maybe it's an
| integer handle to a kernel object. And you may still need
| to free/release it even though it's not a pointer at all.
|
| There are plenty of APIs that have similar semantics
| (connect/disconnect) that must be followed. And even if
| something _is_ a pointer doesn 't mean you can just
| free() it -- you might need to use whatever method the
| API provides to get proper operation.
|
| This is the main abstraction mechanism in C programs --
| the abstract data type. A piece of data you pass around
| but never know the innards of.
| ncmncm wrote:
| File descriptors are an example of such a type. In good
| code they are carefully kept equal to -1 when not open,
| and are carefully identified, and not leaked.
|
| When something has reference semantics but isn't an
| actual pointer, that is an extra fact that the reader of
| code needs to know in order to reason correctly about it.
| That is, thus, a burden above what would be needed for an
| actual pointer. It is a burden that is harmful to impose
| entirely unnecessarily.
| Koshkin wrote:
| Pointers aren't special, and memory is not the only
| resource that requires managing.
| 4fips wrote:
| Yeah, for example passing such an opaque typedef as const is a
| common trap and very often source of surprise (even for the
| author of the API), something like: struct
| Opaque { int data; }; typedef
| Opaque *OpaqueRef; void bar(const OpaqueRef ref) {
| ref->data = 42; // compiles fine, ref is 'Opaque *const'
| } void baz(const Opaque *ref) {
| ref->data = 42; // does not compile, ref is 'const Opaque *'
| }
| mannykannot wrote:
| I feel that a large fraction of the complexity of C++ comes
| from the imperative to abstract away the 'pointerliness' of
| pointers. If I have understood the article correctly, it is an
| example of abstraction by anti-unification (over pointer and
| value-semantic variables), and it works very well in the
| Standard Library.
|
| In this view, there is something ironic about how many of the
| complexities of the language came about to enable the
| abstractions of the Standard Library, which greatly simplify
| writing applications in the language!
| ncmncm wrote:
| There is nothing ironic about a language that provides
| unlimited power, including the ability to restrict the power
| of things built with it. That is the whole point of language
| design. At least, languages meant for professionals.
|
| Many languages have strictly limited power, in order to keep
| non-professionals from getting into trouble.
| Koshkin wrote:
| This is a novel approach to designing a programming language
| that, I believe, came along with C. Older languages, like,
| for example, PL/I, tended to put much of the standard
| functionality in the language itself; C, C++, Haskell, etc.,
| on the other hand, decided to externalize everything except
| for the "core" facilities; the benefit of this is of course
| that a developer can now, theoretically, use the language to
| implement anything, but that comes at the expense of the
| language being conceptually more complex. (Even a simple
| language like C is considered complex by many due to its
| excessive reliance on the use of pointers and the manual
| memory management.)
| chakkepolja wrote:
| and disadvantages being it will be never as clean, as
| easily optimizable or debuggable, as the one implemented in
| language.
|
| UFCS is better than C++ ranges. builtin sum types are
| better than std::variant, etc..
| ncmncm wrote:
| Something that showed up in 1972 cannot still be called
| "novel" 50 years later.
| badsectoracula wrote:
| > A common example of a harmful abstraction, in C and C++, is a
| typedef of a pointer to an opaque name. The typedef conceals,
| when you read code using it, that the type is really a pointer,
| and so subject to all the excess operations provided for
| pointers in those languages. But one thing every C and C++
| programmer always needs to know about a type they are working
| with is whether it is a pointer.
|
| C (and C++) programmers only need to know if a type is a
| pointer if they are meant to know it is a pointer. Otherwise
| very often a foo_t is meant to be used via manipulation
| functions and it being a pointer or an integer or whatever else
| is a detail that the programmers do not need to care about.
| This is a very common approach for libraries when trying to
| make a shared library with a stable ABI, though it is also
| common when you want to isolate accessing the underlying data
| of whatever a "foo_t" represents to a single known module.
|
| Often you see "foo_t*" instead of "foo_t" (with foo_t being an
| undefined struct) but with "foo_t" being unusable by itself it
| is always stored and passed around as a pointer and thus the
| same -incredibly few and irrelevant in practice- pitfalls would
| apply anyway, so in reality it all boils down to personal
| stylistic preference if you want to litter all those stars in a
| project or not. Personal preferences like that have nothing to
| do with youthfulness or even experience.
| ncmncm wrote:
| I.e., you lack the experience to understand that concealing
| pointer semantics of a type is harmful.
| badsectoracula wrote:
| > I.e., you lack the experience to understand that
| concealing pointer semantics of a type is harmful.
|
| I have been working with C codebases for decades and have
| more than enough experience thank you.
|
| You didn't really reply to what i wrote though.
| ncmncm wrote:
| Suffice to say, there is way too much bad code out there,
| and we all pay.
| criddell wrote:
| Are HANDLEs as used by Win32 an example of what you are
| talking about? They may be implemented as a pointer to
| something, but that's not how you use it.
| ncmncm wrote:
| Yes, HANDLEs are the worst kind of abstraction: they hide
| everything you need to know, and provide no corresponding
| benefit.
| Koshkin wrote:
| Believe me, you do not _want_ to know what is hidden
| behind a HANDLE!
| mattgreenrocks wrote:
| The nice thing about a HANDLE is they can be a pointer to
| kernel space, a pointer to something in user space, or an
| opaque index into an internal table of managed resources.
| If it was a pure pointer, then 0 has to be avoided as it
| can be mistaken for "no value" by users. Of course, you
| replace that with knowing to check for
| INVALID_HANDLE_VALUE.
|
| IMO, HANDLEs are probably a bit too opaque for my taste,
| as you have to know what operations you should be using
| with them. I'd prefer opaque structs if I had to choose.
| ncmncm wrote:
| I don't even want a HANDLE.
| userbinator wrote:
| In my experience, beginners tend to underabstract, and it's the
| intermediately-experienced ones that go too far in the other
| direction. The most experienced ones are somewhere in the
| middle and closer to using abstractions where they make sense.
| Unfortunately, the majority of the community and industry is in
| the middle group.
| ratww wrote:
| Yep, my experience as well. I'd say (in keeping with the
| article's terms) that the intermediately-experienced tend to
| overuse indirection, but underuse abstraction.
| ncmncm wrote:
| "the majority of the community and industry is in the middle
| group"
|
| I.e., "intermediately-experienced" and younger than the "most
| experienced". As I said. You are unlikely to find yourself
| relying on a library written by a beginner.
| eternityforest wrote:
| This is really interesting!
|
| Encapsulation might be a more appropriate word in most cases,
| since abstraction doesn't tell you what specifically you're
| abstracting away from.
|
| Coming from OOP, I've always thought of abstraction as just "A
| thing that hides the real nature of something and presents it as
| a standard and simplified model, and lets you ignore more things
| than the non-abstract truth allows".
|
| drawImage(file, x, y) is an abstraction, because I don't need to
| know how it works or how it knows what decoder to use.
|
| One might even say a toilet is an abstraction because what goes
| into it is(Presumably) dealt with in a sanitary manner by
| professionals.
|
| Things like monads and composition are abstractions in the
| colloquial sense, objects far from some concrete thing like a car
| or a pen, but using them effectively requires understanding the
| logic, so in a sense they are leaky, because the act of using
| them "leaks" the mathematical logic, and subjectively nothing
| like that comes to mind when I think of abstractions in
| programming.
|
| They're definitely abstractions, but they are used to reveal and
| illuminate a program's structure, not to hide it in a black box.
| reidjs wrote:
| > They're definitely abstractions, but they are used to reveal
| and illuminate a program's structure, not to hide it in a black
| box.
|
| In my mind, abstractions are used to reveal the program's
| interface and intent more than its structure. The functions,
| data structures, variables, and ultimately the source code
| reveal the program's true structure.
___________________________________________________________________
(page generated 2022-03-30 23:01 UTC)