Defensive Programming: A Proactive Approach to Security and Reliability

Think back to some of the very first applications you made when you were learning how to code.  Chances are that you wrote a simple console application of some kind, and showed it to a friend or family member–who promptly broke it by typing “yes” instead of “Y”, putting in the word “two” when asked for a number, or giving the a value that couldn’t be parsed the way you expected.  Chances are that you went back into your code and wrote in conditions to handle invalid input.  When you did that, you were using “defensive programming” – a technique that ensures software functions correctly, even when faced with unexpected inputs, situations, or user behaviors. 

Photo by Annushka Ahuja

The goal of defensive programming is to reduce the chance of errors, crashes, and/or security vulnerabilities in the applications you write.  It involves thinking of the things that could go wrong as you write code, and trying to catch potential problems before they happen.

Defensive programming is important because it improves the reliability and maintainability of the programs we write.  By anticipating errors and preventing them from happening, programmers can reduce bugs, crashes, and security vulnerabilities in the code.  Another plus is that defensively-written code is often more verbose and easier to understand and maintain, which can save development teams time and effort in the long run. 

How you can you start implementing defensive programming practices? These bullet points will give you some tips:

Validate & Sanitize User Input

  • Use conditionals to check that any user input is valid before using it in your application.
  • Consider using loops to force users to try input until it matches the desired pattern.
  • Sanitize any user input that will be used programmatically.  For example, concatenating user input directly into a SQL query is a good way to open up your application to SQL injection attacks.

Handle Errors 

  • Check for errors and handle them gracefully to prevent your application from crashing.
  • Use appropriate error messages to help users understand what went wrong and how to fix it. 
  • Wrap potentially dangerous operations (reading data streams, file input/out, opening databases connections, etc) in try/catch statements. 
  • Catch exceptions only when you are expecting a failure in a specific part of your code and have a plan for how to handle that failure.

Think Security

  • Restrict users’ access to resources, data, and functions to just what is necessary in order to limit the risk of security vulnerabilities.
  • Use strong passwords, encrypt and/or hash sensitive data, and avoid leaving hard-coded passwords or other sensitive information in your code.

Keep Things Simple

  • Write code as clearly and logically as possible, using descriptive variable and function names.
  • Avoid writing code that is hard to understand; simple code is easier to maintain and less likely to contain bugs.
  • Maintain a consistent formatting style while coding.  If you are working on a company project, follow your company’s code style guide.
  • Conduct code reviews with teammates or mentors to ensure that your code follows best practices, and to catch potential issues before they become bigger problems.

Test Early & Often

  • Start your application after you finish writing small pieces of functionality, and manually test each piece with different types of input.  Try to cause errors on purpose and see if the application breaks.
  • Write unit tests for your code to ensure that the software functions as expected, and that adding new pieces of code do not break any existing functionality.  Again, do this when you finish writing small pieces of functionality

Defensive programming is an essential practice for building reliable, maintainable, and secure software. By anticipating and preventing errors, we can reduce the risk of bugs, crashes, and security vulnerabilities in our code–and following best practices such as validating input, checking for errors, and testing early and often can help ensure that your code is resilient, bug-free, and safe!

Add a Comment