Software Design: The easy way is complicated

Wait... WHAT?

A programmer may find it easier to copy and paste a statement 10 times than to use a for loop if they have not done a for loop at least several times in the given language. The fact remains that tedious and repetitive work is easier than work that constantly differs by a large degree.

The real life story

A colleague of mine once made me change back something I had added, because she wanted to "keep things simple". What is it she wanted to change you ask? I had created a simple class with constant strings to name session variables(.Net). This way you could easily find troubles with session variables being misset or accidentally reused for something else, because instead of strings they are simple. One problem that arose is that the debugger refused to display the value of the session variable or use it in any expression, and thus it was removed, but at a cost.

What cost?

The costs are debugging and testing time. Keeping your code centralized is an important aspect of good design. If this was untrue there would be a sink in one room, and a toilet in the other. This would mean you can take a shit, but you have to walk accross the hall to wash your hands. Oversimplification of a problem requires narrowing of the problem domain, which means that you will be solving more oversimplified problems later. It can actually get to a point where renaming a variable can take days, and break entire system which rely on it.

Another example

If you don't use a for loop in your code, and copy and paste the same code snippet 30 times, you will most likely not have out of range indexes, and if your careful it will work perfectly. Then you leave the project and the next programmer comes along. They run into your hard coded loop and wonder: "Why did he do it this way?". They(and by they I mean me too, this is a real example) then have to sift through every single iteration making absolutely sure that there are no functional differences in any iteration. This almost bit me. A database field in a legacy system is limited to 10 characters. When the field names increment past 10, the last letter of the name is replaced by the 1 in the number. So you would have flag9, fla11 suffixing the field name. Another catch was that 10 was 0, so you would have a sequence: FLAG9, FLAG0, FLA11...

The problem was perfectly solvable with one for loop with 2 nested if statements. The programmer before me took the lazy route and made my route hell. I still worry a little if some business logic wasn't lost there, but I cry no tears for bad code. It needs to go. As soon as possible.

Complex implementation makes simple interface

To return to the copy and paste example, it is easy to copy and paste some little action everywhere you need it. A typical example is:

- Connect to Database
- Execute query
- Return result
- Close connection

Pasting snippets that do this is luckily not something I have seen often(except maybe in sloppy PHP). Writing a function that does the above will mean you never have to paste that snippet, and you can make global changes enhancing the way you data access layer functions.

Wrap up

I have seen many programmers wrestle with the same problem over and over again. I mean... I have seen the same programmer wrestle with the same problem he had a few days ago, because he solved the problem once, but did not wrap the answer up into a simple to remember way. In order to advance yourself and the systems you work on, you have to make sure you do the least work with maximum area effect.

Be rike the atom bomb, smaw bom, but spread rarge area.

Software Design: Getting it right the first time

The longer you spend designing your software, the quicker you will write it... right? WRONG!

The best way to design software is to write it. Now I know that goes against the principles of good design, so let me say this: You need a fairly good design to start with, but one that is essentially an experiment. During this first version of your software you will start to notice that there are flaws in your design. This is what makes writing it so important. Your writing it to throw it away.
"Always be ready to throw (at least) one away" - Fred Brooks in The Mythical Man Month

I read somewhere that Microsoft uses this approach by making competing products.

Here's an interesting discussion on the topic:

This will teach you important lessons in the next version. I think that version one should always be an attempt at a functional system, and version 2 should be a complete redesign addressing the problems with version 1 head on.

But WHY!!!? Why not perfect the first time?

  1. The answers are simple. When you solve a problem set the first time you choose an angle of attack after some forethought. The angle of attack is based on assumptions you have made according to specification documents, users and the operating environment. Specifications being what they are(incomplete at best) change as the system evolves. The initial idea of how something should have worked may come under scrutiny only when it is actually being used.
  2. During the detailed design of the software, including classes, modules, interfaces etc you make decisions on how things will branch out. What will remain static? What will change? These things are assumed, and quite often guessed completely wrong in the first iteration of the software lifecycle.
  3. Your expertise need to change. When you first take on a new project you may know something about underlying business rules, but you are very likely not an expert. You essentially need to become an expert in the needs that a system has before you can start writing it. The problem is that the best way to become an expert is to write code for the application. You learn that babies cant jump over hedgehogs, and hedgehogs are allergic to babies, but only when they have salted peanuts. Before you know these things your business logic fails multiple times, and this may happen on the design level.
The programmers aversion to design

The programmer's aversion to design is natural, and not a failure. Wanting to accomplish the goal or see how the machinery will work is what a programmer can and should do, instead of meaningless speculation. I am by no means saying that no design should be done. There is useful design. A good database design that will work across different versions of your application is essential. Data anomalies and conversions are not easy problems, so it's best to get it right the first time.