Contents

Functions and Methods

After five chapters worth of Katas, you may have noticed that the quiz game program is becoming quite large. In this chapter we’ll look at how large computer programs can be split up into smaller components using functions and methods.

Splitting things up

A big part of being a programmer is knowing how to take a complicated system and split it up into small, easy-to-understand components. Even the most complicated things in the world - super computers, fighter jets, supernovae - are made up of small components. The complexity of all these things is built up through the small, specialized components, that interact with each other.

Let’s look at the Teaching a robot life skills example again to see what I mean.

Teaching a robot more life skills

The instructions to make a cup of tea were:

‘Put some water in the kettle. When it’s boiled put a teabag in the cup. Then pour the water in. Wait a bit then take out the teabag.’

Remember how difficult it was to teach the robot to follow these instructions? We needed to write very specific instructions that the robot could perform. The more specific we got, the longer and more complicated the instructions became.

Let’s have another crack at it. This time we’ll write a book that will instruct the robot to create a perfect cuppa from scratch.

Each page will describe a specific part of the tea making process. We’ll title each page with something that describes the instructions each page contains.

Page 1 is the first page the robot will read. Let’s title it ‘Tea Making’.

On page 2 we can write instructions that tell the robot how to fill up the kettle with water. Let’s title that ‘Kettle Filling’.

On page 3, we’ll write some instructions that can tell the robot to turn on the kettle and wait for it to boil. We’ll call title this page ‘Kettle Boiling’.

On page 4, we’ll write instructions that tell the robot how to pour water into the cup. We’ll title this page ‘Kettle Pouring’.

On page 5, need some instructions that tell the robot how to put the teabag in the cup, and and how to take it out. We’ll call this ‘Brewing the Tea’.

Now we can start filling in each page with instructions. On the first page we can write something quite general. Like this:

If the kettle is empty then turn to page 2 for Kettle Filling
To boil the kettle turn to page 3 for Kettle Boiling
To brew the tea turn to page 5 for Brewing the Tea
To pour water into the kettle turn to page 4 for Kettle Pouring
Let's be nice and fill the kettle up for the next person; turn to page 2 Kettle Filling

On the page titled ‘Kettle filling’, we might write:

If the kettle lid is closed then open the kettle lid
Grab the kettle and place it under the tap
Turn the tap on
Wait until the kettle is full
Put the kettle back on the table
Close the kettle lid

When the robot reads the book, it will start following the instructions on Page 1 - the first page. Page 1 provides general instructions, and directs the robot to other pages for more details.

On Page 1 we don’t have to repeat ourselves too much as we can refer to the same page multiple times, like we do with the ‘Kettle Filling’ page.

Each page also has a title that describes the instructions it contains. This makes it easy for the person writing the book to understand how the instructions work together. By scanning Page 1, we can easily see which what over-arching tasks are required to make a cup of tea without looking into the specific details of each task. If we want to make any changes to the instructions, it’s much simpler to see which page we need to make the changes on since they have been given descriptive titles.

Functions

Computer programs are structured in a similar way to the book we just wrote. However, instead of splitting up into pages, computer programs can be split up into groups of instructions called ‘functions’.

Imagine we were writing an operating system for the tea-making robot, instead of a book. In a made-up programming language, we might write something like this:

Function Main()
    If the kettle is empty then
        KettleFilling()
    End If

    KettleBoiling()
    Brewing()
    KettlePouring()

    Output("Being Nice!")
    KettleFilling()
End Function

Using made-up programming languages, or ‘pseudo code’, can help computer programmers think about how to solve computer problems without worrying about the specifics of any particular programming language - this is why I’ve used pseudo code here.

Looking at this example, we have defined a function called Main(), which is the entry point of the program. That means the program will start executing the instructions from the top of Main(), and continue in order until the end.

Inside Main(), we run, or ‘call’, several other functions, such as KettleBoiling() and Brewing(). The double brackets, or parentheses, indicates that these are function calls.

When a function is called, the execution of the program stops. The called function is then executed. When the function execution is complete, the program carries on from the place the function was called.

For instance, we call KettleFilling() from Main. The KettleFilling() function might look like this:

Function KettleFilling() 
    If the kettle lid is closed Then 
        OpenTheKettleLid()

    GrabKettle()
    TurnOnTap()
    WaitUntilKettleIsFull()
    PutKettleBack()
    CloseKettleLid()
End Function

Similarly to Main(), KettleFilling() works by calling functions which perform more operations. However, notice that these functions are more specific than those in Main(). Well designed programs work by having very general function calls that call down to functions that do increasingly specific things.

Arguments

Functions can be provided information in the form of arguments. We’ve seen arguments a lot throughout this book, and for functions the principle is the same.

For instance, say we wanted to fill the kettle by a certain amount. We can alter KettleFilling to take an argument amountInLitres:

Function KettleFilling(Integer: amountInLitres)
    // Some instructions to fill the kettle...
End Function

When KettleFilling() is called, we must provide a value for amountInLitres inside the parentheses. It could be called from our main program like so:

KettleFilling(1)

Providing 1 for the value of amountInLitres.

Outputs

Functions can also produce outputs. Say we wanted KettleBoiling() to provide us with information about how long it took for the kettle to boil. We could amend KettleBoiling() to say it is going to produce a number that represents the amount of seconds it took to boil the kettle. In pseudo code it might to look like this:

