You could probably find “Code Complete” by Steve McConnell in any of the top 10 lists of books recommended to read for all programmers. I recently finished reading that book too. I have to confess that at times the tips and knowledge in there was a bit too basic and fundamental but, on the other hand, I also think that it has a lot of golden nuggets of knowledge.
While reading it, I was writing down notes after every section. Essentially, they were three/four ideas that I thought were the most important in each section. Sometimes, they were paraphrased from the conclusions of each section written by the author himself. In other cases, I summarised them myself, in my own words.
Note that some of these things I knew already, obviously. However, I think that they are still very important to know to all programmers, independent of their skill level. Let me know what you think of it and if you picked up any other things from that book! Here is my assorted list of 10 ideas that I got from this book:
- Defects in the requirements/architecture stage are very costly money-wise. In general, the later the errors were detected, the more you will have to pay in terms of money or time. For example, if you noticed issues in those two things in, for example, the implementation stage then you would have to go back a lot: not only you would have to re-do your requirements/architecture but you would have to design your code again and essentially almost start from scratch. Also, that’s why code reusability is paramount. (Chapter 3)
- Software development is a heuristic process – there is no methodology that works for all cases. That is why prototyping is important – do not be afraid to write small pieces of code for testing something out. (Chapter 5)
- The imperative of software design is to reduce complexity. It should be rethought or thrown away if it does the opposite. Keep accidental complexity to the minimum. Essential complexity is inevitable. Learn how to know which is which. Try at least a few designs before settling onto the final one. (Chapter 5)
- Make sure that related statements are in groups, close together. Relatively independent groups of statements should be moved into their own functions. Also, code should be written to be read from top to bottom. That’s why early exits are important, IMHO. (Chapter 14)
- Consider jump tables. They offer a good opportunity to reduce complex code with a lot of conditional statements. They can be index-based or staircase-based (when not exact values are used but ranges instead, you have to duplicate values). Think if you need to put index calculation into a separate function instead of duplicating code. (Chapter 18)
- Testing by itself is not very effective. Consider combining multiple quality assurance techniques according to your organisation goals to achieve maximum effectiveness. Make quality objectives clear because people will optimise for them. You should also formalise this process to make it even more clearer. (Chapter 20)
- Use binary search with hypotheses to narrow down the search space of where the error might be. Understand the root of the problem before trying to fix it because you might introduce more defects while fixing it. Set the compiler to the pickiest level possible. It will save more time in the long run. Don’t ignore the warnings. The compiler is your friend. (Chapter 23)
- Do not stop with the first code-tuning technique, there almost always exists a better one. Move expensive operations out of loops. Always benchmark your changes because results vary wildly depending on a plethora of variables. Apply optimisation with care: readability and maintainability are still paramount. As Sir Tony Hoare said: “premature optimisation is the root of all evil”. (Chapter 26)
- Consider rewriting a routine/function if its decision count is more than 10. Make boolean checks positive. Do not use double negatives. Write boolean checks according to the number line so that they would flow nicely from left to right. (Chapter 19)
- Always think if arrays are really suitable for you. Research shows that programs with container data structures – queues, stacks, et cetera had fewer bugs. Use enumerated types instead of constants because they enforce more type-checking and thus it makes the program more correct. Abstract data types should be oriented as much as possible to their functional purpose. Don’t create ADTs just to store arbitrary data. (Chapter 12)