Tom's Sixth Law: He Who Has the Best Duck Wins

The best way to solve a difficult problem is to talk it through. I for one talk to myself regularly, but problem solving talk-throughs require an independent audience in order to be effective; your listening-self can assume too much and thus your talking-self isn't required to break things down to the same level of detail (which in the end is what really leads to you figuring out the problem). Find a good listener and you can solve anything.

What does this have to do with ducks, you ask? Well, long ago I read a story somewhere about a guy who kept a rubber duck on top of his monitor. (Consider yourself lucky if you don't remember monitors large enough to put things on.) Whenever our fictional hero had difficulty figuring something out, he would explain it (the problem) to the duck. Usually, before the explanation was complete, he had discovered the solution.

Forcing yourself to break a problem down enough to explain it to a toy duck will clarify your understanding of it. Almost always that clarity will lead to a solution.

Incidentally, this is one of the reasons I love to teach things to people. Organizing my thoughts enough to explain them enhances my understanding of them as well. Everybody wins.

At the last company I worked at, the team I worked with grew so fond of this principle that when someone needed to talk through something they would often just walk up to somebody else, go "quack quack", and start talking. Very confusing to new hires, but very effective.

Bottom line: find yourself a good listener and treat them like gold. They will often be your best problem-solving tool.

Even if they can't talk back.

Tom's Fifth Law: User Interfaces Should Look and Feel Native

If you're building an application that will run on Windows, it should look, feel and behave like a standard Windows application. If you're building an application that will run on some flavor of *nix, it should look, feel and behave like a standard application for that flavor (Gtk, KDE, X/Motif... whatever). If you're building a command line application for a given platform, it should take look, feel and behave like a standard CLI app for that platform (argument styles, argument names, output destination... whatever). Etc. etc. etc.

Why? Because when using a certain system, one expects applications to look, feel and behave a certain way. Accordingly, you expect to start them up and put them to work. When they don't look, feel and behave like the other applications that run on that system, however, you are forced to focus on the application's interface rather than on its functionality. This makes the application more difficult to use, which makes it less functional, less useful and ultimately less desirable.

So put away those spiffy widget sets and the customized controls, and stick to what everybody's used to. Your customers may not thank you for it, but your potential customers will notice if you don't.

Tom's Fourth Law: With Power Comes Complexity

Software that does something very simple is usually (usually) very simple to develop. Software that does something complex is usually very difficult to develop, and therefore usually very difficult to use, at least for its first few generations.

(As an aside, this actually applies to computer systems in general and in fact most things in life, not just software development. Food for thought.)

"Well, duh!", I'm sure you're saying. This seems intuitively obvious. But you would be well served to keep this in mind when:

Conversely, if you WANT your software to be easy to use, keep the functionality simple. Focus on the few essential pieces and build them well. (For good examples, check out just about anything built by Google.) Just don't expect to have all the same functionality at the end of the day.

You probably don't need most of it anyway.

Tom's Third Law: When in Rome, Do as the Romans

or Have Good Coding Standards

Laws don't get any more straightforward than this one. If you're making changes to a piece of code that someone else has written, make your code look like theirs. Use the same naming conventions, formatting conventions, design conventions, language constructs... everything.

This benefits:

a) The original author, who will probably end up being responsible for your changes
b) All subsequent readers and modifiers, who won't have to decipher two different coding styles to read one piece of code
c) You, who will be less likely to break something

Anyone who has developed software professionally has at least seen this law broken. Odds are good that they've broken it themselves, for that matter. But the first time you have to look at code that has been touched by different people with different coding styles you learn how frustrating it is when people don't follow this rule.

Imagine a document where the first paragraph were written by an American, the second by a Brit and the third by an Australian. Is it all English? Of course. Would it be easier to read if you didn't have to change contexts and vocabularies with every paragraph? Of course.

This concept applies not only to coding style, but philosophy and tools as well. If the program you're working on is written in an old-school functional style, don't force objects into it - just modify the functions. If the application makes heavy use of SQL to manipulate and retrieve data, don't start adding functions that retrieve raw data and manipulate it in code - just write some more SQL. And if the program you're working on uses a certain toolset - database connectors, loggers, etc. - use the tools that are already there. Don't add new ones. And whatever you do, don't write new ones.

Quick story: I worked on a system not long ago that used three different logging subsystems. Why? Three different people, who each had their own personal logging system preferences, had worked on the app. The last two had decided to integrate their logger of choice rather than use the one (or ones) that was already there. Was there plenty of logging in the application? Yep. Could you practically control and use the logs the system produced? No, because each sub-system had it's own configuration, it's own message levels, it's own output format, etc. This is admittedly a pretty extreme example, but it makes the point rather nicely: if all three developers had used the same logging system, the system's logging would have been phenomenal. Instead, it was utterly useless (and, in fact, was a hindrance rather than a help).

I bet you don't have to think very hard to recall a similar mess in an application you've worked on. Consider yourself lucky if you can't.

In some ways - particularly concerning tools - this is a corollary to my second law. If you're re-using what's already there, you're being properly Roman. If you're not, well... you'll eventually get thrown to the lions.

Tom's Second Law: It's Already Been Done

Or, Do NOT Re-invent the Wheel

When designing and/or implementing anything other than business logic - and sometimes even then - the odds are very good that what you need has already been built. The problems solved by any particular application are usually related, so in a project of reasonable size you're likely to find an existing solution within that same project. And the problems solved by applications in general are largely similar, so thanks to free and open-source software, you're likely to find a solution somewhere out there on the web. Seek out those existing solutions and use them if you can. If you can't use them you can at least learn from them.

Remember what Picasso said - good artists copy, great artists steal. Programmers tend to think that only their code is worthwhile, and that they must write everything themselves from scratch. That mindset is a recipe for disaster. Fight the urge to code everything yourself. Instead, assume that it's already been done, and build it yourself only after you fail to find an existing implementation. You'll be much more productive and produce higher-quality code over the long-term.