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.

Source