If you are a beginner programmer, this article is not meant to make you feel bad about the mistakes that you might be making, but rather to teach you to spot signs of them, teach you how to spot them, and remind you to avoid them. Update: This article is now part of my book “The Professional Programmer”.
Not Taking Breaks
You are a human and your brain needs breaks.
- Integrate something in your workflow to force you to take breaks. Break even if you don’t feel like it
- Leave your chair and take a short walk to think about what you need to do next.
Not Understanding that Code Problems Will Cause Data Problems
Even the smallest bugs in a program’s code will result in an unpredictable state for the data it manages.
- How do you protect yourself?
- Use multiple layers of data integrity validations. Do not rely on the single user interface. Create validations on front-end, back-ends, network communications, and databases.
Having the Wrong Attitude About Errors
Errors are a good thing. They mean you are making progress.
- Look at them as helpers. You need to leverage them to make progress.
- Some errors need to be upgraded to exceptions. Exceptions are user-defined errors that you need to plan for.
Obsessing About Best Practices
The term “best practices” implies that no further research is needed
- There are no best practices, and some of the best practices may be outdated
- Focus on what you can do best
- Question everything, challenge all theories, know all your options, and make only educated decisions
Not Questioning Existing Code
As a beginner, you should just assume that any undocumented code that you do not understand is a candidate for being bad. Question it.
- Only when you completely understand the code you get to form an opinion whether it is bad or good. Do not assume anything before that.
Underestimating the Importance of Code Quality
If you can only focus on one aspect of the code that you write, it should be its readability
- Look at coding as a way to communicate implementations
- Your main job as a coder is to clearly communicate the implementations of any solutions that you are working on
- Always code as if the guy who ends up maintaining your code knows where you live
- Even the small things matter
- Anything beyond 80 characters is much harder to read
- Break long code into smaller chunks that can be tested and managed separately
- Use double negatives
- Using short, generic, or type-based variable names
- Hard-coding primitive strings and numbers without descriptions
- Thinking that longer code is better
- The excessive use of conditional logic
Over-Using Shared State
Every variable we define represents a shared state. It holds data that can be changed by all elements in the same scope as that variable.
- Try to keep new states contained in small scopes and make sure they do not leak upward.
Picking the First Solution
While the first solution might be tempting, the good solutions are usually discovered once you start questioning all the solutions that you find
- Your job as a professional programmer is to find the simplest solution to the problem
- There are two ways to construct a software design: one way is to make it so simple that there are obviously no deficiencies, and the other way is very complicated and there are no obvious deficiencies
Planning for the Unknown
Always write the minimum amount of code that you need today for the solution that you are implementing.
- Handle edge-cases, sure, but do not add edge-features. Growth for the sake of growth is the ideology of the cancer cell.
Planning Too Much Before Writing Code
Planning before jumping into writing code is a good thing, but even good things can hurt you when you do too much of them
- Do not look for a perfect plan. Look for a good-enough plan, something that you can use to get started
- Too much planning is simply a waste of time, especially when planning small features
Having the Wrong Attitude Towards Code Reviews
Look at every code review as a learning opportunity
- Thank your reviewers when they teach you something
- Sometimes, the reviewer will be wrong and it will be your turn to teach them something – teaching is one of the most rewarding activities that you can do as a programmer
Writing Code Without Planning
Writing quality programs is a process with a flow
- Think. Research. Plan. Write. Validate. Modify.
- Create a habit to always go through the right amount of these activities
- Coding is also a way to communicate your thoughts
- When reviewing code, count to 10 before you refactor a line. If the code does not have tests, a hundred.
- Samer Buna
Obsessing About Performance
If you cannot measure the suspected performance problem with the code, do not attempt to optimize it
- Any non-obvious optimization that is carried out on any existing code without measurements is considered harmful and should be avoided
- What you think could be a performance gain might actually be a source of new, unexpected bugs
Not Picking the Right Tool for the Job
Tools are continually improving and you need to get comfortable learning about them and using them.
- You need to familiarize yourself with the tools available to you and keep an open mind about the new tools that you can start using.
Making Existing Code Worse
Duplicating code
- Using unnecessary conditional statements and temporary variables
- Not using configuration files
- Extending a function with a branch logic instead of introducing another function
- Every time you think you need an if-statement or a new function variable you should ask yourself: am I changing the code at the right level or should I go think about the problem at a higher level?
Not Using Encapsulation
Not using encapsulation often leads to harder-to-maintain systems
- In an application, a feature should have only one place that handles it
- Within a class of logic, self-contained pieces of tasks should get their own methods
- Methods should do one thing and do that thing well
- Similar classes should use the same method names
Writing Comments About the Obvious Things
Structure your comments to answer the question of WHY this code is being written rather than “what is this code doing”
- Don’t be tempted to write a what comment to clarify the code
- Some comments add unnecessary noise to the code, so remove them
Not Using Source Control
Commit often and commit early
- Use present tense verbs in your commit subject line
- Be detailed with your messages
- If you need more than a few lines in them, that is probably a sign that your commit is simply too long
- Source control is about clear history
- Commits can help you identify what code introduced a bug
Reinventing the wheel
Unless you actually need a wheel that is not used in its typical design, do not reinvent it. Just use the damn wheel.
- The cool thing about software wheels is that most of them are free and open for anyone to see their internal design. Use open-source wheels if you can.
Not Writing Tests
If you are not writing tests in code, you are most likely testing your program some other way, manually
- There is nothing wrong with manually testing your code
- Start by guessing or designing your validations even before you write the code to satisfy them
- Testing-driven development positively affects the way you think about your features and how to come up with a better design for them
Not Using the Right Data Structures
Using lists (arrays) instead of maps (objects) to manage records
- Not using stacks when writing simple recursive functions
- Push function calls to a Stack yourself and start popping them out when you are ready to traverse the calls back
Assuming That If Things are Working Then Things are Right
If you do not write a test case to document your decision, future maintainers of your function will have no clue if your ignoring of negative numbers was intentional or buggy
- Problem #1: There is no handling for empty input when the function is called without any arguments
- No handling of invalid input
- Not all valid cases are tested
- Problems #1 and #2 are sometimes referred to as edge-cases
- Solution: Reduce accepts a second argument to be used as the initial value for the accumulator.
Not Targeting the End-user Experience
The easiest way to add a feature to an application is to look at it from the point of view of the user, not how it fits in the current User Interface.
- Think about the ways to make the feature easy for the users to find and use
Not Quitting
When it comes to writing programs, the right mentality is fail early and fail often.
- The minute you begin doubting a solution, you should consider throwing it away and re-thinking the problem. This is true no matter how much you were invested in that solution.
Not Googling
Google It First
- Unless you are using a bleeding-edge technology, chances are someone else ran into the same problem and found a solution for it.
- Do not assume that you know everything needed to pick a solution to a problem. Google will surprise you.