Function KettleBoiling() : Integer
    Calculate timeToBoil...

    return timeToBoil
EndFunction

Functions that have outputs are said to ‘return’ data to the place they are called.

KettleBoiling() will return the value of ‘timeToBoil to the place it was called in Main().

In Main(), KettleBoiling() could be used like so:

amountOfTimeToBoil : Integer = KettleBoiling()
Output(amountOfTimeToBoil)

A variable called amountOfTimeToBoil is assigned to the return value of KettleBoiling.

Remember, the above is written in a completely made-up programming language - not C#. The concept of functions is almost universal to all programming languages. Therefore, in order to be a great software engineer, it’s important to separate your understanding of the concept of functions from how they work in C# specifically.

Functions in C#

Now you know the theory, let’s see how functions work in C#.

In C#, a fundamental way to split up a long program is using a ‘method’. The term ‘method’ is, more or less, C#’s name for a function. The terms function and method can basically be used interchangeably.

Methods are blocks of code that exist under a unique name. The code inside the method can be executed elsewhere in the program by referencing its name. This is known as calling the method. A method written in C# might look like this:

void WriteAlertMessage(string alertMessage) {
    Console.WriteLine("ALERT: " + alertMessage);
}

This method is called WriteAlertMessage. It asks for a alertMessage of type string as an argument, and writes the word ALERT along with the alertMessage it was provided.

WriteAlertMessage can be called by using its name elsewhere in the code. Calling it might look like this:

int ageInYears = Convert.ToInt32(Console.ReadLine());

if (ageInYears < 18) {
    WriteAlertMessage("You must be 18 or older to use this program!");
}

In this example, the program asks for the user’s age. If the user younger than 18, it calls WriteAlertMessage with the message it wants to write. The program’s execution will jump to WriteAlertMessage. When the method is finished, the program will jump back to where WriteAlertMessage was called and continue.

Methods can also provide information to the part of the program that calls them. This is done using the return ‘keyword’.

A keyword is a reserved word in the C# language that already has a meaning. We have seen many of these already - int, float, and so on. If you try and use a keyword outside of it’s intended use - like creating a variable with the name int - then C# will complain.

More methods

Let’s introduce a new method to this example, GetAlertMessage:

string GetAlertMessage() {
    string alertMessage = "You must be 18 or older to use this program!";
    return alertMessage;
}

The program can then be amended to use GetAlertMessage:

int ageInYears = Convert.ToInt32(Console.ReadLine());

if (ageInYears < 18) {
    string alertMessage = GetAlertMessage();
    WriteAlertMessage(alertMessage);
}

This program does the same thing as before. However, the alertMessage variable is assigned to the return value of GetAlertMessage. When GetAlertMessage is called, it uses the return keyword to supply alertMessage to the caller.

Let’s look in a bit more detail at how methods work.

Anatomy of a method

Methods in C# are made up of several fundamental components. These are:

  • Return type
  • Name
  • Argument list
  • Body

The return type, name, and argument list, together form a method’s signature.

Return type

As we’ve seen, methods can supply, or ‘return’, information to callers. To do this they must specifying the type of data they return. Consider the signature of GetAlertMessage:

string GetAlertMessage();

The signature starts with string. This is the ‘return type’. It means that callers can expect GetAlertMessage to return a string when they call it.

Now consider WriteAlertMessage:

void WriteAlertMessage(string alertMessage);

This one has a void return type. void is a special type in C# - it basically means ‘nothing’. For methods, void return types mean nothing is returned from the method call.

Methods with a non-void return type must use the return keyword to supply some information to the caller.

Name

This is hopefully self-explanatory! The name of the method is just that - the name. The rest of the program will use this to call the method. Method names must be unique, and the name ought to clearly describe what each method does.

Argument list

As we’ve seen, methods can ask for information through arguments. They do this by specifying a list of arguments they require in order to operate. This is similar to how arguments are used in the Command Prompt, as you’ve seen in the first Kata.

Arguments are similar to variables. They have a type, and a name. Callers must provide arguments if the method signature asks for them.

Consider the signatures of GetAlertMessage and WriteAlertMessage again:

string GetAlertMessage();

void WriteAlertMessage(string alertMessage);

GetAlertMessage has empty brackets - (). This means it doesn’t ask for any arguments.

WriteAlertMessage has (string alertMessage). This means it’s asking for one argument, called alertMessage, of type string. Callers must supply the relevant information in order for WriteAlertMessage to work.

Methods can ask for multiple arguments, separated by commas. For instance, if WriteAlertMessage was asking for 2 arguments it would look like this:

void WriteAlertMessage(string alertMessage, string alertTitle);

Body

This is the code that the method will be executing. Methods must have a body, otherwise they don’t do anything! In the body, the method can reference its arguments by name and use them like normal variables.

Let’s look at WriteAlertMessage again:

void WriteAlertMessage(string alertMessage) {
    Console.WriteLine("ALERT: " + alertMessage);
}

The body of WriteAlertMessage is the bit in-between the curly braces. Notice that the alertMessage argument can be used inside the method as if it was a variable.

Learning how to use methods is essential to writing good C# programs - in fact, it’s essential to writing good code in any programming language. In the next Kata you’ll see how to write methods in C# for yourself.

Copyright Mikiel Agutu 2019