display | more...

The act of programming a piece of (usually) existing code when one does not fully understand the language, algorithms or assumptions used to create the code in the first place. Often done by novice programmers to twiddle a feature or try to fix a bug in a large complex project.

Each line of code balances on a knife-edge of assumptions. It has been placed there carefully by a skilled programmer that had to keep about a thousand little details (assumptions) in mind when writing that particular line of code. Some assumptions are critically important so they are manifest in the use of the "assert" macro just to make sure that the programmer (or more often other programmers) do not forget that "here" things must be just so or disaster will strike.

Other assumptions are made so that the program will run faster. For example, you could recompute the digits of Pi from basic principles each time you needed it. But it is faster just to assume that Pi is 3.14159... and use the constant value instead of the computed value.

Assumptions are made when things are static. The duration of this condition depends on the algorithms. Some data is only static for a few microseconds (a couple of lines of code) so the assumption can be quickly dismissed as trivial. Other assumptions can be made for the duration of the program and have a larger influence. And, in every other case in between, assumptions are at the "heart" of each step in the program.

Then some young, wide-eyed, know-it-all, hack comes along and thinks: "I know what I’m doing" and starts changing code at random failing to consider the consequences of his actions completely disregarding the careful tapestry of assumptions the original programmer has laid. And, presto, you’ve got bugs coming out the wazoo.

I must thank wamckee for a most excellent and thought provoking node title.

Programming by approximation - what does it mean?

We tend to think of programming as an exact science. However, ongoing trends are increasingly making this not the case. But this is part of a continuous process of cutting the human out of the loop. Whether the end goal of removing the human completely, will ever be achieved is a big subject of debate.

Getting it right first time

The first programs written by me were entered into the computer using punched cards. Any errors in the code needed replacement cards. We also had a 24 hour batch turnaround cycle. This meant that much of the intervening time between runs was spent pouring over listings, trying to imagine and predict what the computer was going to do.

The primary consideration in the philosophy of Getting it right first time is: what is the cost of a mistake? There is a tradeoff between how long we spend on going for perfection, and how much time is taken to fix bugs. In the early days of punched cards, bugs were very expensive, both in terms of human time and elapsed time.

The technology is improving all the time, and is enabling us to use approximation, and hence save us having to be perfectionists.

Abstraction

Each step of assembly language, high level language, metadata, etc. is taking us further away from the 1's and 0's of what is happening. Abstraction also underlies Object Orientated Programming, and use of design patterns takes this a step further. Methodologies provide another form of abstraction, relating to the design process.

Abstraction saves the human having to worry about fine detail, and hence reduces the likelihood of making mistakes. Greater degrees of automation also help.

Prototyping

In recent methodologies such as evolutionary delivery and extreme programming, the whole application exists right from the start of the development cycle. It exists, but it does not work yet. The application exists as requirements documents, These are broken down into modules as part of the design process, and at the same time unit tests are built in for each module. If this is in place first, it is much easier to guarantee what needs to be delivered.

This means that prototype applications can be delivered to the users incomplete - often before the users have worked out properly what they wanted.

Fault Tolerance

Although this is primarily applied to hardware design, the space program showed how majority voting algorithms could be applied to software. A majority of several machines have to agree on the answer for it to be accepted. The dissent is recorded and analyzed after the event.

Emergent Algorithms

The use of genetic algorithms, classifier systems and neural networks means that the human has even less to do. The human provides a training set, which comprises sets of data - which are really the expected results, input and output, together with a fitness function to evaluate how well the software performs - how far away from the goal. The internal storage of the emergent algorithm is randomly seeded, and it is made to grow some code.

Despite the apparent sci-fi feel of emergence, much use has been made in the fields of pattern recognition and image processing.

Sources:

  • Artificial Life : Stephen Levy. ISBN: 0140231056
  • Principles of Software Engineering Management : Tom Gilb. ISBN: 0201192462

Log in or register to write something here or to contact authors.