Computers are dumb! It is just that simple. Over the years that computers have been around, we have tried a bunch of different ways to express our desires to these dumb computers. Some of the ways we have tried made things easy for the people involved, some made things harder. Let’s skip to the easy way.
First of all, what is a program, anyway? The simplest definition is just a detailed list of specific instructions that a particular computer can follow to perform some task. Phew! That definition raises a number of questions right away! Like:
And the biggest one of all:
We will address all of this as we proceed. For now, rather than get too deep into computer programming right away, let’s focus on the problem solving part first.
How do we create a program - or even a simple list of instructions some computer could understand?
We should have a clear definition of just what our program is to do. We also need to know what resources we will needed to solve the problem, and what results we expect to obtain.
Hmmm, let me think about that for a moment! If I figure out what resources I need to provide to my computer, then figure out what to do to those resources to solve my problem, then figure out how to get my results out, I am done! Cool!
Three simple steps to success! What could be easier?
In the old days of computer programming, any problem was broken down very quickly into these three major blocks:
Today, exactly how to do the initial breakdown of functions is more difficult. Especially when the program will include extensive interaction with a human operator and the outputs are more complex that simple printed reports.
The most important skill needed in the early part of problem solving is an ability to see the problem clearly enough to identify places where the big problem can be broken up into smaller pieces. This process, known as decomposition, is one of the ways humans have learned to deal with complexity. The whole is just too complex, so break it down into a series of smaller, less complex, parts and glue those parts together. If the first decomposition still leaves us with parts that are too complex, break them down as well. Continue until each part can be clearly constructed.
A key characteristic of a good problem solution is a clear identification of exactly what input data is needed for each piece, and what output is to be produced. The design should identify the processing that is to be performed, but that processing is often not completely understood until after you have worked on the problem for a while.
You should have noticed something important here. At the top of this entire problem solving process, we tried to identify all the information we need to have available to solve our problem, then identify what is to happen in a process, then identify the results we want to get out. While we design a solution, we can focus on the transformation of data from input stuff to output stuff and not worry about exactly how that transformation takes place. We can think of this transformation process as a kind of black box that does magic.
In the decomposition process, we break up a big magic box into a series of smaller magic boxes, and what comes out of one box flows into another box later. Seen this way, it seem like all we need to do is to work out how data flows through the entire system undergoing small transformations along the way, until we get the final output we want.
The problem is that there are a gazillion different ways to build any solution; some work well, and some do not. Your job is to first find at least one way that works, then see if you can make it better.
So, how do we decompose a problem?
When computer programming first took off as a professional activity, there was little guidance in how to perform decomposition. So, programmers just started with the first step they could think of. They usually followed their data as it moved through a series of processing stages until it was ready for output. Along the way, as they thought up something that needed attention, they would hook additional process boxes into the system in ways that were not well thought out at all!
The problem with this approach was they often still forgot fundamental things that needed to be included. So, they would go back into their scheme and patch in new blocks of code to take care of the missing elements. As they patched in new process steps, they would need to perform tests to see if this new process was to be performed, or skipped. Where the program code was to be picked up after a test depended on the result of that test. What came out of all this patching was a solution process that was jumping all over the place , from point to point - not a nice linear sequence of steps at all! Over time, the flow of the program became very confused - and the term Spaghetti Code became a popular way to describe these solutions schemes.
Many people studied this strange situation, and one famous computer scientist, Edsger W. Dijkstra, published a paper titled Go To Statement Considered Harmful (Communications of the ACM, Vol. 11, No. 3, March 1968, pp. 147-148). Dijkstra’s analysis determined that the programming languages of the day gave too much power to the programmer to do whatever they wanted, whenever they wanted. Specifically, he pointed to the uncontrolled use of a jumping statement in most languages that let a programmer jump from one spot in the code to another with few constraints. The result was clearly a mess.
Surprisingly, many programmers took notice of this paper, and programming languages went through a re-engineering period that lead to a revolution in programming and design - structured programming.
As simple as it seems, a structure is just a block of processing that has a single point where you enter it, with a clearly defined set of data items in hand, and a single point where you leave it, with a different clearly defined set of data items in hand. We usually draw a structure as a simple box with a line going in the top and a line exiting the bottom:

