Developers around the world frequently make mistakes and write buggy code, but often these flaws can be discovered quickly. However, some mistakes can be hard to detect if they only lead to errors in very rare circumstances. There are plenty of reasons that programmers may not realize they have messed up while writing code, so we’ll go over some reasons for the most common mistakes too. Make sure you avoid these common mistakes by always paying attention, and testing your code thoroughly before ever using it in a production environment or public server.
Good Programmers Make Mistakes…
Every programmer makes mistakes, but that doesn’t mean they are a terrible developer. In fact, making mistakes is good for the learning experience. I can remember some of my worst mistakes better than my most significant successes. This is great because it helps me catch potential bugs in my code, and is beneficial for helping other programmers avoid critical issues in the systems we build for clients or ourselves. The difference between a bad programmer and a good programmer is that a bad developer will not test their code for every possible condition, or ignore potential concerns to try to finish the project quickly. But both good and bad programmers are going to make mistakes throughout development. It’s natural and expected.
#8. Syntax Errors
Although syntax errors are not the worst mistake you can make, they are very common. Even amazing programmers will occasionally forget to close a line with a semi-colon, or put a comma in the wrong place, put a value in the wrong spot for a function parameter, spell something incorrectly, or make a general structural error. They can be easy to find if they throw a fatal error or prevent code from executing, but this also may rely on proper bug testing. It’s always important to test each block of code for every possible condition including missing values, values of the wrong type, data in the wrong format, etc. Many times syntax errors slip through the cracks because they only affect one condition. If you don’t test for all conditions, it’s possible you are testing a feature without actually testing every single line of code. If you do proper bug testing, you can be assured that you will catch syntax errors before they affect a production environment.
#7. Value “Type Checking”
There are definitely pieces of code that can reasonably expect the correct type of value every single time. For example, if I create a function that is only ever used on hard-coded integers (numbers not supplied by a user / numbers written in the code itself), I can probably get away with not checking if the value is an integer inside my function. This is because I trust myself to make sure I only ever pass an integer to that function. Another example of this is if we are pulling an auto-incremented ID from a database. Because of our database engine, we know that ID is going to be an integer, so there wouldn’t be a need to make sure with any additional code.
#6. Data Formatting
Another common problem I see is with the way people format, or don’t format data. I have come across countless examples in systems of clients who relied on low quality development at earlier stages. We inevitably have to alter database values, storing procedures, and retrieval methods. For example, one time at Wubur (our web development company) we acquired a client with database columns for the publishing date of internal articles. However, instead of just having one timestamp or date column, the date and time were split up across many columns. There were separate columns for month, day, year, hour, and minute. To find the post date and time, there were 5 columns to pull the info from. To store the date of new content, those 5 columns had to have values provided to them. It just didn’t make sense when you can analyze and sort/filter dates much easier when the value is in one column. It’s also not hard to split up a timestamp into date and time parts, or even further to identify the exact month/day/etc.
In another old system, we discovered that the product subscription lengths were being stored like “2 Months”, “1 Year”, “15 Days”, etc. They were then using PHP to basically say “if subscription length has ‘months’ in it, take the number (2) and multiply by 30, to equal 60 days”. Then they looked at the current date and start date of the subscription to see if it had expired. In this case we altered their current database values and the associated logic to always store a number of days. We also went one step further and introduced an expiration date column to store the exact date of expiration so that we could easily find that data in the database without any date-based math.
#5. Scope Issues
There can be many issues with the scope of a project, and it’s not always a developer’s fault. If a programmer is not given proper details about the long-term goals and outcome of the project, they may struggle to properly design the system. For example, if you are selling one single product, you would design the check out process differently than if there were three products. If each of those products can be purchased at different price points or they can have different colors/sizes, the check out process and shopping cart changes even more. A developer needs to know the scope of a project to properly design each feature to not only accommodate current needs, but future needs to.
However, even if a developer understands the scope there can still be other issues. Sometimes coders will go “out of scope”, which essentially means creating features that aren’t included in a contract / proposal or they have over developed something that should have otherwise been much more simple. For example, in our early days at Wubur we had a developer assigned to add some account management features in the client’s user dashboard. The developer had been using Angular on another one of our projects, so he went ahead and used Angular for this client. The problem was that this client’s old system did not use Angular anywhere else. They went ahead and spent hours perfecting their models and data responses to work for the new features, and even converted some other features to use Angular as well. Although their code was well written, they were out of scope. They were told to build some simple features and comply with the current system’s format, but instead they went a much more complicated route. We were able to convince the client that using Angular did provide some significant benefits as an upgrade to their older website, so it all worked out, but we did have to help that developer understand the importance of not going out of scope and listening to specific directions or tasks.
#4. Confusing / Odd Code
This may be one of the most common mistakes, but it’s also one of the easiest to fix. I don’t have this issue anymore, but when I first started coding I made the mistake of writing confusing code. Code can be hard to understand for a variety of reasons… Avoid doing the following:
- Limited or zero comments in the code
- Too many comments in the code: Focus on why something is being done… You will most likely be able to figure out what the code does without comments
- Strange, generic, non-descriptive or unrelated variable names
- Duplicating code throughout the page instead of using a shared function or setting true/false values to trigger the desired code later in the script
- Too many if-else statements: Implement a ‘code strategy’ instead of relying on an excessive number of if / else statements in your code to account for all the different scenarios
Code should be beautiful. There should be helpful comments that help any future developers understand why your code is doing something, which makes it easier for them to understand and alter your work. Variable, method, function, and class names should be self explanatory. Developers should avoid excessively long or short variable names, and they should always be accurate. For example, if you create a function to handle profile image uploads, you could name it “imageUpload” or “profileImageUploader”. Well, if the function can be reused for other image uploads, profileImageUploader becomes a bit too specific and strange to use for other images – even if the code functionality works for all. Keep your function names specific when the situation calls for it, and more generic when the code is being used for a variety of current or future features.
#3. Duplicating Code
This is one of the biggest mistakes you can make in the development world. Whether you’re developing software, creating a website, or working on an app, you want to avoid duplicating your code. When code is copied and pasted across a system, any future changes to that code needs to be done in several places. If you are reusing the same logic or script, you should be utilizing a function, class, or method that allows the code to stay in one place and be used around your system. Let’s take a look at an example.
Example 1: A system saves a file with JSON information stored inside of it every time a user writes an article. The file stores the author id, article title, content, small description, and publish date. Imagine that there are four different ways to create a new article. Without a function or similar way of creating modular & reusable code, the developer would need to maintain four separate blocks of code for the article saving process.
Example 2: A system uses a function that accepts the article title, author id, content, small description, and publish date. The function is used by four separate files that send new article data. The website recently released an Android application that also allows users to share articles. It uses the same function that the web portal relies on because the app uses an API.
Scenario: The developers decide that saving articles in files full of JSON data is not a great idea. It’s decided that an SQL database will be used instead. In example 1, the developers need to modify four separate blocks of code to make this happen. In example 2, the developers modify the function and everything continues working well.
This might not seem like the biggest deal to you, but when you have dozens or hundreds of functions to handle events for a large system, it can be complicated already… Now imagine that same system without any functions or shared methods… That could be hundreds or even thousands of separate files being edited for every change. If you are ever duplicating your code, you’re doing it wrong. Code should be modular, reusable across the system, and if done right you can even take code from one project to use in another.
#2. OCD Programming Habits
While checking the type of data is important, it’s a great example to kick off our segment about OCD programming habits. OCD, or obsessive-compulsive disorder, in programming can take many forms. Imagine a person coming home, making sure their door is locked, and then checking to make sure the door is locked every few minutes. In programming, this can drastically slow down your system. So now imagine the following… A user submits a form and we analyze the received data. We check if all the data is of the right type, and sanitize it to make sure there’s no future XSS, SQL, etc vulnerabilities. We go ahead and save the data. Now that we know know 100% that the data is safe, we don’t need to check it constantly, but some programmers have a habit of doing so. Every time the value is analyzed, they’ll make sure it’s of the right type. Does this make sense? If we know for a fact that the data being saved will always be formatted properly and of the right type, it does not make sense to constantly verify this every time we use the data… much like it doesn’t make sense to check if the door is locked every few minutes if we know for a fact we did indeed lock it.
I remember seeing some old code in a client system that verified that an email address was in the valid format before inserting it into the database. When the email was used to send an email verification message, they checked if the email format was valid. When the person clicked the link in their email to verify their address, the system would then verify that the email was a valid address again. So the code checked to see if the email was a valid format three separate times. This didn’t make sense because the code specifically disallowed non-valid emails in the database, so the system should be designed in a way that trusts that the emails in the database are of the correct format. There are definitely cases where verifying data more than once should be protocol, but in many cases it is unnecessary. While this example seems quite simple, other forms of OCD programming habits can drastically affect a system.
#1. Inconsistent Coding
Every developer can look back and notice differences between the way they used to code and the way they code now. For the most part, the developer will improve their skills and write more efficiently. However, it might be less likely to see noticeable changes between the project start and end date unless it’s a long-term project. With longer projects or systems that are being reworked years later, it is very important to remain consistent. There are times when you must make changes to your coding style mid-project, but for the most part consistency is vital. This doesn’t mean the code should not improve. It should always improve, but it should not differ in style or format entirely just because you learned about a new library or coding method – unless it truly makes sense for the project.
Acknowledge, Accept, Adapt
It is very important to acknowledge your mistakes, whether it is to yourself, your team, or even your employer. This allows you to recognize that you have written broken code, or designed something in a way that does not comply with industry or project standards. Once you have acknowledged this, you can accept that you have made a mistake and learn from it. This allows you to adapt your thinking and coding skills / style to be better in the future. Sometimes you may even have to adapt current code to make sure it’s working, secure, and efficient. Or perhaps you just need to adapt for the future. Regardless, it is very important that you follow the Triple A rule. Acknowledge your mistakes. Accept that they are yours and could have been prevented. Adapt your skills and mindset to prevent making the mistake again.