Home » Software Security Blog » The Ultimate Programming Best Practices Guide
1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

“Person[] software_Developers_who_FollowProgrammingBestPractices;” What’s wrong with this variable name? Find it out in our ultimate programming best practices guide. Discover how to get a better developer experience, write clear software, and ace your coding skills. Awaken the geek in you now

Did you know that the number one software security vulnerability listed in the Common Weakness Enumeration’s (CWETop 25 Most Dangerous Software Weaknesses is caused by programming mistakes like buffer overflows?

Everyone can make mistakes. But, when you hire constructors to build your new home, you expect them to ensure that the house is safe when you move in. In the same way, coders are expected to make sure they aren’t leaving any vulnerabilities open for hackers to exploit. Because as the Latins said:

“Errare humanum est, perseverare autem diabolicum” (To err is human, but to persist is diabolical).

In our previous article, you discovered seven essential coding languages to know for your cyber security coding career. Now, we’ll take you a step further and show you actionable programming best practices you can’t do without. With time and practice, this will help you become a first-class programmer. Learn how to avoid costly mistakes and improve your coding skills, no matter what programming language you use. It’s time to get serious and level up your coding game!

7 Programming Best Practices You Need to Know

Throughout my career, I’ve met people coding in very different ways. Even in my team, each developer had their unique way of programming. And rightly so — software development has its creative side, too. However, even if there are different ways to write code, the best practices that’ll help you become a better programmer remain the same.

Too busy coding to read an entire article? Take a quick coffee break and learn about the ultimate programming best practices with our summary table below.

Programming Best PracticeExamples
1. Follow a Coding Standard
  • Computer emergency response team (CERT) standards. Available for several programming languages like Perl, C, C++, or Java.
  • Motor Industry Software Reliability Association (MISRA). The preferred coding standards for products related to the automotive industry.
2. Write Clear Code
  • Effective naming
  • Clear structure and alignment.
  • Stay DRY: Don’t Repeat Yourself.
  • Add comments and documentation.
  • Organize your files and folders.
3. Ensure Your Code Is Easy to Maintain
  • Standardize your headers.
  • Reuse your code, don’t duplicate it.
  • Avoid Hard-Coded Numerical Values.
4. Check Your Code (Before Code Review)
  • Raxis.
  • Sonarqube.
  • PVS-Studio.
  • Klockwork.
5. Secure Your Code
  • Run pen-tests.
  • Add input validation to your code.
  • Allow only encrypted connections to your database.
  • Be careful with authentication information (e.g., login credentials).
6. Use the Right Tools
  • Code and artifact repositories.
  • CI/CD pipeline engines.
  • Containers.
  • Integrated development environments (IDEs).
7. Refactoring
  • Tools like various IDEs.
  • Methods like refactoring in test-driven development, extractions, and renaming variables.

1. Follow a Coding Standard

Do you want to create clean, readable, and efficient code? Follow the coding standard related to the language you’re using and the software you’re writing. Why? Because the right collection of rules and techniques will enable you to write code that:

  • Matches product and users’ expectations, and
  • Meets business requirements.

Coding standards vary from industry to industry, and they’re very specific. If you’re writing software for a smartphone app, you’ll follow a different standard than if you were writing software for a Tesla car.

Usually concocted by software development and security communities, these standards are periodically updated and published on the internet. The most popular are those promoted by:

  • Computer emergency response team (CERT). Are you programming software in Perl, C, C++, or Java? Check their coding standards on CERT’s website. They’re free to download and you can give your contributions by adding your comment and recommendations.
  • Motor Industry Software Reliability Association (MISRA). The name says it all. It publishes the preferred coding standards for products related to the automotive industry, focusing on safety-critical industries in general. Only downside? Its publications aren’t available for free.

2. Write Clear Code

Developers come and go, and if they didn’t write clear code, it results in a wave of confusion when they leave. The last time it happened in my team, we learned the hard way how important it is to write code that’s clear and readable for everyone — not only computers.

The guy left and, a few days later, a key software program he wrote stopped working. The other developers in the team wanted to fix it but it took them ages to figure because of how it was written. The software’s security team had to do without it for weeks until the situation was rectified. In the end, it was clear that the best solution was to completely rewrite the software (and so they did). This time, the programmers and developers applied the following programming best practices to ensure the code was readable for all and easy to fix in the future.

Use Effective Naming

If you ever had a toddler asking for something, you know how difficult it can be to decrypt their request because they have their individual way of doing so. (For example, a term like “binky” may mean blanket or pacifier to them.) Programming is the same thing: call things by their name and everyone will understand you; get it wrong (i.e., use non-standardized terms) and they won’t have a clue what your code is about. Let’s have a look at an example:

private String dn;

Do you know what “dn” stands for? Of course not, you could only guess, but it could be anything. What if I write it like this?

private String developerName;

This looks much better, right? A good naming should also be effective, though. Do you remember the variable example at the beginning of this article?

Person[] software_developers_who_FollowProgrammingBestPractices;

Did you figure out what’s wrong with this variable? It’s too long and the naming is inconsistent. Do you want a better version?

Person[] DevelopersFollowingProgrammingBestPractices;

Can you still understand the meaning of the variable? I think so. This means that it’s clear enough but more concise. Did you notice that I capitalized the first letter of each word? This is a way to keep a consistent naming scheme. I could have also used underscores between words, which is the preferred method of PHP scripts like I did in the next example.

Last but not least, what if you’re writing SQL queries and keywords? Don’t forget to capitalize special words.

Create Clear Code Structure and Alignment

Don’t you hate when you have to scroll right to read a sentence? I find it extremely annoying and difficult to follow. It gets even worse when the structure isn’t clear enough in coding. To avoid all this, be sure to:

  • Limit your line length. Don have more than 80 columns.
  • Use the space key when you have to indent. This will make exactly four spaces like used in most languages, while the tab key won’t.
  • Limit your use of nesting. Nesting refers to code that performs a specific function contained within another code with a broader function and how that code is formatted. A good nesting limit is no more than four levels.

Let’s see an example of a badly structured code. The following example screenshot is code that allows you to check and report the working status of a/b/c/d. If they’re working, it’ll display the message “Working!” Otherwise, every time that one of them isn’t working properly, it’ll display the message “a/b/c or d broken.”

The code below has four levels of nesting (indicated by each “true”). It basically asks if conditions are true before getting to the code to run. It’s still readable because it has ‘only’ four conditions, but can you imagine with 10? It’d be a mess and would leave most people scratching their heads.

example of badly structured code
This is an example of badly structured code

If you remove the nesting, though, and put near each condition the exit instructions, the code structure becomes much clearer:

what the improved code looks like
This is what the improved code looks like. No more nesting!

Isn’t the second example much easier to read and understand?

Stay DRY: Don’t Repeat Yourself

Do you remember when you were a kid and your parents were repeating the same things to you over and over again? We all had it and we all hated it. The same happens with coding. Headers and footers are typical examples. Isn’t it better to create a separate file to reference wherever needed instead of repeating the same header and footer on each code page? Here’s how you can do that:

$this->load->view(‘includes/header’);

$this->load->view($main_content);

$this->load->view(‘includes/footer’);

Looking for more examples? Check another DRY scenario with JAVA codes.

Add Comments and Documentation

Let’s go back to my story about the developer who left the team. Well, unfortunately, the guy didn’t only write unreadable code; he also didn’t write any documentation about it, either, for us to reference. And this just made things worse for us because we were left scrambling to figure everything out when his application broke.

Want to be better than him and leave your team in a good position? Make sure you:

  • Write proper documentation. I know that it can be a boring task sometimes. However, having useful document can make a huge difference both for you and your team. Many of the teams I worked with used Confluence, others GitHub wiki as repositories. Regardless of which one you choose, just be sure to create these necessary resources.
  • Add comments only when necessary. Comments should be used to explain why you did something, not to explain your code. If your code isn’t clear enough, rewrite it, but don’t add redundant comments. Let’s consider the following example: ‘int pf;’ Do you want to clarify its meaning?

Don’t write a comment: int pf; //printfrequency
Improve your coding instead: int printfrequency;

  • Be specific. Make a habit of describing the issue. For example, if you want to assign a specific task to a colleague, you should clearly explain the action required and the owner of the task. Would you know what to do if you’d find this comment?

//TODO: make it work.

I don’t think so. In the above directions, you don’t know who is being directed to do something, or what the something is that needs to be done. What if I change the comment like this?

//TODO: (@John) implement xyz for stability.

Now, John knows exactly what he has to do and that he’s responsible for handling it.

Do you want to know more about what we discussed till now? Check the Massachusetts Institute of Technology (MIT) Communication Lab’s best practices for coding and comment style.

Organize Your Files and Folders

Think about your last coding project: would you be able to find a specific file quickly if asked? Would I be able to find it as well if I’d have to work on the same project and you weren’t available to ask? If the answer is no, then you should organize your files and folders more consistently. The following tips may help you:

  • Create a unique main folder for each project. It doesn’t matter if it’s a big or small project. The main folder should always be only one.
  • Include a README file. This is the first thing I look for when working on a project. Why? Because it contains all the information needed for a quick start: what the project is about, the way files are organized, and where further information can be found.
  • Keep your files small. The bigger the files, the more complicated they’ll be to read and maintain. Make sure that each file is dedicated to just one function or one feature.
  • Name your files properly. Before you pick a name for a file, ask yourself whether anyone would know what’s included in the file just by reading its name? If the answer is yes, then you’re good to go.
Bad File Name ExamplesGood File Name Examples
button1.pngsubmit_button.png
very_final_versionversion_4
  • Don’t forget to create a changelog file and copy licenses. The first one will include information about changes made on every version or revision. The second one will contain the license covering the software and any third-party licenses.
  • Use the right file structure. Depending on the size of the project, you may want to opt for a simple or more complex hierarchy like the examples available on GitHub.

Check the MIT Communication Lab’s File Structure page for more recommendations and tips.

3. Ensure Your Code Is Easy to Maintain

When I visited Easter Island, I was fascinated by those big heads carved in stone (Moai) by the Rapa Nui people. Sculpted hundreds of years ago, they’re still standing there, nearly unchanged. Codes aren’t like this. They aren’t set in stone. You constantly have to update, fix, and extend them. This is the reason why it’s so important that they’re written in a way that makes them easy to maintain. How can you do that?

Standardize Your Headers

Even when you have different modules, ensure you always follow the same header format for each one. For example, a header should include the following information:

  • Module name
  • Creation date
  • Author of the module
  • Modification history
  • Module summary
  • List of the functions supported in the module
  • List of the variables accessed or modified by the module

Reuse Your Code, Don’t Duplicate It

Duplicating code, while easy, creates a slew of issues. If you make changes to your cloned code but those modifications don’t propagate to all of your duplicated instances, it’ll result in corrupt code and errors. Making changes to a code with a lot of duplicated code is looking for trouble. What if (like it usually happens) the change doesn’t propagate to all duplicated instances? Your code will be corrupted. Isn’t it better to create reusable code by developing functions performing each unique task?

Avoid Hard-Coded Numerical Values

Check the code below. It’s a bit of a small truck dispatch program. Can you figure out what the 150 number means?

hard-coded numerical value
an example of a code including a hard-coded numerical value (magic number)

The number of boxes delivered? Nope. The number of boxes ready for shipment? No. What if I write it like this instead?

well explained numerical value
an example of a well explained numerical value

Now, can you guess what the 150 number refers to? In this case, it refers to the number of boxes that each truck can contain. That was much more straightforward, right?

Now, take the same examples and imagine that you have to have to change the number 150 to 250. In the second example, you’ll just have to update the value in one place, while in the first example, you’ll have to go through the whole code and update the magic number one by one.

4. Check Your Code (Before Code Review)

As we said at the beginning, everybody makes mistakes. Nobody is perfect, not even the best programmer. This is why it’s essential to constantly check and test your code even before a proper code review takes place. Adding a static code analysis tool to your continuous integration development process, where every change is integrated, tested, and verified, can be great. It’ll enable you to get almost real-time feedback on every piece of modified code and the affected execution paths without executing it.

Wanna try it for yourself? Pick one or more static code analysis tools among the ones listed below.

Raxis
The tool won’t only check that your program is working as designed, it’ll also run penetration tests to find security vulnerabilities. (We’ll talk more about securing your code in a bit.)

Sonarqube
This tool offers thousands of static code analysis rules covering 29 programming languages. It also has a free version.

PVS-Studio
Available for C, C++, C#, and Java, this tool is also compatible with Windows, Linux, and macOS. It matches warnings to MITRE’s Common Weakness Enumeration (CWE), SEI CERT Coding Standards, and supports the MISRA standard for automobiles.

Klockwork
This tool analyzes codes written in C, C++, C#, Java, JavaScript, Python, and Kotlin. Built with a focus on the devsecops process, security is integrated at the heart of the development process.

5. Secure Your Code

Insecure coding often results in vulnerable applications. Relying on unsafe applications puts your customers as well as your organization’s brand and reputation at risk. This is especially bad news when you take into account that 85% of organizations interviewed by Imperva were victims of a successful cyberattack in 2021. It’s even worse when you consider that 75% of customers will stop doing businesses with organizations that have data breaches.

Following programming best practices for writing secure codes can greatly minimize those risks. Here are a few examples.

Run Pen-Tests

Take your white hat out of the closet and start breaking into your code to early identify weaknesses, errors, and vulnerabilities. Use:

  • Exploit kits. With pen-testing frameworks like Rapid7 Metasploit, you’ll be always a step ahead of the game.
  • Fuzz testing. Automated tools to find out the reaction of your application to certain behaviors (including malicious ones). BeSTORMCode Intelligence, or Mayhem for Code are just a few examples of the numerous fuzz testing tools available on the market.
  • Scanners. Scan every corner of your codes and applications to prevent attacks like SQL injections (i.e., a malicious code that could interfere with the queries that an application makes to its database.), XSS (i.e., cross scripting, or malicious code inserted in your web application), and more. Try Invicti scanAcutenix scanner, or the open-source Zed Attack Proxy (ZAP).

Want your pen test to be more effective? Put security first in your development lifecycle by implementing secdevops.

Add Input Validation to Your Code

If your code allows user input, do you really want to allow users to enter any type of input without restrictions? Let me give you a practical example. I use WordPress. Do you know what one of the first things I did at the time I set up my website? Ensure that every comment was set for review before it would be published. I didn’t like the idea of my readers viewing spam, phishing, or dodgy links in the comments. The same goes for programming.

Writing a code without including any form of input validation is like leaving the door open to attackers.

javascript form validation
an example of a JavaScript form validation

In the example above, we’re ensuring that if the form field fname is left empty, this function shows an alert message (e.g., “Name must be filled out”), and returns false (meaning that the submission won’t go through).

Allow Only Encrypted Connections to Your Database

The majority of databases allow unencrypted connections by default. However, some others (e.g., Microsoft SLQ server) encrypt only the initial authentication process. What does it have to do with your code? Well, if you’re programming an application that requires users to enter their usernames and passwords to access it, that sensitive information will be transmitted in plain text (i.e., it’s susceptible to man-in-the-middle attacks). Don’t let the hackers celebrate — ensure your database traffic is always encrypted.

  • Change the configuration to only allow secure, encrypted connections.
  • Install a trusted  secure socket layer/transport layer security (SSL/TLS) certificate on your web server.
  • Configure your application to validate the digital certificate to establish a secure connection.

Be Careful With Authentication Information

Usernames, passwords, and authentication errors are all very sensitive and precious information that could resonate all over the press if they end up in an attacker’s hands. Look what happened recently to GitHub — 100,000 users were impacted when stolen OAuth tokens were used.

  • Never store passwords in plain text. Salt them (e.g., add a random string to the hashed password) and hash them using a strong hashing algorithm before storing only the salted password hash. (Never store the passwords themselves.)
  • Remove sensitive data before publishing your project. Did you just publish your project on GitHub and suddenly realize that you forgot to remove some credentials and tokens from it? You’re not alone. Make sure you know how to remove them and how to avoid accidental commits in the future.
  • Be somewhat vague with your error information. When you write how your code should handle authentication errors, make sure you don’t give out too much information. Why? A malicious third party may read it and use the information at their advantage. Take the examples of bad authentication errors below: the attacker would know that the user ID he entered is incorrect or that the user doesn’t exist. It’s like a poker game: never give out too much information if you want to have a chance to win.
Bad Authentication Error ExamplesGood Authentication Error Examples
Login failed, incorrect user IDLogin failed, invalid user ID or password
Login failed, the user doesn’t existLogin failed, invalid user name or password

Find more information and examples about authentication error handling on OWASP’s authentication cheat sheet.

6. Use the Right Tools

Would you clean your chimney with a toothbrush? You could, but it would take ages, a lot of effort, and the end result would be pretty poor. The same goes for coding. If you really want to follow programming best practices, you must have the right tools to do your job. Is money an issue? No problem, there are plenty of open-source tools that you can use.

Code and Artifact Repositories

  • Code repositories. Are you coding an application together with other developers? No worries, you’ve got options. Code repositories like GitHub are used by millions of people, and Bitbucket, a cloud-based hosting service for projects, enables you to keep track of source code changes and versions.
  • Artifact repositories. Every time you commit a change, a continuous integration/continuous development (CI/CD) pipeline produces a build. Artifact repositories like CloudreponpmJFrog, enable you to store, organize, and share all builds, making them available for the whole team. They’re essential for rapid releases, easy version tracking, consistency, and enhanced collaboration.

CI/CD Pipeline Engines

JenkinsGitLab, and AzureDevOps are among the most used CI/CD pipeline engines that enable developers to get continuous and effective feedback about their coding. Why did we include them in our programming best practices guide? Because they streamline software development and delivery, they enable you to develop higher-quality code, minimizing human error. How? Through automation of testing, production, and monitoring.

ci cd pipeline flow
The graphic shows the CI/CD pipeline flow.

Containers

How can you make your code work exactly the same on different infrastructures throughout the whole development lifecycle? Using virtual machines (VMs)? Yes, that could be an option, but do you really want to put all that burden on your CPU? Containerization software tools like open-source Docker or podman will run the software without killing your CPU while making your job much easier.

Integrated Development Environment (IDE)

Are you still using a simple text editor for your coding and switching from application to application just to check your code for errors? Then it’s time to switch to IDEs, the developers’ virtual workplace. An IDE includes all the basic tools needed to write and test your software (e.g., a source code editor, build automation tools, a debugger, and the possibility to install several different plugins). If you’re developing mobile applications, you’ll even get an emulator.

Using an IDE will help you boost your productivity and development speed by having everything you need at your fingertips. A few popular examples of IDEs include:

  • Eclipse IDE. One of the most popular IDEs for Java. It offers a sleek interface, includes drag-and-drop functionality, and the possibility to do static analysis. The same company also offers other IDEs supporting other languages.
eclipse org
Image source: Eclipse.org.

  • AWS Cloud9. This cloud-based IDE supports real-time analysis and more than 40 languages. It’ll enable you to write, run, and debug applications with just a browser, without installing a local IDE.
aws cloud9
Image source: AWS Cloud9.

  • SlickEdit. It’s a highly customizable IDE that supports more than 70 programming languages. It’s excellent for coders who need to develop in multiple languages across multiple platforms.
slickedit homepage
SlickEdit homepage

  • Visual Studio 2022. This IDE is suited for mobile and desktop apps but also works on Windows, Linux, and macOS. It has a wide range of features (e.g., debugging, real-time collaboration, version control, code completion tool, refactoring, etc.) and supports several languages.
visual studio 2022
Visual Studio 2022

7. Refactoring

Too busy to focus on small improvements? Think again. Taking the time to implement seemingly minor enhancements could make a big difference with regard to the quality of your code and project. Have you ever participated in “Fix-It Fridays”? At one of the companies I worked for, Friday was our development team’s fix-it day (unless there wasn’t an urgent issue to resolve of course). On that day of the week, every developer was free to pick something to work on and do some small improvements. Some examples include:

  • Fixing small bugs,
  • Testing a new library,
  • Reducing code complexity, and
  • Improving code readability, maintainability, structure or functionality.

This, essentially, describes refactoring: you clean your code without altering its behavior or creating new functionalities. How? Using some tools and applying some standard methods.

Tools

Do you remember the IDEs we talked about a few minutes ago? Many of those tools like Eclipse IDE and Visual Studio include automated refactoring, too, allowing you to speed up the process. Of course, automated refactoring isn’t essential as you can also opt for the manual method. But they can be a great help, especially when you don’t have a lot of time to dedicate to refactoring.

stepsize refactoring example
Stepsize refactoring example

Methods

Refactoring can be done in several ways. Let’s have a look at some of the most popular methods.

  • Refactoring in test-driven development (TDD). Very much used in the Agile methodology, tests are written before writing the code. If the test fails, the code is refactored and then tested again.
test driven development test
Refactoring is an important step of the test-driven development test.

  • Extract function. A piece of code is moved into a new method and renamed in a way that’s easier to understand its function. This helps reduce complexity and improve code readability.
example of extract function
An example of extract function included in Martin Fowler’s online refactoring samples catalog.

  • Extract variable. Did you find a piece of code with duplication or that it’s difficult to understand? This method will enable you to put the result of long and complex expressions (or part of them) into a less complex separate variable.
example of extract variable
Example of extract variable taken from a catalog summarizing all refactoring examples included in Martin Fowler’s book Refactoring.

  • Rename variable. Very often you find code that has variables with a confusing name. Check the example below; what does ‘a’ refer to?

flat a=height * width

It could be anything right? What if I write it like this instead?

flat area=height * width

Isn’t that clearer? This is what the renaming variable in refactoring does.

Now, we’ve gone through a bunch of programming best practices that could add that little something to your coding. However, if you choose to follow all or some of them, it might take you some time to get familiar with them. So why should you do it? This is what we’re going to answer next.

Why Should You Follow Programming Best Practices?

Have you ever tried to guide a blindfolded friend through a trail full of obstacles only using your verbal instructions? Believe me, it’s very hard. Instructions, if not clear enough, can be interpreted differently. Your friend may get on the wrong track or get a big lump on their head by bumping it against an obstacle because he misunderstood your guidance.

In a way, coding is like helping someone get through this obstacle trail without damage. Write your software code wrong and it may end up doing something totally different from what you expected. If you’re lucky, it could lead to a minor glitch or to a major security issue if you aren’t.

Here’s a cute example to demonstrate how unclear directions can lead to problems:

This is why programming best practices are there, to help you write a software that’s:

  • Reliable. In other words, it works as it should, all the time, without failure.
  • Secure. It’s impossible or very difficult to hack.
  • Maintainable. It can be repaired, improved, and expanded with ease.
  • Portable. It works in every environment without issues.
  • Testable. It can be easily tested. Tests can be automated and controlled without effort.
  • Safe. It doesn’t cause issues when used or implemented.

But what are the key benefits of following programming best practices?

  • Code uniformity. Often new developers join the team in the middle of a project. Following best practices will ensure that the code remains consistent even if different employees or contractors write it.
  • Fewer errors. As the errors will be easier to detect, the code will contain no or few mistakes.
  • Faster development, lower maintenance costs, and reduced time to market. By making the code simpler, easier to read, and maintain you’ll get effective high-quality software in a shorter amount of time.
  • Better employability. Following industry best practices is now included in the key requirements of many companies’ job descriptions.

And remember, like the game programmer John F. Woods once said, “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.”

Final Thoughts on the Ultimate Programming Best Practices Guide

Programming best practices are there to help developers ensure that all codes are written in a way that makes them secure against attackers, easy to read, test, use, and maintain by any authorized users. Because when we code, we write for others (those who’ll have to read it), not only for ourselves.

If you want to improve your programming skills and progress from being an amateur to a professional developer, you’ll definitely benefit by incorporating the best programming practices mentioned in this article into your software development routine.

Don’t wait any longer! Turn experience into expertise. Become a top performer that writes only error-free, efficient, and usable code.