What makes a great programmer? Is it the capability to solve problems? Or the passion for coding? In truth, great programmers know that people matter. Whether you work professionally as a developer or you’re an enthusiast coder, you’re likely to be coding with and for other people. Being a great programmer isn't just about solving problems, but making sure that the solution is simple and that others can understand, maintain and extend it.
Let’s be honest, programming is hard. Regardless if you just started coding or you’re an experienced programmer, there’s always room for improvement. In the classic book The Pragmatic Programmer, Andrew Hunt and David Thomas formulated a list of principles every programmer should follow. Here are our favorite ones:
Don’t live with broken windows
According to The Broken Window Theory, “If a window is broken and left unrepaired, people walking by will conclude that no one cares and no one is in charge. Soon more windows will be broken…” Don't leave "broken windows" in your code. Bad designs or poor code should be fixed as soon as it's discovered.
Good enough software
Write software that is good enough for your users and other maintainers. This doesn’t mean writing poor code, but knowing when to stop. Be consistent with your users' requirements and don’t try to add new frivolous features or over polish. Good software now is better than great software later.
Invest in your knowledge portfolio
New techniques, languages, and environments are developed every day. Keep yourself updated. Learn at least one new language or framework every year. Read a technical book each semester. Diversify your knowledge. And don’t forget to be social! Attend conferences. Engage in a programming community. Just never stop learning.
Don’t Repeat Yourself
The DRY principle speaks for itself: “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” Create an environment where it's easy to read and reuse things.
As your project evolves, the user’s requirements might change. Keep in mind that there are no final decisions. Things can (and probably will) change, so be prepared. To avoid future headaches, minimize coupling, unnecessary dependencies are expensive to maintain and tend to be unstable. Maintain a flexible code, architecture and deployment.
Have a debugging mindset
No one writes perfect software, so debugging takes a lot of every developer’s time. When debugging, concentrate on fixing the problem, not the blame. Start by gathering all data needed to reproduce the reported bug. If you can’t find the cause, try Rubber Ducking, this technique encourages you to explain the problem to someone else (or a rubber duck), by verbalizing the problem you may gain new insight. When finding the bug, don’t just fix it, always modify the automated tests to check for the bug, no matter how trivial it may seem. This way you’ll make sure that if the bug repeats itself you'll be aware.
Test early, often and automatically. After writing your tests, ask yourself: did I test all the boundary conditions? Create a safety net with regression tests — tests that compare the output of the current test with previous known values. As you develop, run your tests to ensure nothing has broken. There are many kinds of software testing, make sure you cover the most of the types: unit testing, integration testing, validation and verification, resource exhaustion, performance and usability.
To comment or not to comment
"Good code is its own best documentation. As you're about to add a comment, ask yourself, 'How can I improve the code so that this comment isn't needed?” — Steve McConnell
Most high-level languages allow you to write code that’s pretty readable. In general, the code should already explain how something is done and the goal, so before commenting evaluate if it’s completely necessary or if it's redundant.
"Things change, requirements drift, and your knowledge of the problem increases. Code needs to keep up."
Software development is a continuous cycle, as your code evolves you need to rethink your previous decisions. Maybe you discovered a duplication (violating the DRY principle) or you realized the design could be more decoupled. Here are some tips offered by Martin Fowler:
- Don't try to refactor and add functionality at the same time.
- Make sure you have good tests before you begin refactoring and run them as often as possible.
- Take short, deliberate steps. If you keep your steps small, and test after each step, you will avoid prolonged debugging