This thread is for sharing any programming advice you have for anyone who wants to improve.
I have a few things that I'm doing at the moment which seem to be working:
1. Learn assembly language (if you use a bytecode compiled language (e.g. Java, C#, Python), learn its assembly language as well) and get your compiler to produce assembly output of your sources (or use a disassembler if your compiler doesn't have that option. For gcc, use the -S command-line flag). Read the assembly code and understand it. Experiment with different methods of achieving the same thing. Look at which one is fastest (usually the one which produces the least number of instructions, but not always).
2. Learn compiler theory. This helps with #1.
3. Learn a language that's completely different to anything else you've ever used. I recommend Haskell and Scheme.
4. Read the standard/specification for your chosen langauge(s). Then you'll know all the caveats and nuances of the features of the language, which will help you learn what is faster and also help you write more maintainable code.
5. Learn the threshold at which your code is considered 'production grade'. Too often, hobbyist programmers tear down their work only because a 'better' approach is thought of. Learn the point at which your code is good to go and move on, otherwise you'll just be spinning your wheels.
* Learn to design for testability, and learn to write unit tests: both black box and white box. Learn how to do boundary testing (interface, implementation, and platform boundaries!), how to test along orthogonal dimensions, category partitioning, depth-ordering of problem space, etc. Maintain 100% test coverage. In some companies, it is enforced.
Start writing tests before you even start writing your actual code. You'll get a better understanding of what you are trying to achieve, and your code will be more robust because you'll need to code to cover your cases from the get go.
* Annotate - that thing everyone hated in highschool really does have a use. commenting and highlighting important information in your book not only helps you remember that information better but leaves a mental book mark incase you come across a problem that involves the information you annotated. Little things like
<- good use for sorting method
and
Functions helps clear memory for compiler, dont forget to use! --->
Start writing tests before you even start writing your actual code. You'll get a better understanding of what you are trying to achieve, and your code will be more robust because you'll need to code to cover your cases from the get go
You can do it, but it is very arguable if it is a good advice. Some write tests before, some after, some don't do at all. It is very arguable if writing tests early brings you some benefits. Making your code pass all the tests really doesn't guarantee anything about its quality. And coding just to pass the tests often leads to sloppy code - lots of special cases just to make tests pass [1].
* Think carefully about the overall design of your code and algorithms before you start writing your tests [1]
* Keep number of tests as low as possible. Avoid testing things that are trivial or can be proven right in other ways, e.g. by good design, clean code, static code analysis, proofs [1].
* Code bottom-up. Books on software engineering say you should code top-down, but it also almost never works in practice and most talented coders code bottom-up [2]
* Clean code structure is more valuable than complex code with lots of comments.
* If you still insist on writing tests, give test-writing to a different coder / team.
Making your code pass all the tests really doesn't guarantee anything about its quality.
That is true (code review and testing address different issues), but it doesn't mean you should ever give *unit* testing to someone else. They don't know the internal boundaries of your implementation.
I don't advocate TDD either: design, especially in C++, takes quite a bit of thought. I am saying that testability is one of the major requirements in design.
Example: To solve the birthday problem (how many people are needed in the room to find two with the same birthday with given probability), you write a function that returns the probability that at least 2 of the specified nonnegative number of people have the same birthday (assuming february 29th doesn't exist)
1 2 3 4 5 6 7 8 9 10
double sameBirthday(int numPeople)
{
assert(numPeople >= 0);
if(numPeople > 365)
return 1.0;
double probability = 0.0;
for(int i = 1; i < numPeople; ++i)
probability += (1.0 - probability) * i / 365.0;
return probability;
}
Guess what? This is not designed for testability There is a platform-imposed boundary between 183 and 184.
Much better design would give you the probability that no two of the specified, randomly chosen people were born on the same birthday
1 2 3 4 5 6 7 8 9 10 11
double uniqueBirthday(int numPeople)
{
assert(numPeople >= 0);
if(numPeople > 365)
return 0;
double probability = 1.0;
int lastNumerator = 366 - numPeople;
for(int i = 364; i >= lastNumerator; --i)
probability *= i/365.0;
return probability;
}
(Examples are from the 2012 ACCU lecture by John Lakos)