We sometimes call this box a process box.
By itself, this is not very useful. The power of structured programming comes from the use of three very simple variations to this simple box.
If we glue several of these simple process boxes together in order, we have a Sequence of actions. Viewed as a whole, there is still a single point of entry and a single point of exit - even for the entire group of boxes. So, we could draw a single box around all the smaller boxes.

Bingo - I see a decomposition here!
The single big box is our original problem, and the sequence of steps is a decomposition of that problem into smaller, hopefully easier to understand, sub-problems.
Not very many problems can be solved with just a simple sequence of steps. Most will involve making a decision at various points in the flow of processing. Based on the results of each decision, we will perform different kinds of processing. It was probably this single activity that was most abused in unstructured programming.
Today, we only allow decisions to be made in the following structured way:

The diamond represents a question of some sort - one that has only a true or false answer. We allow the flow of the program to branch out of the diamond two ways - one way if the answer is true and the other if it is false. Each path goes to a single process box where the processing for that answer will be performed. We require that the flow rejoin after each of these possible processes so we still have a single point of exit for the structure. (We may allow the process box for the false answer to be missing - in which case we simply pass through the box with no magic happening, but we never allow the process box for the true answer to be missing.)
Constraining the program flow this way seems like it might cause problems, but it turns out not to be in real life - we just have to think a bit harder.
Finally, there is often a need to perform one action a number of times in a program. For instance, you need to process all the time cards for all employees in your company to figure out the monthly payroll. Loops are easy to set up in a computer, we just jump back to a previous point in the program and do it all over. We really need a way to stop this process or we get stuck in what programmers call an infinite loop - one that never stops. (Some programs need such a loop, most do not!)
Here is one variation of a loop. Can you think up another?

