November 15, 2006
Simplicity isn't easy to achieve, and John Maeda's short book, The Laws of Simplicity, provokes a lot of thought on the topic.
Programmers swim in a sea of unending complexity. We get so used to complexity as an ambient norm that we begin, consciously or unconsciously, projecting it into our work. Simplicity is tough in any field, but in ours, we exacerbate the problem. Impossibly complex applications are the default deliverable for new programmers. Only seasoned software development veterans are capable of producing applications that are easy to understand and troubleshoot. Simplicity isn't achievable as a passive goal; it's a force that must be actively applied.
You can read most of the book online via John's excellent blog, including abbreviated versions of the ten laws of simplicity. One of my favorite sections is about the evolution of the iPod's controls.
Keep it Simple, Stupid. If only it was that easy. It feels more like back-breaking work to keep things from inevitably devolving into complexity.
Posted by Jeff Atwood
A technique I use when I think I'm overcomplicating issues (usually after much frustration) is to ask a non-programmer. Find someone that is relatively techno-savvy and present them the problem in a jargon-less way.
I typically get a very simple answer, as they are almost like children in their response. They are honest because they have nothing to lose and don't know any better -- that is exactly what I need and use to create some of the "best" applications I've made. Simple people have simple ideas.
Thinking as an observer is extremely hard, especially when you're in the zone. So when you can't do it, you need to find a real observer and ask them.
When something quits working, always make sure it is plugged in BEFORE you start to troubleshoot the insides. Don't assume it is a complex problem.
This topic is way overdue. There was a certain beauty to coding procedural code in say, Turbo Pascal.
Complex development UIs, event driven programming, UI concerns, fighting with OS and tool updates and bugs, plus dozens of new supporting technologies to learn seem to compete with the need to design the core of the system well.
Have we all been duped?
I read once a book that is no longer available that gave the following example:
You have a rectangle circle and a triangle.
How do you tell the computer to place the circle above the rectangle and the triangle above the circle ?
Most of the developers try to solve this example, always complex things too much, and unable to solve this simple "problem".
I'm reminded of an ACM programming race in which the assignment was to print out roman numerals for a range of numbers just large enough that an elegant algorithm would be a challenge of an hour or so. The team that won typed in a string lookup table and fools out of everybody else.
Why does this form hate b-l-o-g-s-p-o-t?
i don't think there is anything simple in a programmers life or else the logic may not work
*Sigh* Wish SUN had read that book when laying the API foundations for Java. For some reason, solving a problem in this domain strikes me as much harder than any other - almost as if complexity was a design goal. 16.000 classes and still no datepicker.
Another key principle for writing maintainable code is DRY: "Don't Repeat Yourself" (http://en.wikipedia.org/wiki/Don't_repeat_yourself). One of the challenges to Keeping it Simple, however, is the DRY KISS dilemma. Eliminating redundancy often requires adding complexity. And conversely, one can sometimes significantly simplify a system by selectively allowing duplication.
Ah, if only we could persuade our customers to simplify their business processes rather than having to automate their existing complexity...
But Don, a plane is subject to strict regulations, documentation requirements, tests, certifications, maintenance sessions and inspections. Its domain is non-negotiable, it needs to be able to withstand heavy stress, cope with bad weather, a busy life in service etc. Yet, planes too are faulty and when it happens it often results in catastrophic accidents. The contrast is stark; the lifecycle and manufacturing process of a plane and its components is well understood. This is rarely the case for software.
OK, so let's consider the example of 20 constructors. That suggests 20 reasonable ways to create an object of that type. If .NET supplies one way, then I suspect that .NET developers will need to write extra code in 19 out 20 scenarios - I'm not claiming that all scenarios are equally likely, just that they exist.
Which code is likely to be more robust - the written once, used heavily .NET code or the many sections of code written by many different developers, and used lightly?
Personally, I find it easier to find the exact function I want rather than write extra code. If someone prefers fewer choices, then they can always select one and use that for all cases they have.
Simplicity is something I try to always keep in mind. Whether I'm designing a large library or engine, or an end-user application, things should be easy to use, but still as functional as possible.
When I just got into 'this simplicity thing', I found myself rewriting a lot of code, just to make it simple.
Something that I see a lot is that people often (seem to) consider simplicity the same as minimalism, but I don't agree with that. It's possible to have a large function/application/algorithm/... that is still easy to understand.
Unfortunately complexity isn't always evitable.
Talking about simplicity, the "Getting Real" methodology (http://gettingreal.37signals.com/toc.php) kicks arse.
From what I can see on the blog (and many of the Amazon reviews suggest this book is disappointing)
I think Donald Norman tackles this material in a much better fashion in his "The Design of Everyday Things" which is the same book as "The Psychology of Everyday Things". He tackles how to make usage obvious, trade-offs between having knowledge in the world versus in one's head, interfaces as analogies, making things discoverable, etc. In the IPod article John Maeda says Apple has achieved an "over simple" design. He ought to have described that as a maximally simple design -- over simple would mean important aspects were missing.
FIRST SAINT-EXUPERY QUOTE OF THE THREAD.
"A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away."
- Antoine de Saint-Exupery
It's low-hanging fruit but had to get it in there before anyone else. :-)
FWIW, I felt this quote was true of software the first time I read it. There was no moment of disbelief or skeptical evaluation. Straight away I knew it was good advice for software design. Of course, knowing the path and walking the path...
There is a key balance that must be struck between complexity and simplicity in software. Complexity is a necessary evil, but it is only necessary if a simpler solution does not exist.
This is captured in the law of irreduceable complexity...the classic example being the mousetrap. It cannot be made simpler, therefore it is an irreduceable design: hence the saying "You cannot build a better mousetrap."
Software is no different, the best design is one that is only as complex as necessary to meet its functional requirements.
As a sidenote, reducing complexity in software is called "refactoring".
What is simple for me, may be complex to some one else. And may be complex to me later if it is undocumented. But not every one needs to do the complex parts. Complexity as such is not that bad. But if complexity turns into a mess or leaks into other areas of software, then that is bad.
I mean, an airplane jumbo jet is complex, but it is not a mess. Of course the simpler the better. But a jumbo may have billions of parts that are all documented. Still the jumbos are simple: Almost every airplane is built according to simple rules. 1) A tube that can be of variable length and diameter. 2) Wings big enough attached to the tube. 3) Motors attached under the wings so that they can be easily maintained or changed to bigger ones.
Casper Bang, if strictness was implemented in the field of software engineering, we would have lots of less buggy software.
Airplane accidents are obviously much more rare than software crashes. So if we want better software, we need methods like those with airplanes. Ok, you could say that it is negotiable to have some bugs in software, because software is not _that_ critical. But in the same time we curse software and software engineering, because everything goes bananas now and then. So which will it be? Strictness and reliability or just-do-it and a bug-trap?
Software engineering does not have strict regulations. But is that a good reason to build bad software? No.
There is contrast yes: You say that the lifecycle and manufacturing process of a plane and its components is well understood, and that this is rarely the case for software. But I say that this situation is not something that is supposed to be this bad. We can introduce well understanding also into software engineering.
Simplifying the components of software is of course a good thing. But there is some degree of complexity in every case. And that complexity should be as well understood as possible - because there is no point with code that is a mystery when you need to use it. Regulations, engineering methods, and documents make the life of an engineer easier, hence the life becomes more simple and more bearable. And if the software doesn't have any bugs, then the life of a end user becomes more simple, too.
From a .Net world I think it has gotten more complex and vast, but it is also more unified than previous development environments. Have you ever used a namespace with a object with 20 constructors? Ugh. Which one to pick, there are so many...Now I understand that Microsoft and other third parties have to be flexible, but I would rather see less. I think one of the mantras of simplicity is reduction. I think we should actively practice the reduction principal in code.