![]() ENGINEERING |
Home of TurboCNC, the best open-source CNC control around... |
|
||
You are here: Homepage -> Articles -> Software tips |
Latest release of TurboCNC is v4.01
build 050312, released March 13 |
|||
Tips on Software Engineering |
Hardware | Software | ||||
Articles | HOME | FAQ's | |||
Manuals | User Forum |
||||
About DAK |
Ordering | Contact DAK |
|||
Sitemap | Links | ||||
Writing
software is a fairly new art, and as such is pretty disorganized in practice
with countless individuals struggling to re-invent wheels and chasing bugs in
their code. Part of this is owed to
the rapid progress in the field that obsoletes entire languages faster than
books on them can be printed. Here
are some working rules and guidelines to make your software projects go more
smoothly. I'm assuming a high level
language here like Java, C++ or Pascal, but most of the lessons are applicable
to machine level assemblers and state logic as well. KISS
"Keep it Straightforward, Stupid".
I'm changing this over from "simple" used in other design
trades, because for the most part programming does not deal with reducibly complex
problems as such.
Customer requirements change, new developers come in, and code needs to
be maintained - perhaps even re-written for the language/platform of the month.
The more straightforward the programming model is, the easier your job
will be when these things come up. Very
sophisticated and flexible algorithms are nice, but quite often it's the
straightforward, easy to understand ones that carry the day. Avoid "trick" programming that relies on the special nature of a problem or a particular compiler. Examples would be things like adding booleans to integers, taking advantage of little/big endian order, or assuming a particular floating point representation or memory model. Planning,
then framework, then finishing I think that if most programmers built houses like
they wrote their programs, they would start by building the kitchen completely, including the sink and
range, and then proclaim: "Well, the kitchen works!
Now all I have to do is get the rest of the house in order."
Next week I'll start on the Foundation class. Whoops!
Need a door here, hmm. I'll
just modify this code here to cut a hole through these two adjacent rooms. Bang! Looks like I cut through a light switch - oh well! I'll move
that to the other side so it's out of the way.
Actually, I think I'll move all the switches to their own special room
until the rest of the house is ready.
Or maybe they'd build a paper-thin house shaped veil of paint first so it
looks good, get the customer's approval, and then decide how the house should
fit inside it!
Go ahead and laugh, but a lot of programming projects are done this way.
The way to do it right is similar to homebuilding.
Plan first. Figure out the
basic layout (see the section on function mapping) and make sure it satisfies
the requirements, number of users, how much it'll cost to build.
Then frame it up - just skeleton functions that call each other and go
through the motions of the program logic. Get
it to compile, but not really do anything useful yet.
You just want to make sure the logic is sound at this point and fix
anything that seems strange while it's still simple to do.
The flow of the program and data structures should be notionally clear.
Once that's taken care of, start fleshing in the actual code that makes
it work. You'll probably find that
this goes much more cleanly than trying to make it up as you go along. Put
flexibility only where you need it
The more flexible you make a program, the more complicated it becomes and
the more development time is required. Know where you need to be flexible, and
where you need to code "stiff".
Excessive abstraction is probably the best example of this, as are
gee-whiz things like configurable menus and toolbars, or the all elusive
"General Case". Just like
the old saw about implementing the constant PI as a variable in case it changes,
only code for change where it is legitimately anticipated, or when it simplifies
the implementation. Watch
the kLOC
kLOC stands for '1000 lines of code' and has become a rough measure of
the complexity of a project, as well as programmer productivity.
You want to keep the number of lines of code down as much as practical.
According to research, a programmer generates about 200 lines of code per day as
a long term average. Bugs generally occur at the rate of 5 per kLOC or so, and the
complexity of a program goes up pretty much with the log of the number of lines
(assuming that good engineering/coding practices are in place).
So in general, only code what you need and keep it short.
You'll have to scroll back and forth over it, re-shape it, and debug it
dozens or hundreds of times over most likely before your project is done - so
the less of it you have to thrash around in the better. Comments
& documentation
Comments and docs are probably the most overlooked elements in coding.
Under pressure to "just get it working", programmers often
forgo them in favor of honing algorithms or just getting more code written.
Good comments should be descriptive, and are especially important at the
function and object level. A
comment should not re-state what the code is doing, which is an especially
common mistake in assembly programming. Bad:
Better:
Better
still:
Make sure you update the comments when you change the code!
Otherwise, no one is going to understand it - maybe not even you.
Similarly, ensure that documentation is accurate and is helpful to
someone only moderately familiar with the details of your program.
Likewise, libraries and special functions should be documented -
preferably with a page on your desk or a "white paper" that describes
how they work so as to make remembering easier.
This saves alt-Tabbing and searching through code so you can remember
what the parameters were for the WidgetOf() function again. Know
your tools
Take an hour or two every week to glance through documentation for the
tools you use (compilers, editors, profilers, etc..) and learn something new
that strikes you. Quite often you'll find some unused capability there that
will help you to be more productive. Understand the limitations of the languages and libraries that you use. Know them thoroughly enough that you can design your programs without stumbling over a bad assumption and having to write "band-aids" to compensate.
If you write a lot of code, I suggest getting hold of a good keyboard
macro utility that lets you create hotkeys for commonly typed blocks like
function definitions, loops, and so on. I
was surprised to find how much easier it is to write software with a few good
macros. A simple block-if
declaration in Pascal is about 50 keystrokes for example.
Using a hotkey it types itself in a flash, saving energy for the
more important things. Function mapping
Flowcharting is fairly "old school" nowadays, and isn't
terribly useful in most situations. But
function mapping is, and should be done as part of the planning/framing stage of
a project.
Essentially, you sketch on a sheet of paper the function tree for a
program, or part thereof. Just the parameters and the returns, and which functions call
which. Put the lower-level
functions toward the bottom.
Don't worry about drawing boxes, or making it neat.
I like to use whiteboard and markers for initial planning. Object
properties/methods are best listed in one block rather than separately. This helps get a few of how a program is going to work, and is invaluable in smoking out ways that you might get painted into a corner later on before moving to the keyboard.
Also, you may spot places where new functions should be created, or where
functions can be combined or eliminated. Even
for a small project of 2000 lines this is often helpful where you might have been
tempted to just dive in and go. If you didn't test it, it probably doesn't work
This is just a re-statement of Murphy's law.
There doesn't seem to be any such thing as a trivial change, so if you
add some functionality and then don't test it, it probably doesn't work.
Make sure the new whizzo-bango code actually does what it should be doing
before you send it out. Keep the users' needs foremost It
has become almost a dogma in programming circles that anything that saves the
time of the programmer should be done. If
it's faster to code something a particular way, then do it that way.
I believe this is wrong - programs should be written for the ease of the
users so that their time is saved. For
example, say that you as a programmer can save 10 hours of your time by
programming some feature in a particular way that is awkward, but satisfies the
letter of the users' requirements. Suppose also that this awkwardness will cost each user about 30 minutes on the average to figure out how this feature works and get the results s/he wants. For even a modestly successful program that has 1000 users, you can immediately see that the balance hangs in favor of conserving the users' time (500 hrs), not the programmer's (10 hrs). They're
paying for it and money is portable, so make it good. Peer Review
Have someone else review your code.
If you don't have a buddy, print it out and look it over carefully a week
or two after you wrote it. You'll
be amazed at some of the things you find.
This is especially important for library type functions that will be
relied upon again and again throughout a project or even a career. Don't code when you feel lazy
I feel that good programming is really more a matter of stamina than of
intellect. Going the extra mile to
trap all the possible errors, work through test cases, and grind out the obscure
bugs all takes significant mental discipline.
If you're feeling lazy, take a break, go for a walk, whatever. Just don't
slog out 500 lines of mediocre code, it's not the right time to do it. Eat your own dogfood
This one comes from Joel on Software, who recommends that you use your
own applications as much as you can - for the purpose they are designed, to get
a feel for what the customer has to go through.
How can you make things easier for them?
Any bugs in there that no one has bothered to complain about yet? Beta test early and often
Beta testing is an important part of the development process.
Test early on while things are still malleable so that you can
incorporate the suggestions of the users upfront.
This is really what can make a good piece of software into a great one. Use input from the people who need to use it on a routine
basis. Rules you should unlearn
These have crept into the programming lexicon somehow, and are parroted
by many individuals whom, I'm convinced, don't know what they're talking about
really. The tipoff is the
"Never" and the "Always", which is a reliable indicator of
inflexible thinking.
Now generally, you do want to avoid GOTOs, global vars, void returns, and
mysterious constants in your code. Long
functions can be tedious to work with, and many languages are in fact limited.
These are all complicating factors.
But strictly following rules 1..7 can lead you to a gangly, awkward
implementation in many real-world problems.
Every situation is a little different.
Work sensibly and logically, using your head. Take
advantage of the tools that are effective for the problems you're solving. Good luck with your projects! |
|
|
© 2001-2020 DAK Engineering. All rights reserved. This page last updated on January 11, 2015 . Email: admin@dakeng.com |