I had a thought of creating this website where I can show off some of my work in progress websites and to help remind me to push myself towards learning and getting some of my work out there. Throughout that time neither seemed to have happened and this site was just out there collecting Internet dust. If you asked anyone what I was doing they would each say that I was working on a game, or some side project, or even learning a new language. If you’re like me then your initial reaction would be “Awesome, when can I see it in action!” and that’s where it would end. I would have tech demos sent to my buddies, or have a small little gameplay video to show but after that it would be silence. Life would intervene and push my side projects on the back-burner. When I found myself with extra time I always had 2 options open: Either get some sleep and prepare for my next day or attempt to go back to the project but completely forget where I left off and step through my logic to figure everything out. You could say that I had a big picture in my mind for where the project was supposed to go but never had the small puzzle pieces lined up as to what to tackle next.
Having a big picture of what to do is great and it gets you fired up to do something. You start to plan for the project by compiling a list of ideas and making a plan of attack before programming. I started to fail when the pieces of the big picture were still too big to put together within my short span of free time. Between working 60-80 hours of my professional job and spending the rest of the time keeping up with family and friends left me with a couple of hours a week for myself, which would mostly go to sleep.
With the limited time left I am going to try a different approach to my side projects to help not only motivate me, but to help with execution. I am going to see if I can split m tasks down into short hour or 2 bursts that can be found here and there. This way tasks can be simple and independent of each other without having to go back to another part of code and trying to see what had been done. I’m hoping that this will help break down my giant puzzle pieces into smaller ones.
If this little experiment works then hopefully there will be content here to show for it. Otherwise, we’ll be back to collecting dust and figuring out another way to approach this.
I had many mentors as a Padawan in the world of programming. These mentors varied from helping me learn the first steps as a programmer from the famous “Hello World” program in C, C++, and C#. To the more advanced techniques and theories of data structures and various design patterns. I also got thrown into a world of 2D and 3D graphics programming with OpenGL and DirectX. But the mentor that stood out the most out of them all taught me about Linux, embedded architecture, and the famous x86 assembler. He was very knowledgeable and gave me the following wise words to always remember as a programmer. While he added his own spin on these rules, they always stuck by me while I was designing new functionality or going back and improving my existing code. Below are his words that were modified from Code Complete and from NASA’s 10 coding commandments that stuck with me:
- Comment your code with valuable comment not useless ones
- Don’t forget about error checking since anything can fail and it will
- Use less code (DRY don’t repeat yourself)
- Write code that can be easily modified but don’t make it unreadable. Code can always be thrown away.
- Write code that can be easily tested. If you did not test it then consider it broken.
- Fix the problem, not the symptoms. The symptoms are the obvious artifacts of the problem, you need to find the problem.
NASA’s 10 coding commandments
- Restrict all code to very simple control flow constructs – do not use goto statements, setjmp or longjmp constructs, and direct or indirect recursion. (well all of these can be used in moderation if need be but there must be a justification)
- All loops must have a fixed upper-bound. It must be trivially possible for a checking tool to prove statically that a preset upper-bound on the number of iterations of a loop cannot be exceeded. If the loop-bound cannot be proven statically, the rule is considered violated. (Good idea but not always possible but you must justify the exception)
- Do not use dynamic memory allocation after initialization. (of course this assumes that during initialization you know exactly what memory you need, which might be difficult to determine)
- No function should be longer than what can be printed on a single sheet of paper in a standard reference format with one line per statement and one line per declaration. Typically, this means no more than about 60 lines of code per function. (Good idea but limits be arguable)
- The assertion density of the code should average to a minimum of two assertions per function. Assertions are used to check for anomalous conditions that should never happen in real-life executions. Assertions must always be side-effect free and should be defined as Boolean tests. When an assertion fails, an explicit recovery action must be taken, e.g., by returning an error condition to the caller of the function that executes the failing assertion. Any assertion for which a static checking tool can prove that it can never fail or never hold violates this rule (I.e., it is not possible to satisfy the rule by adding unhelpful “assert(true)” statements).
- Data objects must be declared at the smallest possible level of scope.
- The return value of non-void functions must be checked by each calling function, and the validity of parameters must be checked inside each function.
- The use of the pre-processor must be limited to the inclusion of header files and simple macro definitions. Token pasting, variable argument lists (ellipses), and recursive macro calls are not allowed. All macros must expand into complete syntactic units. The use of conditional compilation directives is often also dubious, but cannot always be avoided. This means that there should rarely be justification for more than one or two conditional compilation directives even in large software development efforts, beyond the standard boilerplate that avoids multiple inclusion of the same header file. Each such use should be flagged by a tool-based checker and justified in the code. (could be a debate here but since macro are not well checked this is a good idea)
- The use of pointers should be restricted. Specifically, no more than one level of dereferencing is allowed. Pointer dereference operations may not be hidden in macro definitions or inside typedef declarations. Function pointers are not permitted. (No function pointers? Seems like the skill level expected here is suspect, but it does prevent static analysis tools from working well)
- All code must be compiled, from the first day of development, with all compiler warnings enabled at the compiler’s most pedantic setting. All code must compile with these setting without any warnings. All code must be checked daily with at least one, but preferably more than one, state-of-the-art static source code analyzer and should pass the analyses with zero warnings. (in some ways I agree, but suppressing the errors and warning can cover-up other problems)
Do you agree with these rules or are they outdated? Do you have other rules that you abide by that help make you a better programmer? Leave your comments below.
The above statements came from a post from my mentor Gary Miller. May he rest in peace.