DEV Community

Adam Roynon
Adam Roynon

Posted on

What is Defensive Coding?

Defensive coding is a way of ensuring your program or code continues to function under unforeseen or unintended circumstances. Imagine a hacker or malicious user is trying to find vulnerabilities in your program, such as seeing the contents of a database, you want your program to not reveal any secure information or break in such a way that reveals vulnerabilities. Another reason to write defensive code is to prevent a normal user from accidentally making your program halt or perform in an unintended manner.

Let's look at a simple example and how we can write some defensive code around it to protect it against unintended usages. The below code snippet shows a simple function that takes two parameters and returns the multiplication of those two parameters. This function obviously should take two numbers as the parameters, but what would happen if a string or a boolean is passed into the function instead?

function multiply(a, b){
  return a * b;
}
Enter fullscreen mode Exit fullscreen mode

We could add an if statement to the function to ensure that both parameters are above the number 0, this would ensure that they're number variable types. This change to the code is shown below, if the parameters are not numbers (e.g. booleans or string) or are not positive numbers, they are not above the number 0, the function will return the number 0 otherwise it will return a multiplication of the two parameters. The two numbers passed into the function. This if statement does include defensive code but it stops the function from returning the multiplication of numbers below or equal to the number 0.

function multiply(a, b){
  if(a > 0 && b > 0){
    return a * b;
  }
  return 0;
}
Enter fullscreen mode Exit fullscreen mode

We can change the function by checking the variable type of the two passed in parameters. The code below ensures that both parameters are of the variable type 'number' and if they are it returns the multiplication of the two numbers otherwise it returns the number 0. This would allow negative numbers or decimal/floating-point numbers to be passed in and the multiplication of those returned.

function multiply(a, b){
  if(typeof a == 'number' && typeof b == 'number'){
    return a * b;
  }
  return 0;
}
Enter fullscreen mode Exit fullscreen mode

Defensive coding is a way to prevent your program from 'acting up' under strange or unforeseen circumstances, such as the wrong parameter variable types being passed into a function. The example shown on this page is very simple and defensive coding can become more complicated or include checking other things and not just numbers. For example, if you are processing a file you may want to check that the file exists and you have permission to access the file before trying to process it. Try catch blocks can be used to attempt a process and then catch any errors or exceptions, and run a different code path if any errors occur.

This post was originally published on https://acroynon.com

Top comments (9)

Collapse
 
cappe987 profile image
Casper

Returning 0 when things go wrong is bad practice, since 0 is a valid output for a regular multiplication. You wouldn't expect "hello" * "world" to return 0, would you? Now you would need to check before calling the function too if both params are valid, otherwise you wouldn't know if the function did multiply them or not.

In cases like this it might be more appropriate to throw an exception and catch it when you do the multiplication. That way you can handle the error in a way that fits the situation.

Collapse
 
acroynon profile image
Adam Roynon

I believe this can be argued either way. I didn't want to get into exceptions and what they are in this post, as I wanted to concentrate on just defining what defensive coding is and how it looks.

Returning a valid value is a good way to avoid returning null values and therefore littering your code with null checks. It can also prevent increasing the cyclomatic complexity of your code.

Throwing an exception would require a new code path to be created. If you just threw the exception without handling it then your program would exit immediately, making the code brittle and therefore not 'defended'. In the example of the 'multiply' function you either put a try/catch in this function and still have to return a value, or put a try/catch higher up and have to define a new code path.

Both ways are completely fine, but depending on the context of the surrounding code/functionality one may be a better choice.

Thank you for the feedback and comment, I really appreciate it.

Collapse
 
polmonroig profile image
Pol Monroig Company

Strongly typed languages reduce the number of defensive coding needed.

Collapse
 
acroynon profile image
Adam Roynon

It definitely reduces the amount of type checking you have to do but that doesn't mean strongly typed languages are necessarily better than dynamically/weakly typed languages.

Collapse
 
polmonroig profile image
Pol Monroig Company

Yeah, wouldn't say they are better, just different hahaaha

Thread Thread
 
acroynon profile image
Adam Roynon

Yes, you can hit problems in both, just different problems.

Collapse
 
patarapolw profile image
Pacharapol Withayasakpunt

Now, how can I integrate this into my TS/JS projects, because of not-so-true static typing, and any casting...

Collapse
 
acroynon profile image
Adam Roynon

I'm not sure I fully understand what you mean here, but to improve the defensive coding of your program I would suggest breaking stuff down into small to manage functions and then thinking about the edge cases and potential problems those functions may face (e.g. wrong inputs, missing inputs, etc) and add some code to defend against those cases. Similarly to how I show the progression of a normal multiply function and then adding code to handle edge cases.

Collapse
 
brownio profile image
Antonio Djigo

Maybe someone will be interested in Guard Clauses if they arrived here!