Showing posts with label Defensive programming. Show all posts
Showing posts with label Defensive programming. Show all posts

Thursday, March 20, 2025

Defensive Programming Pt 2 - Try Catch Throw, Finally.

 Defensive Programming Pt 2 - Try Catch Throw, Finally.

 In this second part, we look at what we can do or how we can deal with errors when they happen.  We’ve already looked at how to check if a field that we want to programmatically interact with is there and if it’s the type we’re expecting.  Now let’s look at the built-in feature referred to as ‘Try-Catch’ that we can use to help us deal with errors in JavaScript.  Before we do, let give some context.  When we write code, there is always a part that does something, maybe it’s a calculation or making a field mandatory.  Let’s suppose we’ve made a mistake in the typing, which will cause a code crash.   We never want the code to crash, it’s just not a good look. 

If we use the example from before, but lets make a change so it fails.  We’ll change setValue(now);  to SETvalue(now);

 

ContactEvents = {
   setDate : function(executionContext){
      let formContext = executionContext.getFormContext();
      Var dateFld == formContext.getAttribute("new_lastcontactdate");
         if(null !== dateFld){
            var fldType == dateFld.getAttributeType();
            If (fldType == "datetime"){
               var now = new Date();
               formContext.getAttribute("new_lastcontactdate").SETvalue(now);
            }
            else {
               return;
            }
         }
         else {
           return;
         }
   }
}

In the runtime, this will create an error with a message popping up in the user interface.  The standard messages are designed for programmers and don’t mean much, if anything at all to the end user, if anything it just annoys them and puts them off using it.

 Obviously, mistakes will happen but, we can do our best to minimise any issues and shield the user from the often terse message that gets popped on to the screen.

 

Let’s Try and Catch that error

NOTE:  Let me reiterate, these posts are not meant to be teaching you ‘How’ to write programs, or as any form of definitive guide, they are here to trigger some thought processes and answer some questions at a higher level.

 

JavaScript has this neat feature, shared with other languages too, that allows you to trap an error and decide how you deal with it. It’s referred to as the ‘Try-Catch’ and here in its most basic form is the skeleton code for the JavaScript Try-Catch


try {
  Block of code to try
}
catch(err) {
  Block of code to handle errors
}

The ‘try’ block braces go around your execution code. In our example for the setDate function the code is really simple and there is only one real area that is likely to cause an error.   However, as you build up more code and complexity, you may have multiple execution lines that could cause a potential error.  You don’t need to have 1 try catch around each line, but also, you don’t want to have one try-catch around your entire set of functions.  It’s all about getting the balance right.  I like to keep my try-catch blocks small and distinct, by which I mean I try and group them to match the function, or areas within a function that makes sense (to me at least).   There are lots of software blogs out there that can give you more guidance on when and where to use the try-catch, my advise is start small and get comfortable with using it.

 Here is our setDate function with the try-catch added. 


ContactEvents = {
   setDate : function(executionContext){
      let formContext = executionContext.getFormContext();
      Var dateFld == formContext.getAttribute("new_lastcontactdate");
         if(null !== dateFld){
           
            var fldType == dateFld.getAttributeType();
            If (fldType == "datetime"){
               var now = new Date();
               try {
                  formContext.getAttribute("new_lastcontactdate").SETvalue(now);
              }
              Catch(err){// this is where we deal with any errors from the above try
                 alert(“There has been an error setting the date: ” + err);
              }
            }
            else {
               return;
            }
         }
         else {
           return;
         }
   }
}
 

In our example above the 'try' block is around the line that sets the last contacted date only, so if, there is an error detected, we (as the programmer) know where it is. The catch segment gets passed the error from the application and it stores it in the parameter (err in this example) which we can then use.  You can use google to find out more about the error object created by the system and what’s available for you to use in your code, the two key things you may want to look at are: ‘name’ and ‘message’.

So now we know that we can put a fence (try) around parts of our code that might error.  Typically, I like to put them around pieces of code that I know will be an issue if there is a mistake or if there is something that could be influenced or changed later (like someone removing field that code updates, for example).  We’ve also seen that we can ‘catch’ the error and put up a nicer more meaningful message.  We can also put more code inside the catch block to do something else and this will only execute if there is an error that occurs inside the try block.  But wait there’s more!

Throw me something to work with

