Aim: To learn the basics of how to use functions and sub-routines to make code more manageable.
- What is a function?
- What is a sub-routine?
- Why and how should they be used?
If we were to code using only assignments, statements, conditions and loops, then we could produce some very sophisticated scripts and applications. Unfortunately as they got more complex they would be harder and harder to read, and there would likely be a lot of repetition.
In order to help us, scripting and programming languages have functions and sub-routines (sometimes called non-returning functions).
Sub-routines or non-returning functions
A sub-routine allows us to execute multiple statements from a single statement. This helps us to simplify our code.
If we have a function named countToTen…
Sub countToTen() For i = 1 to 10 step 1 Print i Print newLine End For End Sub
Then every time we need to display the numbers 1 to 10 we can simply call the sub-routine…
This means that every time we need to count to ten, we now have a function that reduces the code by (approx) 5 lines, and is understandable to read.
If we sometimes wanted to count up to different numbers then we could write a lot of different sub-routines such as countToFive and countToTwentySeven. The number of sub-routines will quickly build up if we continue along this line. Instead we can solve this problem by making use of parameters.
Parameters are variables that are set when a value or expression is passed in the sub-routine/function call.
In our example, we could pass in the number that we would like to count up to, as a parameter…
Sub count(num) For i = 1 to num step 1 Print i Print newLine End For End Sub
This could then be called multiple times with different numbers. So we could count from 1 to 5, then count from 1 to 10 and then count from 1 to 27 with three simple statements…
count(5) count(10) count(27)
Sub-routines (or non-returning functions) are particularly useful when you want to tell the machine to do a particular list of instructions, but you don’t need any direct response.
When we would like to get a result from a list of statements we can use a function. A function is similar to a sub-routine, but has a return statement (and a type in strongly typed languages)…
Function doSomething(usefulParameter) // Main code block End Function
If we take another look at our counting sub-routines, and consider a new requirement. We now need to be able to save the results to a file. A simple change we could make is to create a new sub-routine that is specifically for writing the count to a file, and pass in a file name as an extra parameter…
Sub countToFile(num, fileName) For i = 1 to num step 1 writeToFile(i, fileName) writeToFile(newLine, fileName) End For End Sub
A problem with this would be that if our requirements changed again (and they nearly always do) we could start building up a large number of new sub-routines.
- we need to send the count to a web-service, a database, a network port, a printer, or any number of other devices.
- we want to append the count to the file in some cases, but overwrite the file in others.
- we want to add start and end tags to the count for compiling into XML files.
Another alternative to multiple sub-routines is that we make one enormous sub-routine that takes all of these options as parameters and uses conditions to split processing across multiple clauses. This would take us back to the problems discussed earlier relating to complexity and repetition of code.
Instead we could take a step back and look at what it is that the count sub-routine/function is trying to achieve. In each case we are writing text (the number count) to something. So if we can get that text then we can use that in any number of different ways.
Function generateCountText(num) Declare result For i = 1 to num step 1 Add i to result Add newLine to result End For Return result End Sub
Then if we want to write the results to the screen, we can call it as follows…
If we want to write the results to a file, we can call it like this…
text = generateCountText(10) writeToFile(text, "count.txt")
The design of functions can have vast impact on the quality, usefulness and re-usability of the code we write. Well-named functions with useful and usable parameters that have a specific efficient purpose lead to readable and maintainable code. Functions that are badly named, have awkward parameters or do not have a clear purpose are much less likely to be used and maintained correctly.
Feedback on 1.04 Functions and Sub-Routines
If you have any questions or suggestions relating to this article or any other then please fill in our feedback form and let us know what you think.