ntoll.org

(Everything I say is false...)

Programming ~ Concise and Simple

Wednesday 30th January 2013 (08:00AM)

(As with all "concise and simple"
articles I assume no prior knowledge of the subject and keep the length to
less than 1500 words.)

This is a personal reflection on programming: the creation and curation of
instructions that make computers do things. Instructions (also known as
"source code" or just
"code") are organised into
programs (or
"software") that fulfil
specific tasks. People who write programs are called
programmers,
developers, software engineers or (colloquially)
hackers.

Instructions are expressed in
programming languages
that make it easier for humans to comprehend what is going on. So-called "high
level" languages are easier for humans to work with than "low level" languages
that express things in a way that is closer to how the computer works. In
all cases programs are transformed from the original programming language into
the binary
instructions that cause the computer to function in a particular way.
This transformation can happen in two ways:

The program is "compiled" in to binary instructions by a special
program called a
compiler. The result
is an "executable"
run by the end user.

The program is "interpreted" by an executableinterpreter
whose function is to act as a sort of on-the-fly translator of the
instructions.

Both mechanisms have strengths and weaknesses. Because compiled programs
have already been transformed in to the computer's binary instructions they
are often much faster than interpreted programs where such
transformations happen as the program is running. Yet interpreted programs
offer the flexibility of adapting and changing themselves while they are run by
the interpreter which makes it easier to solve certain sorts of programming
problem. Sometimes a combination of these techniques is used:
A JIT
compiler will interpret until certain sets of instructions are
obviously more frequently used, at which point only the popular sets of
instructions get compiled "just in time" to make them faster.

Sometimes programs work as expected and produce valuable results. More often
they do not. The failure to make a computer work usefully is called a
bug.
There are generally two sorts of bug: the wrong outcome is correctly
implemented (the design is wrong) or the expected outcome is wrongly
implemented (the instructions are wrong). In any case, because computers are
complex machines, making them do something useful is surprisingly hard.

Managing and taming complexity is one of the core tasks of a programmer. A
common piece of advice given to junior developers is
"kiss"
(keep it simple, stupid!), for there are fewer things that could go wrong. As
computing pioneer Tony
Hoare explains,

"There are two ways of constructing a software design: One way is
to make it so simple that there are obviously no deficiencies, and the other
way is to make it so complicated that there are no obvious deficiencies. The
first method is far more difficult."

Personally, I think creating simple and useful software is more like
writing succinct yet powerful prose than opaque logical wizardry. This has
an important side effect: simple and coherent code is easy to understand. Code
that is easy to understand is easy to maintain. Maintaining code is the act of
fixing bugs and curating instructions so things work efficiently (also known
as re-factoring).
In this way a program is easy to improve as bugs are found and new features
implemented.

Some languages have been created with the explicit aim of making code
easy to read and understand (such as Python).
Some developers promote certain development styles that they claim encourages
programmers to produce high quality software. A classic example of this is
test driven
development where developers write a failing test encapsulating a feature
of their program before actually implementing the feature itself to make the
test eventually pass. Others (such as
Donald Knuth)
promote a
literate style of
programming where code is interspersed with natural language explanations
that tell the "story" of the code.

Another core skill of a programmer is de-constructing and analysing
problems. Often the problem is expressed in a
vague and open-ended way and it is the task of the developer to precisely
constrain the scope of the problem so they create some
useful outcome. A personal example, from my first programming class, illustrates
this beautifully: my tutor explained that programs were merely instructions
and that we had five minutes to provide instructions telling him how to switch
on the classroom's lights. How hard could it be to write such
instructions? Take a minute to imagine what you would write (you
may assume that the person following them knows about directions, actions and
names of things).

I can still remember my list:

Stand up.

Look around until you locate the light switch.

Walk in the direction of the switch.

Press the switch with your fingers.

Retrace your steps.

Sit down.

Of course, I failed miserably. My tutor pointed out that he was already
stood up, there were desks between him and the light switch and the damn lights
were already on anyway.

Time and resources are also essential elements of software development:

First, the developer needs to have a feel of how best to organise a
program. This means analysing their implementation of the
algorithm (the
instructions at a conceptual level) to ensure that it is both timely and makes
efficient use of resources like the computer's memory and
CPU. Often
this is expressed using big-O notation.

Second, programming usually involves a deadline. Customers need to know how
much time it will take to finish software given a certain number of developers
and some sort of collaborative development process. I've heard this described
as "the cat herding problem". Fred Brooks
famously observed
that adding developers to a struggling project only slows it down further.
Furthermore, clients change their minds mid-project (in addition to providing
vague problems like the one mentioned above) and there are always
unknown
unknowns that add unforeseen time and effort to the project. If this were
not enough, how do you coordinate teams of programmers who are all working on
the same software? It's like trying to get ten people to co-compose a symphony
at the same time.

Happily, developers have created methods and tools to help them work
together. Small autonomous
"agile"
teams are preferred over large managed cohorts of developers.
Issue tracking
systems make it easy for clients to request and prioritise features,
report bugs and give developers a clear audit trail upon which to base
development decisions. Code is stored in
version control
systems that allow developers to track each other's changes and
resolve any conflicts in the software (for example, when two people edit the
same piece of code). In fact, developers have become so good at this sort of
thing that others borrow these tools and techniques: lawyers have been known to
collaborate on complex legal documents with a version control system.

Finally, programming is a political activity: making software
means defining the laws that dictate how the digital world should be. Often
this obvious fact is left unacknowledged. However, incumbent interests affected
by the rise of digital culture (for example, the so-called "creative"
industries represented by organisations such as the
RIAA,
MPAA and their ilk)
have attempted, with some success, to change the law to limit the use of file
sharing software used to distribute pirated content.

The freedom to study how the program works, and change it so it does
your computing as you wish (freedom 1). Access to the source code is a
precondition for this.

The freedom to redistribute copies so you can help your neighbor
(freedom 2).

The freedom to distribute copies of your modified versions to others
(freedom 3). By doing this you can give the whole community a chance to
benefit from your changes. Access to the source code is a precondition for
this.

These freedoms are enshrined in the
General Public License (GPL) -
a license that subverts copyright (that seeks to
expand the rights
of creators at the expense of the rights of others) in to
copyleft (that
seeks to expand the
rights of everyone). There is one important exception that limits
everyone: any modifications to source code covered by the GPL must also be
freely available under the GPL. While the GPL has been described as
communist and
cancerous
it is not anti-commerce and (I think intentionally) does not mention any
political affiliations. Code covered by the GPL can be sold (see sections
10 and
11). It's how the FSF
first raised money for their cause.