In the last installment of this series, we began to touch on the fundamental structure of programming languages, it’s grammatical structure, so to speak. To get a better grasp on how programming languages are organized, let’s take a step back and get a top-down view.
At the uppermost level, there is the program itself. This is the total collection of all the instructions that are required to make the program do what you want it to do.
This program can usually be broken into one or more chunks of code that, for the purpose of these lessons, we’ll call modules. I’m using this word in a generic sense, as the actual terminology varies from language to language. You can think of modules as being all of the instructions necessary for a particular feature of the program, contained in one body. Each module should be able to perform its tasks totally independently of the other modules in the program. In fact, in the purest sense of this concept, a good programmer should strive to never have the modules of the program interact directly with one another. Which is to say, they should be able to function without error regardless of the state or presence of the other modules. (Modules that behave this way are sometimes called “agnostic.” It turns out that programmers are also amateur philosophers.)
Confused yet? Don’t worry, it gets better. We’ll play a little game at the end of this article that will help illustrate to your kids these relationships.
So, inside these modules, you’ll find more specialized blocks of code that we’ll call methods, though, again, the exact terminology will differ from language to language.
Methods are a collection of instructions and expressions (which I’ll explain here shortly) that achieve a specific task. Typically, a method receives zero or more values, which are commonly called “arguments” or “parameters,” manipulates those values in some way, and returns a single value. It can create what are known as side effects, but I’ll go into much more detail on this in future lessons.
Finally, we have our most basic components: expressions and instructions. These are the individual lines of code that make up the bulk of a program. They can exist alone, or in combination to create more complicated statements.
The easiest way to think about the difference between expressions and instructions is this simple distinction: expressions always reduce to a single value while instructions tell the computer to do something. So, the command “puts 1 + 2” has an instruction (puts) and an expression (1 + 2) that work together to achieve a specific task. In this case, it prints the number 3 to the console.
A distinction should be made between the definition of a method and the calling of that method. In the above example, “puts” is actually a method, which is defined within the Ruby core library. When it is called, “puts” behaves like an instruction. It tells the computer to output some value, but does not really reduce to any useable value (it does, in fact, return a nil value, but its usefulness is unlikely). Its counterpart, “gets,” can be treated like an expression, since it reduces to a single value (a string input by the user), which can then be further manipulated.
Here’s a very simple module called ‘Arithmetic’ to look at as an example of these concepts:
Now, how in the heck are you going to explain all of this to your tweens?
How about this simple game that expands on the game from my last article:
Let’s focus on teaching the hierarchical relationships. Start by coming up with a task that can be broken into smaller parts. This will represent the program. How about baking a cake? That’s simple enough, right? Now, brainstorm with your kids about all of the things that have to be done in order to bake the cake.
Let’s say you come up with the following tasks:
1. Gather all of the right ingredients
2. Measure and prepare the ingredients
3. Bake the cake
4. Decorate the cake
5. Eat the cake
Now, collect enough toys so that you have one toy per task (action figures and stuffed animals will probably work best for this). These will represent the modules of the program, each of which will perform a distinct task. Ask your children to think about which of their toys are best suited to each task.
Next, come up with a list of subtasks for each of the above larger tasks. Again, brainstorm with your kids to get them really thinking through the problem.
Let’s look at how the second task, “Measure and prepare the ingredients,” might break down:
- Measure each ingredient according to the recipe
- Store each ingredient in a small container so it’s readily accessible
- Mix the ingredients together according to the recipe
- Pour the batter into the cake mold
Do this for each task.
Each of those subtasks represents how you might use methods in a program. Each one plays a distinct role in the overall solution that can be performed without concern for the other processes that are going on in your program (which is to say, whoever is responsible for measuring ingredients, doesn’t need to know anything about oven temperatures, or any other part of the problem). Keep a list of these methods, noting which toy is responsible for each.
Finally, for each “method,” come up with a more detailed list of instructions.
Let’s look at “Measure each ingredient according to the recipe.” What are the specific instructions you’ll need to give your toy to make sure it knows what to do? Well, it’ll need to know a few things for each measurement, such as what its measuring and how much it should measure. Think of these bits of information as the parameters for the method. Brainstorm with your children, and maybe you’ll end up with something like this:
If the ingredient is a liquid, pour it into a measuring cup until you have the right amount.
If the ingredient is a powder, use measuring spoons to count out the appropriate measurement.
If the ingredient is a solid, use a knife to cut it to the right size.
These steps are the expressions and instructions your toys will need in this little game to perform the tasks necessary to achieve the overall goal.
Now that you have done all of that, quiz your kids to make sure they understand this hierarchy. Ask things like, “Which toy’s job would it be to measure one half cup of milk? What method would it use?” or “Which toy does this tool belong to?” (hint: each tool is only useable by the toy we assigned it to earlier. This touches on the concept of data scope, which will be covered later).
Once your kids have a good grasp on the general structure you’ve created, try more complicated problems, like, “If Mr. Wubbles (the toy tasked to gather the ingredients) needs to measure an ingredient, how would he do that?” (The correct answer is that Mr. Wubbles would ask Charlie the Sock Monkey, who is in charge of measuring ingredients, to come along and help him out.)
It may take a few tries to get your children to really understand what is going on here, so try it with a variety of projects of varying complexity. Keep doing this often enough, and you’ll have them thinking like a programmer in no time!