I have often thought about what the proper software methodology should be for the various robots that I build. My thoughts have evolved over time as I have seen these tool work. While I do not have any formal software engineering training, these are the common principles that I have seen, heard, read, etc. that I believe in (at 2am while I write this).
Disclaimer: Most of the suggestions here have come from other sources. Please check out the links attached for more information.
I will start with how to write code, since that is the basis of everything else. After that we will move into the software engineering infrastructure needed to make the software work properly.
Without having basic rules that you follow when coding, your code is doomed to fail and be unreliable. Everything else is built upon this. Many people start programming and want to use crazy template magic where everything inherits something else, however you must STOP and write simple code that is easy to understand and test.
Helpful links:
Rules for defensive C programming
The Power of Ten – Rules for Developing Safety Critical Code
Having a code repo should be a given for every programmer and programming team. There are many free tools available, so there is no excuse to not use them.
Having a software repository lets you save your code at various points so that you can roll back to prior working versions. Repositories also let you log what was changed in each file and by whom. These tools are a great way to share code with a team – there is no need to email code back and forth. You can also put documentation in the repo so that is is always available.
There are many options to choose, from cvs, svn, mercurial, git, bitkeeper, etc. Just pick one!
Lately I have been using a hosted repo service called github.com – I like all of the tools that are packaged with git on the website. bitbucket.org is another similar option.
I generally like to create repositories with the following directories in the root directory:
In addition to the directories above, I will usually put the main make file for the project and a README in the root directory.
Links:
Software repositories or just plain repo
Having a central database to track bugs is very important for developing great code that runs bug free. This lets anyone who identifies a bug to report it in such a way that it does not get lost. Just telling the developer or emailing them is not sufficient. People forget things easily. Ideally, you do not want the developer to close a bug; you want somebody to report the bug, the developer to fix it, and then the original person who identified the bug verify that it was properly fixed.
A bug report needs three things:
Links:
Painless Bug Tracking
Each of your processes/functions should have a set of tests (often called “unit tests”) performed on them to verify functionality. These tests make sure that functions work with various input extremes and combinations. Ideally you should have a test for each possible control path within a function.
For example if you are testing a “sum(number1, number2)” function, you can have the following test file:
int main () { assert( 2 = sum(1,1)); assert( 0 = sum(-1,1)); assert( NULL = sum(1,NULL)); // or whatever you want it to be doing… assert( 0 = sum(0,0)); assert( 1999998 = sum(999999,999999)); assert( 5 = sum(4.2,1)); // assuming integers and that floats are rounded. RETURN (TRUE); }
In this example assert will print an error message about where it failed and exit. (This is just my quick example, and can definitely be expanded and improved. It can also be changed to fail at compile time so that you do not need to “run” it.)
Having a build server that builds every time somebody commits code, or at minimum, every night, is valuable for identifying inadvertent bugs introduced into your system and automatically running your tests.
Often you will make a change to one module that will cause another module to fail. But as developers we get focused on our modules and tend to not try recompiling all of the code to make sure that we did not break anything. It is always better to find out you broke something earlier than later.
Certain things tend to cause other modules to break more than others. For example making a change to a widely used header file or message definition file can affect other items.
This also makes programmers only commit code that compiles to the repo and not broken code. If they commit broken code the build tools can/should send out emails to notify people that the build failed (and whose fault it was).
You can either just make a quick script to check out the repo, build it, parse the output and email the results; or you can get a proper build system such as Jenkins. Generally using somebody else’s product will be more reliable and a better use of your time.
Links:
Daily Builds Are Your Friend
Code reviews are tough, but they are also one of the best ways to reduce the number of bugs in a piece of software. The traditional code review – where a person gets up and talks others in the room through the code (that the people have never seen before) – DOES NOT WORK! This might be good for getting people familiar with the program’s operation, but it is not the best way to do a code review and find problems.
To do a code review you should have the programmer send a review request to 1-3 other software engineers. The review request should have an overview of the code, a flowchart, and directions to access the code. The number of engineers and the experience level of those engineers should be based on how critical the code it. Each reviewer should:
Some of things reviewers should watch out for are when reviewing code before a large review:
(Did you notice how this list is similar to the good programming practices above?)
After doing the above steps it is now OK to hold the big meeting where people sit down and walk through and review the code; although this is not strictly necessary.
Reviewing code can be hard. Getting your programmers used to reading code and reviewing it will help strengthen their own coding. It can also be useful to have dedicated QA people who review code.
Links:
Embedded System Code Review Checklist
Microsoft: Best Practices: Code Reviews
You should be using a build tool so that you are not manually compiling each file. Probably the most common one is make.
Each make file should have at minimum the following directives:
I believe you should be able to build, install, test, or clean your entire system with one command. As such I will normally create a make file for each process, and then create one master make file that calls all of the individual make files. Having a single make file that can build everything is good for installing a new system and makes setting up the nightly build easier.
Do you have other favorite tools to make your software more reliable? Please leave comments below.
Main image based on sample code from wikipedia and hammer from pixabay.com/.