In the case of the loop, the question we place in the diamond is not really a question. It is an expression we can evaluate to see if it is true or false. Something like this:
This statement is clearly true or false whenever we check it. That leads to a true or false condition that controls which way we branch out of the diamond.
Now for the real trick in structured programming. We are seeking to decompose big problems into easier to work sub-problems. We can take any of these three fundamental structured forms and place it inside any process box you find in your diagram. Since each structured form has more boxes inside it, you can continue installing other structured forms as needed to clearly define how your processing should proceed.
Cool!
Note
If you think about what we have just said, you will see that programming is actually very simple. The trick is to train your brain to only use these structures and make sure you do not generate any of that nasty spaghetti code. Seriously, if you find yourself having problems getting your programs to work - make sure you are using the structures as we have explained here. If not, do not be afraid to junk what you have and rethink the problem and how you have designed the code. There is a lot of proof out there that says 80 percent of your time should be spent thinking and ony 20 percent coding!
It helps to have a tool of some kind to use these diagrams in this way, but many programmers use just pencil and paper - lots of paper - to do the job. When you decompose a process box, put a number in it - go to another piece of paper, put that number on it and show what goes inside. You end up with a lot of paper, but by taping it to the wall, you can see how it all fits together. (I have seem teams fill up all the walls in a room this way!) Today, there are powerful programs like Microsoft Visio that can be used to build diagrams using these structures. Oddly enough such a diagram is called a Flow Chart.
After a lot of study, scientists have proved that anything that can be done on a computer can be done using just these three basic structured forms. So the answer is clearly NO - it is not too confining. Most modern programming languages have constructs that map cleanly to each of these fundamental forms. Most languages add to this simple set to make programming a bit easier, but each addition still conforms to the single entry - single exit principle.
For a long time, building flow charts was a big part of thinking through problems - not just computer problems. Paper and pencil worked well then, and it works well today - if you have no other way. However, many people are not that good at drawing pictures, and anyway, as you decompose one block into others, you end up redrawing the darned things over and over. So, can we come up with another way to do decomposition using tools we already have, and that do not require graphical skills?
Suppose we invent a simple, English-like shorthand notation that can be used to do the same job that drawing diagrams does. Wouldn’t that be just as good?
Since we do not need to worry about asking a computer to read our notation, we can be very informal in what we invent. Here is a simple scheme:
Use simple, numbered, English sentences to describe a process
A sequence is just a series of sentences to be followed in order
What goes inside this is just English - short and clear. This is called Pseudo Code because it is almost code, but not quite.
Here is a simple example - a pseudo code description for driving up Congress Ave.
1. Start the car and start driving
2. WHILE (I have not run into the Capitol)
2.1 Drive to next intersection
2.2 IF (the traffic light is green)
2.2.T THEN Continue driving
2.2.F ELSE Stop at the intersection until it is green
ENDIF
ENDWHILE
3. Stop before the guards yell at you!
Study this a while and make sure you see how it works. You are free to use any description of what you want to happen you like. The only requirement is that you use indentation to show where actions are part of a structure. Notice that I used outline-style numbering to number the sentences inside the structures, and even invented my own numbering scheme for the decision structure.
Note
See anything wrong with the pseudo-code above. Is every line a simple application of one of the structures? How about 2.2.F? What kind of structure is that? Well, for now, this will do. However, we will need to get a bit more clear about what we want to happen here before this is a good description of the steps we want to follow!
You might notice, also, that if we are neat in writing our sentences, we do not even need to number the lines. We can see where each structure is by studying the indent level of the sentences. However, if your sentences get long, it is helpful to use the numbers to clearly define where each sentence begins.
When you practice writing pseudo code, use any text editor and be neat! Your skills as a programmer will be judged (not just inside this class) by other programmer on how easy it is to read your work. Someone will have to fix any problems in your work, or may just want to study how you did something - and they expect to be able to see what is going on easily!
We will use pseudo code a lot as we learn how to build our solutions.
Are you hungry for more?
What’s that you say, this is a programming course? Well sure it is. But we need to begin at the beginning – with a problem or task to work on.
We also need be able to analyze that problem or task in enough detail to be able to tell the computer exactly what we want it to do for us. So, let’s consider a simple problem - baking a cake, actually, let’s bake two cakes!
Is this silly? Maybe so - but maybe not!
We are going to start detailing the process of baking two cakes. To make things a bit more interesting, assume that you are going to write up the instructions and hand them to someone who has no idea how to bake a cake! (Do such people exist? Who knows?)
Since we are all experts in the kitchen, we could just start writing down what we need to do, right? I do not know about you, but if I tried that I might get a cake, but it might be a brick instead. We could Google and find out what to do, but I chose to go to a real authority on the process. I scanned the back of a cake mix box in my pantry! With due credit to Duncan Hines, here is an image of the back of my cake box:

As you look over this image, you should start to see several key things. First, we have to collect a bunch of stuff (tools, ingredients, etc.) to do the job. Next we have to manipulate those tools and ingredients in just the right way to get a cake.
But wait, then we have to do the whole thing over again to get two cakes! Yikes!
At the top of the image we see that we are to collect the following ingredients:
Oh yeah - I almost forgot!
What else do we need to do the job?
Study the entire image and see what you can come up with. Here is my list.
That is a lot of stuff!
Is this list complete? Are there any problems with what we have written down yet?
Well, I did not remember that I have two cakes to bake, so I may need to modify this list a bit. What else needs to be modified?
The reason I am distinguishing between ingredients and tools is that I do not need two sets of tools, but I do need two sets of ingredients!
The image on the box has three steps. But we would see a few more if we look closely. Here is the sequence of actions we need to take to get the cake built!
Oh phooey -
Do everything again (do we need to clean up first?)
Wow! Three simple steps on the cake mix box turned into 31 steps when we wrote down what we think is a complete list of things to do. A professional cook would blast through all of this without batting an eye.
Once we think we know what we want to do, we need to step back and look things over. Maybe we can do a better job. Maybe we missed something. We need to make sure we are confident that our steps will really do the job!
Do you have any problems with what we have written down? I surely do!
What would you do to all of this if you had a helper who could do part of the work for you? Can you see any part of the sequence above that you could carve off and hand over to to your new helper?
Here is a mantra I have heard some programmers mutter:
I am lazy! I do not want to do the same job twice! I will build a simple tool that someone else can use to do that job over and over! I will teach the computer to do that job, then I will relax!
We obviously have a way to go to finish this off. But this should get you thinking about how to approach a problem for now.