Everything breaks. Any component you use in a project will break at some time. Gears will slip, struts will bend, voltage will fluctuate, data will corrupt. It all breaks. Plan accordingly. If some piece of code is bug-free now, someone will change it at some point in the future and introduce a bug. So when you use a function, think about what will happen when (not if!) it misbehaves. Never pause work in a project when the next step in the project is unpleasant. When possible choose your pause when the next step is fun and easy. This makes it much easier to get back to working on it. When you can't win, you can't break even, and you can't get out of the game, change the rules. Optimize for the common case, but make sure it can handle the worst case. It doesn't need to handle the worst case well, just well enough to avoid disaster. Documentation is a necessary part of engineering. So is ergonomics. Someone should be able to easily use your product to do a little, and read the documentation to learn how to do more. Likewise, the documentation should describe the process the product goes through to accomplish its tasks, so that when it breaks someone who knows nothing about it has a chance of fixing it. If nobody uses your tool, there wasn't much point in creating it. People do not use tools that are not well-documented or easy to use. Pay due attention to documentation and ergonomics. It is more important for a tool to be reliable than featureful. Nothing is more frustrating than a misbehaving tool. Perfect reliability is a state which can never be attained, but may be asymptotically approached. Strive for it with zeal and discipline. Introducing features invites their use, and use of features will result in institutional dependence on those features. So only introduce necessary features. Introducing features also introduces bugs. The only part that is bug-free is the part which is never made, so making fewer parts makes for a more robust product. So only introduce necessary features. Time spent on new features robs you of time for debugging the necessary features which already exist. So only introduce necessary features. Upgrading introduces bugs. Only upgrade when it is necessary to fix a bug, eliminate a security vulnerability, or acquire a feature which you absolutely cannot live without. Ten-year-old software which still does what you need it to do is not "obsolete"; it is "mature". Bugs increase exponentially with code complexity, which is roughly proportional to code size (but also depends on modularity). For hardware products, the number of bugs increases exponentially with the number of parts. Moving parts compound the formula. The ideal size of an engineering team is two engineers. Larger groups should be broken up and set to task on independent projects. Do twice as much today, because something might happen tomorrow which prevents you from working at all. Shorter development schedules discourage development of nonessential features, and promote more efficient use of time. If something will take more than three weeks to complete, try to break it up into one-week subprojects, each of which can function independently and either be tested before the next subproject begins, or worked on in parallel by independent engineering teams. Get something working reliably before worrying about optimization. Optimizing trouble-prone processes makes the trouble worse, and makes debugging more difficult. Optimize at the algorithmic level first, and then at lower levels only if still required. Do not be as clever as you can. People less clever than you need to be able to work on your project. For that matter, you might need to work on it someday when you are not at your best (ill, tired, distracted, stressed, etc). Code outside the inner loop should be written for short development time, not for performance. Time spent optimizing noncritical code is time that could be instead spent debugging critical code. Thinking about a problem too much before deciding on a solution is counterproductive. No matter how hard or how long you think about it, there will always be issues which only become evident once you have a working model. Also, issues you do foresee might not be as severe as you think. Everything becomes clearer when you have a working product which you can watch break. If it is too broken to be useful, take what you have learned and start working on version two. Time spent on version one was not wasted; you will learn more (and faster) from failed version ones than you will from just thinking about the problem. When you disagree with a fellow engineer, voice your opinion, then shut up and do it their way. At worst, it will become evident that they are wrong, and everyone will start working on a more-correct solution together. At best, you will turn out to be wrong, and by doing it their way you will develop a useful product. Either way, it is a learning experience for someone, and you will achieve more by doing the work than you would by arguing (which might not change the other engineer's mind anyway). Egos kill engineering projects dead. If two engineers are arguing over which solution is better, quietly pick a solution and implement it. A working solution trumps most arguments. Useful products will often be used in roles for which they were never intended. For more in a similar vein, see Software Engineering Proverbs Go Back to TTK Ciar's Personal Section Go Back to TTK Ciar's Home Page |