In a previous post, I presented algorithms and functional decomposition. Here, we explore how to write an algorithm and then create working Java code from that algorithm. This post’s purpose is not to present a realistic computer program. Moreover, this post omits many fundamental programming topics. But these omissions are by design. Instead suspend disbelief and focus on the simple process of turning a task into a computer program’s skeletal structure. Here, we are using functional decomposition to go from a general real world task to the beginnings of a computer program.*see below
Sketti – Redneck Bolgnese
A recipe I remember from my childhood, sketti, went viral when Mama June made sketti on The Learning Channel’s show, Here Comes Honey Boo Boo. The recipe is simple: spaghetti noodles, hamburger, ketchup, and butter. But let Mama June demonstrate.
Mama June makes sketti by frying hamburger, boiling spaghetti noodles, microwaving a mixture of ketchup and margarine in a bowl, and then combining the ingredients in the pot used to boil the noodles (after draining the water first).
Observation to Algorithm
When you have a process you wish to turn into a computer program, do not begin by writing code. You should first formalize the tasks involved. Start by writing the steps involved in making sketti. Focus on the broad steps, not the details.
- Gather ingredients
- Boil noodles
- Fry hamburger
- Mix ingredients
- Microwave sauce mixture
- Combine ingredients
- Serve and enjoy
These are the seven steps I get from observing Mama June make sketti. But, these steps are much too broad. And so, let’s decompose these steps into more detailed sub-steps. As I’m a redneck, I wanna keep it realistic – so let's get the dishes from a dish-drainer rack rather than the cupboard. Oh, it’s also a fridge not a refrigerator – details are important.
- Gather ingredients
- Get hamburger from fridge
- Get noodles from cabinet
- Get pot from rack
- Get pan from rack
- Get microwavable bowl from rack
- Get ketchup from fridge
- Get butter from fridge
- Boil noodles
- Put water in pot
- Bring water to a boil
- Add noodles
- Cook noodles
- Throw noodles, three, against cabinet
- Drain noodles
- Fry hamburger
- Put meat in pan
- Fry meat
- Drain fat (optional)
- Make sauce
- Put margarine in bowl
- Put ketchup in bowl
- Mix
- Microwave sauce
- Combine ingredients
- Add meat to noodles
- Add sauce to noodles
- Stir
And there, you have a top-level outline detailing making sketti. We can now use this outline to create the beginnings of a working Java program.
Algorithm to Java Code
Now let’s use the outline above to write the skeleton of a simple Java program that uses simple methods that do not return values. Again, suspend disbelieve, the purpose here is to demonstrate translating an outline to a simple program.
First, I create a simple class named Sketti
with a main method.
public class Sketti {
public static void main(String[] args) {
}
}
I then create methods from the top level outline methods. Note I am adding no logic to perform these tasks.
public class Sketti {
public static void main(String[] args) {
}
public static void gatherIngredients(){
}
public static void boilNoodles(){
}
public static void fryHamburger(){
}
public static void makeSauce(){
}
public static void combineIngredients(){
}
}
Now, one of my pet-peeves is placing any logic in the main
method. The main
method is the program’s entry point, it should not be used for any logic. Therefore, I add a top-level method named makeSketti
. This method will orchestrate the sketti making tasks.
public class Sketti {
public static void main(String[] args) {
}
public static void gatherIngredients(){
}
public static void boilNoodles(){
}
public static void fryHamburger(){
}
public static void makeSauce(){
}
public static void combineIngredients(){
}
public static void makeSketti(){
}
}
Now that I have the primary tasks, I can orchestrate these tasks into making sketti
.
public class Sketti {
public static void main(String[] args) {
makeSketti();
}
public static void gatherIngredients(){
}
public static void boilNoodles(){
}
public static void fryHamburger(){
}
public static void makeSauce(){
}
public static void combineIngredients(){
}
public static void makeSketti(){
gatherIngredients();
boilNoodles();
fryHamburger();
makeSauce();
combineIngredients();
}
}
I like to start with a running program, no matter how simplistic, therefore let’s add println
statements to each function.
public class Sketti {
public static void main(String[] args) {
makeSketti();
}
public static void gatherIngredients(){
System.out.println("gatherIngredients");
}
public static void boilNoodles(){
System.out.println("boilNoodles");
}
public static void fryHamburger(){
System.out.println("fryHamburger");
}
public static void makeSauce(){
System.out.println("makeSauce");
}
public static void combineIngredients(){
System.out.println("combineIngredients");
}
public static void makeSketti(){
System.out.println("making sketti");
gatherIngredients();
boilNoodles();
fryHamburger();
makeSauce();
combineIngredients();
System.out.println("done making sketti");
}
}
When run, the program writes the following output:
making sketti
gatherIngredients
boilNoodles
fryHamburger
makeSauce
combineIngredients
done making sketti
Now create methods for each sub-step involved in gathering ingredients. Then have the gatheringIngredients
method orchestrate its sub-steps. The following code illustrates:
public static void gatherIngredients(){
System.out.println("gatherIngredients");
getBurger();
getNoodles();
getPot();
getPan();
getKetchup();
getButter();
}
public static void getBurger(){
System.out.println("\tgetBurger");
}
public static void getNoodles(){
System.out.println("\tgetNoodles");
}
public static void getPot(){
System.out.println("\tgetPot");
}
public static void getPan(){
System.out.println("\tgetPan");
}
public static void getKetchup(){
System.out.println("\tgetKetchup");
}
public static void getButter(){
System.out.println("\tgetButter");
}
Repeat creating sub-steps and orchestration for each major step.
public class Sketti {
public static void main(String[] args) {
makeSketti();
}
public static void gatherIngredients(){
System.out.println("gatherIngredients");
getBurger();
getNoodles();
getPot();
getPan();
getKetchup();
getButter();
}
public static void getBurger(){
System.out.println("\tgetBurger");
}
public static void getNoodles(){
System.out.println("\tgetNoodles");
}
public static void getPot(){
System.out.println("\tgetPot");
}
public static void getPan(){
System.out.println("\tgetPan");
}
public static void getKetchup(){
System.out.println("\tgetKetchup");
}
public static void getButter(){
System.out.println("\tgetButter");
}
public static void boilNoodles(){
System.out.println("boilNoodles");
pourWater();
boilWater();
addNoodles();
cookNoodles();
throwNoodles();
drainNoodles();
}
public static void pourWater(){
System.out.println("\tpourWater");
}
public static void boilWater(){
System.out.println("\tgetButter");
}
public static void addNoodles(){
System.out.println("\taddNoodles");
}
public static void cookNoodles(){
System.out.println("\tcookNoodles");
}
public static void throwNoodles(){
System.out.println("\tthrowNoodles");
}
public static void drainNoodles(){
System.out.println("\tdrainNoodles");
}
public static void fryHamburger(){
System.out.println("fryHamburger");
placeMeat();
fryMeat();
drainFat();
}
public static void placeMeat(){
System.out.println("\tplaceMeats");
}
public static void fryMeat(){
System.out.println("\tfryMeat");
}
public static void drainFat(){
System.out.println("\tdrainFat");
}
public static void makeSauce(){
System.out.println("makeSauce");
addMargarine();
addKetchup();
mix();
microwaveSauce();
}
public static void addMargarine(){
System.out.println("\taddMargarine");
}
public static void addKetchup(){
System.out.println("\taddKetchup");
}
public static void mix(){
System.out.println("\tmix");
}
public static void microwaveSauce(){
System.out.println("\tmicrowave");
}
public static void combineIngredients(){
System.out.println("combineIngredients");
addMeat();
addSauce();
stir();
}
public static void addMeat(){
System.out.println("\taddMeat");
}
public static void addSauce(){
System.out.println("\taddSauce");
}
public static void stir(){
System.out.println("\tstir");
}
public static void makeSketti(){
System.out.println("Mama June's making sketti");
System.out.println("=========================");
gatherIngredients();
boilNoodles();
fryHamburger();
makeSauce();
combineIngredients();
System.out.println("done making sketti");
}
}
When you run the program, you obtain the following output:
Mama June's making sketti
=========================
gatherIngredients
getBurger
getNoodles
getPot
getPan
getKetchup
getButter
boilNoodles
pourWater
getButter
addNoodles
cookNoodles
throwNoodles
drainNoodles
fryHamburger
placeMeats
fryMeat
drainFat
makeSauce
addMargarine
addKetchup
mix
microwave
combineIngredients
addMeat
addSauce
stir
done making sketti
And there you have it, you have used functional decomposition to write a simple program that makes sketti. Admittedly, this is not a realistic program. But it illustrates functional decomposition.
Conclusion
Computer programming is problem solving. Computers require instructions to do anything interesting. Those instructions must be detailed. Think of writing a computer program to perform some task as similar to writing a term paper. Before writing, you decompose your paper’s topics into an outline. That outline becomes your term paper’s structure. The same is true for programming. When programming, your outline becomes your program’s skeleton. If you strip functional decomposition from all other tasks involved in writing a computer program, suddenly writing a reasonably detailed algorithm becomes remarkably simple. It used to be common knowledge that writing algorithms was considered a fundamental programming skill. Somehow, this skill has gotten lost in the newer generation of programmers and the plethora of coding boot-camps that teach syntax but not programming. But if you learn this one simple skill, it will place you in the top-tier of computer programmers. Your problem solving ability and systematic thinking in other endeavors will also improve. You just might start applying algorithmic thinking to your everyday life.
- This post is geared towards students reading the book Think Java through chapter four. It purposely avoids Object-Oriented design, variable passing, and other topics so as to focus solely on functional decomposition.