When we are working with a user and asking them to input data in a form, for example, they don’t always do what we want or expect them to do.  Lets say we have an unconstrained number field as an input, but for some reason we want them to enter a number between  5 and 10.    We can use the ‘throw’ to create an more elegant error message that is presented to the user.   Here below is an example of a how we’d use the ‘throw’ command.   I’ve taken this example directly from https://www.w3schools.com which by the way, is great resource to help you learn more about programming languages and their syntax.  I refer to their website all the time.


<!DOCTYPE html>
<html>
<body>
<p>Please input a number between 5 and 10:</p>
<input id="demo" type="text">
<button type="button" onclick="myFunction()">Test Input</button>
<p id="p01"></p>
<script>
function myFunction() {
  const message = document.getElementById("p01");
  message.innerHTML = "";
  let x = document.getElementById("demo").value;
  try {
    if(x.trim() == "") throw "empty";
    if(isNaN(x)) throw "not a number";
    x = Number(x);
    if(x < 5) throw "too low";
    if(x > 10) throw "too high";
  }
  catch(err) {
    message.innerHTML = "Input is " + err;
  }
}
</script>
</body>
</html>

Let’s look at how it works.  In the try block, you can see there are multiple ‘if’s and they are checking the value which has been entered by the user. At the end of the ‘if is the ‘throw’.  It is really just setting that error object we touched on a little while ago.  Depending on which ‘if’ gets activated, the error message in the ‘error’ object will be set to the value that is thrown.

Now we know how to do some simple form validation, verification, put a fence around potentially erroring creating code, and catch the error if one occurs, we  can even create our own custom messages too.

finally!

Isn’t it great!  We can check to see if in advance if we expect there may be an issue, we can verify what the fields on forms are (the type we expect),  we can put guards around the area that might create errors for things outside our control (and our syntax or spelling mistakes ) and we can make the messages to the user more palatable, but what we’d really like to do is ensure that the program continues to work and the user or the appropriate person gets what is expected and that the error can be dealt with appropriately.  This is where the final piece of the puzzle comes in, right at the end and it's the ‘finally’ clause.   With the ‘finally’ clause you can execute code after the try -catch regardless of the result.

 Here is our sample with the ‘finally’ clause added in.  For the purpose of this post we’re only going to raise another alert, but in the real world this where you would put the code that needed to run regardless of whether or not there was an error.  We don’t always need a finally clause, but its good practice to start using it as often as you can.

ContactEvents = {
   setDate : function(executionContext){
      let formContext = executionContext.getFormContext();
      Var dateFld == formContext.getAttribute("new_lastcontactdate");
         if(null !== dateFld){
           
            var fldType == dateFld.getAttributeType();
            If (fldType == "datetime"){
               var now = new Date();
               try {
                  formContext.getAttribute("new_lastcontactdate").SETvalue(now);
              }
              Catch(err){// this is where we deal with any errors from the above try
                 alert(“There has been an error setting the date: ” + err);
              }
              Finally {
                  alert(“we’ve hit the finally clause, this will run after the try catch regardless”);
              }
            }
            else {
               return;
            }
         }
         else {
           return;
         }
   }
}

Summary

Defensive programming is all about doing our absolute best to elegantly handle the unexpected.    When using JavaScript for form manipulation in D365 for example, we first looked at how using a NameSpace can avoid the wrong function being called then we went on to look at how we can test to see if a field is there (by assigning the field to a variable and checking it’s not null) ,  then we looked at how to check it’s the right type of field (using the getAttributeType function) .  Next, we looked at how we can add guard rails around sections of code that might error (using the ‘try’ block).   We then looked at how we can handle errors that do happen (using the ‘catch’ block).   We even looked at how to create our own error messages (using the ‘throw’ function) and then how we can make sure that the ‘critical’ or ‘must always happen’ code still runs (using the 'finally’ clause). 

 We don’t need to use all these techniques all of the time, but they can be used with great effect to save us (and others) time and therefore money in the future.  The bigger a project gets, the more code you write, the more time consuming it becomes to find and fix errors, especially the ones that don’t present themselves consistently.  Avoiding crashes is ALWAYS better than trying to fix the aftermath…

 External references used – W3 Schools (https://www.w3schools.com/ )

How to Create a PCF by Neeraj Agrawal

 I came across this great introduction to PCF controls today and rather than try to compete and write a similar post myself, I thought I...