Thursday, 5 June 2014

Unnecessary Complexity

My entry for the 'What Dave doesn't like about modern life' round on Room 101 would be Unnecessary Complexity. By that I mean that things seem to become more complex all the time, just because they can. The example I usually give is word processors. I remember writing my university dissertation on a BBC Micro, using Wordwise. That was fine, it did the job, all that was needed really.
Later onto a DOS PC running Protext, again, did the job, added a few whizzy features like fonts and bold / italic, although they were more a feature of the printer than the word processor itself. Later again Microsoft Word on Windows 95. WYSIWYG editor, so it looked lot fancier. More fonts, more effects. Today I'm using Office 2010 on Windows 7. Even more fonts, even more features and buttons I never press.

The final step is Office 365 on Windows 8, and I've seen a lot of people stare at that very confused, because they have somehow managed to overcomplicate it even more by trying to make it simple.

But at the end of the day, all these things basically do the same job, type in some text, modify it, save it and print it. And bring in all the new feature like autocorrecting words (you might not want autocorrecting), autocapitalising (how many times have you missed the 't' out of 'it' and gone back to find the I had been capitalised?). Lets' not mention the office paperclip.
Wordwise ran on the 2MHz BBC in 32K (well, more like 20K if you remove screen RAM etc.). Protext runs in 640K on the 8MHz PC. Word 6 runs in 32MB on the 200MHz PC. Office 2010 is running on a 16GB machine with a quad core 3.1GHz processor. But they are all doing basically the same job, and actually the old ones are sometimes easier to use.

I came across another example yesterday, when talking about approaches to averaging. When you have a limited resolution reading, you can improve it by taking a number of them and averaging the readings. I used this approach for the temperature sensor on the LCD Clocks.
A very efficient way, suggested by a friend, is written in assembler. Take the 8 bit readings and add repeatedly to a 16 bit register, and at the same time increment an 8 bit register. Every 256 readings, the 8 bit register overflows. When that happens, take the top byte of the 16 bit register. Then clear the register and start again. This is a very efficient way of taking 256 readings and dividing by 256.

A little less efficient is the way I do it in C code for the LCD clock is to create an array of 100 bytes, each reading, set an array entry, increment the index, if it's at the end, move it back to the start. Then go through the whole array, adding the values to a floating point number and dividing by the number of readings. Less efficient, but it achieves the same thing.

In a desktop application, I need to do a similar thing to average readings on a chart, but here I'm writing in C#, and using the .net framework linq library. I create a linked list of readings, each time I add a reading, I go through the list removing any entries over a particular age. Then use the built in averaging of the linked list to get the average. This is a lot less efficient in terms of memory and processing.
All three of those involved probably a dozen lines of code in their relative language, and they are achieving the same thing, but the amount of code generated and complexity is increasing each time. The assembler version uses a couple of registers and no memory. The C version uses 101 bytes, the C# version uses considerably more for a linked list of floats,  but the code, memory and processing requirements are a drop in the ocean on a modern PC. The new code has lots of inbuilt safety checks, the old code relied on the author getting it right.

I think that is why I like working with vintage computers and amplifiers and things like that because the beauty in simplicity is thrown into sharper focus against the complexity of their modern equivalents. Older amplifiers had several transistors, modern ones have several thousand. The BBC's 6502 had 3510 transistors, where as the i5 in here has about 2 billion.