JavaScript LogoThere is no need to tightly couple a function and the other function that might call it, by sweating the details of the arguments passed in. You can access the local “arguments” variable, examine it, and decide how to handle the situation

Somewhere, I still have the code from my first fairly serious JavaScript project. From time to time, I like to take it out and look it over. It’s riddled with functions that, while written in good spirit, clearly reveal my level of inexperience at the time. This is not something I am proud to discuss publicly, but it is the truth. And, I always tell myself that everything is relative; some day I will look back on code I wrote last week and recoil with the same horror. Programming is a never-ending learning process and while the initial learning curve is steep, the process never ends; we always strive to improve our skill set.

One of the things that really stood out in my mind was how many functions I wrote that looked something like this:

While I don’t think it’s completely insane that I would write a function that takes so many specific arguments, I’ve come to realize that this approach tightly couples the function with the other function that might call it. The reason I keep mentioning “…might” is that in many cases, we write functions that are probably called in the lifetime of the program, but as many JavaScript apps are event-driven, it is not unusual for events to sometimes not happen, which means that functions are sometimes not called.

The point here is that tightly-coupled functions are, of course, sometimes unavoidable, but to me, it always seems a shame to have to write a function that is tightly coupled to its caller, but may never be called. So, I started to think about decoupling these functions from each other as much as possible. Granted, a function like “updateRecord()” will likely only be called to… well… update a record, but we can make it a bit more generic so that we don’t have to worry so much about what arguments were passed in when we write our code. We can simply write the function as if all the arguments we need have been passed in, and then “handle” the corner cases where some arguments are missing. This also frees up the caller in that there is reduced stress, as well, from that end; the caller can pass-in all the expected arguments, some of them, or none of them. What happens in these cases is, of course, up to us, but it does not always have to be an “all or nothing” scenario.

 Example # 1

In Example # 1, we don’t assume any arguments are passed in. We first test to see if the local “arguments” variable has a length that is greater than 0. If it does, great; we can then do something with the arguments. Most likely, we will want to examine them and see if the ones we need are available.

It is important to note that the “arguments” variable is not a true JavaScript array. The subtle details of this are worthy of another post. But keep in mind, it is simply a local variable that is array-like, in that it is an indexed list that can be iterated over and it does have a “length” property.

 Example # 2

In Example # 2, we loop through all of the arguments. Inside the loop, we could examine each argument and see if it meets the needs of the function.

Example # 3

In Example # 3, we pass an object in as the argument to our “updateRecord()” function. What is helpful about this approach is that the “updateRecord()” function does not break or throw an un-handled exception if we pass in too many arguments, not enough arguments, or no arguments. The function simply covers the following:

  1. Were any arguments passed in?
  2. If more than zero arguments were passed in, let’s loop through each one
  3. On each loop, if the argument being examined is an object, let’s loop through its properties
  4. On each sub-loop, we can do something with each property

Granted, your function may be a bit useless unless the exact number of arguments are passed-in and they are named in some exact way. But, your function does not have to be completely useless. It can handle corner cases gracefully, return a useful error, or maybe even partially carry out its intended task. The assumption here is that you or someone on your team will write this function and the one that calls it, so in the end, you can implement your own logic to make this function useful, yet unbreakable.

Summary

This topic is more of a pattern than a specific implementation. I like to use it because I prefer to keep my functions as loosely coupled as possible. It may not always be possible to keep them 100% uncoupled, but I prefer a pattern in which I can pass a function the right, wrong, or partially right number of arguments, and that function can inspect what it gets and handle the situation gracefully. A big plus when passing in an object, is that you can at least not worry about the order of the arguments; you simply grab the passed-in object, and enumerate the properties. What you do with what you find is up to you.

Helpful links for the JavaScript arguments property

https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments

http://javascript.info/tutorial/arguments

 http://stackoverflow.com/questions/5303003/best-use-of-the-arguments-property-in-javascript