Functions and Methods

Functions or Methods allow the programmer to take a bit of logic and encapsulate it to allow it to be easily used. When we build a function, thought should be made towards the reuse of the encapsulated logic.

Doesn't reuse and generalization make the resulting code somewhat larger? Usually it does, but at what cost? For one, improved maintainability of the code. Additionally, the overall code base becomes smaller since several versions of the code are replaced with a one slightly larger one.

OK, so the value of functions can be seen. How do we go about deciding what should be made into a function and what shouldn't? Let's ask the following questions. If any of the answers is yes, it is a candidate. If several are yes, it is a good candidate.

  • Is there no existing function that performs the task?
  • Does the code (or a very similar version) appear in multiple places in the existing code?
  • Does this piece of code perform a single operation that is clearly separate from the surrounding code?
  • Is the logic for this piece of code particularly complex and confusing?
  • Does this code perform an operation that could be usable in other areas of the code?
  • Can this code be generalized to provide an operation that would have general use?

OK, how well did your target code meet the criteria? If none of the questions came up yes, you might still want to write a function. I won't stop you. But if you do, take reuse into account.

How to write functions

Remember the recipe example? We start by deciding what our function should do. Let's start with something simple, like a list of names we want to sort.

$names = array("Mary", "Jill", "Chris", "Daniel", "William");
0Mary
1Jill
2Chris
3Daniel
4William

Now, what method shall we use to sort the list? How about a bubble sort, or a Quicksort? No.

First rule of writing a function is don't if one already exists. In PHP there is sort() which sorts an array, so we are done.

sort ($names);
0Chris
1Daniel
2Jill
3Mary
4William

Wasn't that easy?

Let's get more complex. Order them by length? Let's try. We will start by looping through the list and adding each one to an array based on length. Then we go through that list and add them sequentially to a new array.

function sortByLength($names) { $sizes = array(); foreach ($names as $name) { $len = strlen($name); $sizes[$len][] = $name; } // sort lengths ksort ($sizes); $new = array(); foreach ($sizes as $len => $ns) { // sort names of the same length sort ($ns); $new = array_merge($new, $ns); } return $new; } $sort = sortByLength($names);
0Jill
1Mary
2Chris
3Daniel
4William

Simple, no? No.

OK, so why did things get so much harder so fast? For one, we used a number of functions we haven't discussed before. Let me emphasize again that we should always look for existing functions to solve our problem before we go off coding.

Isn't there something easier than this? Glad you asked. Yes, there is. Again we go back to the predefined functions in PHP. In this case usort().

function compareStrlen($a, $b) { // if the lengths are the same, compare the strings if (strlen($a) == strlen($b)) return strcmp($a, $b); // otherwise return the comparison of the lengths return (strlen($a) < strlen($b)) ? -1 : 1; } usort($names, "compareStrlen");
0Jill
1Mary
2Chris
3Daniel
4William

Notice the results are identical, but with half the code.

Let’s boil this down to a simple workflow:

  • Identify your objective.
    If you don't clearly know what you are trying to do, it will be difficult to achieve.
  • Determine if functions exist that can simplify your problem.
    Avoid writing code that someone else already has.
  • Use the most direct approach to the solution.
    If it seems difficult, likely you are approaching the problem from the wrong direction.
  • Make sure the solution is maintainable.
    Look for ways the solution might need to change in the future.
  • TEST.
    Test everything, even things that don't seem necessary to test.
    Pay special attention to the following:
    • Bad input
      Never assume users do everything right.
    • Boundary conditions
      The beginning or end of a range of valid values sometimes causes trouble with your algorithm, check 0 as well.
    • Assumptions
      We often overlook the obvious.
    • Warnings
      Always test with the highest level of error reporting to catch coding errors that don't directly break code.

These are a few basic guidelines, but it's a start. Never stop learning how to do things better.