Why isn’t software abstract on a grander scale

abstraction

Consider the following example:

The user wants a program to calculate a few fibonacci numbers.
Sounds easy enough. pseudocode:

stdout.write("How many fibonacci numbers do you want to calculate? ")
int count = int(stdin.readline())
while count>0:
    stdout.writeline(calculate_next_fibonacci_number())
    count--

Even a very simple program like this is already flawed:

  • The program writes to stdout. That is not actually what the programmer intended, is it? The intention is to display a bunch of number to the user, not to write some text to stdout – there's no guarantee the user will ever see the text that's written to stdout.
  • Similarly, the user input is read from stdin, which is a text (or file, if you prefer) interface, when in reality, the program requires a number, not text. This seems fundamentally wrong.

Let's think about what we're trying to do more abstractly. We want to:

  • Calculate a bunch of numbers. How many is up to the user.
  • display the results to the user.

Why, then, don't we write code exactly like that?
(Most) programming languages provide this thing called a "function", which accepts parameters and uses them to do something. Does that not sound exactly like what we're trying to do?

void display_fibonacci_numbers(
        int number "how many fibonacci numbers to calculate"):

        Sequence<int> numbers
        while number>0:
            numbers.append(calculate_next_fibonacci_number())
            number--

        notify(numbers)

display_fibonacci_numbers()

This code is, of course, incomplete – the notify function isn't implemented anywhere, and the user needs some way of inputting a number. I would imagine the user's operating system or desktop manager or whatever to take care of that – it could display a terminal, it could generate a GUI, it could tell the user do write the number into the air with his nose; either way it does not (should not) concern me, the programmer.


It is my belief that software should be more abstract.

A few more examples.

  • inter-process communication. How do you do it? Sockets? Signals? DBus? Files? The goal isn't to use sockets, signals or dbus, it's to communicate with another process. Why not something like Process.from_name("Music player").play_random_song()?
  • Downloading files. local_file.write(remote_file.read())? Why not download(url), which could, depending on the system configuration, start the download right away, but with a low priority so as not to slow down other downloads, or add it to the download queue to be downloaded later, or whatever?
  • File paths. Why on earth are file paths still strings (in most languages, at least)? Why do we have to deal with whether the path separator is / or \, whether it's ., .., or whatever? Why is there no FilePath class that takes care of this?

Going a step further, why not apply the duck-typing concept to modules? For example, in python, HTML is often parsed using the beautifulsoup module:

from bs4 import BeautifulSoup

page= BeautifulSoup(urlopen('http://test.at'))

Again, the programmer's goal wasn't to use BeautifulSoup, but to parse HTML. Why, then, would he explicitly tell his code to use the BeautifulSoup module? What he really wants is to

import HTMLParser
page= HTMLParser.parse(urlopen('http://test.at'))

Duck-typing for modules: Who cares what module it is as long as it does what I want?


Why is programming not like this? Am I overlooking something, something that makes all this impossible (or impractical)?

Best Answer

Why is programming not like this?

Why do you think that? Actually, programming is like that. Of course, you can't do that in assembler. Therefore we invented languages that can be more similiar to the human thoughts.

Good programmers program alike examples you gave. But it is not as easy. First you have to understand, what the requirement is. This is hard enough already and most people can't elaborate correctly what they need - therefore a good software designer needs to actually understand what people want, not what they tell.

After that is done you need to see the concepts behind the real world things. That is quite philosophical and needs much experience. And then, after this is done, you have to translate these results into a language of your choice, working around the incapabilities that every language has and choose the correct abstraction level (you don't want to overengeneer anything right?).

Not all people are good at these steps or even aware of them. Even in small examples one can see that it is not trivial. Let's take your display_fibonacci_numbers function and see what we can improve there (even though its not codereview.stackexchange here).

void display_fibonacci_numbers(

The naming is actually not very precise because you are very specified in the kind of numbers you will display right? That should be described by the function name.

    int number "how many fibonacci numbers to calculate"):

Why is it an int? That is waaay to concrete and even wrong, because ints can of course have negative values right? So what you might really want is a type that can be used for calculating the fibonacci numbers. Maybe a natural number?

    Sequence<int> numbers
    while number>0:
        numbers.append(calculate_next_fibonacci_number())
        number--

Does that really describe what you intend to do? In natural language (which is often a good approximation) we would say "create a list of the specified number of fibonacci numbers". I can't read anything about decrementing a number here, I can't read anything about a static 0 value here. Also nothing about a "calculate_next_fibonacci_number()" function.

Therefore, in Scala I would e.g. write the code as List.fill(number)(randomFibonacci())

It does not read exactly as in natural language, but it at least contains the same information.

I wanted to give you these examples to show you, that it is hard to write software that way. You need to have experiences, spent good amounts of time to think about things, be able to find the correct concepts and abstractions and THEN have a language that does not hinder you to express them in a concise way. This is, why not many people program like that. And even worse: humans get used to things. So if one always programs in a language that hinders him in doing the last step, he will maybe continue to program in a new language as in the old one.

Related Topic