0

I know this is a very basic topic, but I'm curious why an abstraction in programming is always defined as a simplification/hiding of some functionality. Let's say I wrote a set of functions that let me use some functionality in some more convenient way, but I didn't exactly simplify anything, just transformed it. Wouldn't this also be called an abstraction? If no how would be this concept called?

5
  • Is there a fundamental difference between "more convenient" and "simpler"?
    – IMSoP
    Feb 7, 2021 at 10:49
  • @IMSoP Well, I think there is a difference in terms of the code. For me "simpler" means that there is some logic in the code that makes is "simpler", but for something to be "more convenient" no processing is needed, just transforming what's there. Feb 7, 2021 at 10:53
  • What you describe is often called a wrapper. Or a facade or a proxy. Feb 7, 2021 at 11:29
  • Abstraction is a concept that exists in many different disciplines other than programming, and can appear in different forms; you'll often find it described in terms of simplification/hiding/ignoring irrelevant details, but it's important to point out the flip side of that: you're also defining what details or aspects, in your view/approach, are relevant to the problem. And that's perhaps even more important - this is what allows you to be more precise, more expressive and suitably concise. Defining a set of functions (+ the semantics associated with them) is a way of doing that. Feb 7, 2021 at 12:56
  • 3
    Does this answer your question? What is abstraction?
    – Christophe
    Feb 7, 2021 at 13:09

2 Answers 2

7

Probably an example could help.

Let's say you want to do an HTTP request to an API and process its JSON response. Such process involves, at software level:

  • Doing a DNS request in order to transform the URI to an IP address.
  • Creating a socket.
  • Forming an actual HTTP request with the appropriate HTTP headers.
  • Dealing with TLS, which involves certificates and plenty of other things.
  • Sending the request through the socket and receiving the answer.
  • Parsing the answer, checking specifically whether the HTTP response is two-hundred something or not.
  • If HTTP response is three-hundred, deal with redirection.
  • On success, extract the JSON response.
  • Parse JSON.

You can do all this yourself, if you have the skills. Or you can leverage the abstraction of different third-party libraries to do all that for you. In Python, for instance, all those steps can be done in two lines of code with the requests library, which is an abstraction. The library itself uses other abstractions: for instance, it doesn't deal with TLS and certificates, but uses other libraries for that.

Another example: writing a file. When you write a file (would it be through your code, or with a text editor), you use abstractions: you don't necessarily want to know if the file is written to a ramdisk, or to a hard disk, or an NFS share. Those three variants involve very different steps—writing to NFS is not at all the same as writing to local disk. Nevertheless, all three appear the same to you, because the underlying details are put behind an abstraction.

Note, by the way, that most abstractions are leaky—this is a major issue of abstractions. For instance, as a user of the requests library, you are tempted to forget that under the abstraction, there are all those steps involved, but the abstraction will leak as soon as, for instance, your corporate DNS server is down. Or there is a problem with the certificate. Or the connection takes too long. Or you reached the number of maximum sockets. Same when you write a file: if you add a firewall rule which blocks access to NFS, the operation of writing a file will fail if the target is an NFS share. Suddenly, the abstraction leaks, and you need to know what's behind the abstraction in order to fix the issue.

To better illustrate my concern I will use the example you gave. Let's say I use a library that can "do a HTTP request to an API and process its JSON response". But very often I call this function without passing any body, just the headers, so I wrote another function, which calls this function and passes null as body. Would this also be an abstraction? I don't feel like I've simplified anything, just transformed it.

It's all about hiding something behind an abstraction. If the original function is requests.get, and yours is requests.get_without_body, then there is no abstraction there: you haven't hidden anything. If, on the other hand, you have your business layer, and inside you have a function get_products, which calls requests.get with the specific headers and without a body, then suddenly you created an abstraction: the caller doesn't know if you do an HTTP request, or query a database, or do something else.

A good abstraction allows to change the underlying mechanism without changing the interface. For instance, if you add caching, requests.get_without_body would have to be renamed to requests.get_without_body_and_with_local_cache, whereas get_products will keep its signature: only the implementation will change. Similarly, if you need to switch from HTTP to SQL, you'll have to replace requests.get_without_body, whereas get_products will still do the job.

3
  • Thanks for the answer! To better illustrate my concern I will use the example you gave. Let's say I use a library that can "do a HTTP request to an API and process its JSON response". But very often I call this function without passing any body, just the headers, so I wrote another function, which calls this function and passes null as body. Would this also be an abstraction? I don't feel like I've simplified anything, just transformed it. Feb 7, 2021 at 10:58
  • The library is the abstraction. Both functions are backed by the same abstraction. Anyways, you could edit the question and add code to illustrate your doubts. Overloading functions is not the kind of abstraction Arseni is treating in his answer (IMO).
    – Laiv
    Feb 7, 2021 at 11:17
  • @WojtekWencel: I edited my answer. Feb 7, 2021 at 11:17
0

Please check "The Discipline of Organizing", Section 10.3.2.3 Granularity and Abstraction.

The level of abstraction is the degree to which a resource description is abstracted from the concrete use case in order to fit a wider range of resources. For example, many countries have an address field called state, but in some countries, a similar regional division is called province. In order to accommodate both concepts, we can abstract from the original concrete concepts and establish a more abstract description of administrative region.

Also check Chapter 4 or A Philosophy of Software Design by John Ousterhout.

The term abstraction is closely related to the idea of modular design. ... In modular programming, each module provides an abstraction in form of its interface. ... The best modules are those that provide powerful functionality yet have simple interfaces.

The interface is a mechanism to achieve abstraction. We encapsulate module capability and only expose an abstract interface.

Below are some abstraction mechanisms:

  • Declarative: what, not how.
  • Aggregation: container, not contents
  • Generalization: class, not Individuals
  • Parameterization: binding details later
  • Nondeterminism: leaving Choices unspecified
New contributor
Ahmad Ismail is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.