In an earlier post I discussed how we can reuse code by creating our own user-defined JSL functions. The most common reason I hear for not creating user-defined functions is that the code is only being used once, hence there is no requirement for reuse. But there are many benefits to creating our own functions – far beyond code reuse. In this post I’m going to explore some of those benefits.
Think about the process of writing code. A script consists of a sequence of JSL statements. We might write those statements from beginning to end or more likely we go through some iterative process where we edit and refine the code. Sometimes that refinement is because we are struggling with the syntax of the language and sometimes it’s because we are struggling to formulate the problem clearly in our heads.
It’s very unlikely that we write the entire code as one seamless thread. Actually what we do is to chunk up the code and write blocks of it step-by-step with each block performing a specific task. For example we may have a block of code that opens a data table and then another block which performs some data manipulation and then another block of code which creates a graph. When we write our script our minds will focus on each of these tasks one at a time. In essence we are doing in our heads what functions are designed to do!
Whilst the obvious benefits of using functions is that we can define a piece of code once and use it multiple times there is another benefit and that is that they help us develop building blocks which we can use for code construction just in the same way that we can use bricks to construct a wall.
Another way of thinking about this construction process is that we are abstracting our thought process away from the detail of the JSL syntax to a sequence of workflow tasks. We can then focus our attention on each of these steps in isolation without having to constantly carry the big picture in our minds. This abstraction is the primary benefit of creating user-defined functions. And the benefit goes far beyond the mechanics of writing JSL code. Have you ever revisited code that you wrote maybe six months ago and not quite understood how the code works or why you did something in a particular way? Functions provide us with a language that is abstracted above the raw JSL syntax . Take a look at this script:
Load Data(); Reshape Data(); Create Report();
The script describes what it is doing as opposed to how it is being done. If we want to understand how it’s done then we can look at the definitions of the individual functions. But if we just want to change the way the script works we only need to worry about the sequence of function calls.
Functions are a way in which we can make our code more modular. We can have components of code that plug-and-play to perform specific tasks. To facilitate this it’s important that we give some thought to how we chunk up our scripts. At an extreme level I could have a single function called Do It All! Which of course doesn’t give any insight into its purpose.
To help us think about an appropriate level of chunking there is what I refer to as the golden rule of functions. That rule is this: when I define a function I want to be able to give the function a name which is descriptive of the tasks that are performed by the function. That might sound reasonable and obvious but in practice it gives us a discipline of making functions have a clear purpose. It’s often beneficial to give the function the name after we have written the content of the function. Then take a look at the code and find a short name which is descriptive of the functions purpose. If that leads to a function name such as “open data stack it and create a scatter plot” then probably the function is not being defined at the appropriate level of granularity. If you need a long sentence to describe what the function does then most likely it could be broken up into multiple functions each performing specific tasks.
Here are some example functions that I use quite frequently.
Window Exists( windowName ); Unique List Items( lst ); Is Table Open( tableName ); Display Error Message( msg ); XY Graph( xCol, yCol );