1. 0001 - Computers and Coding

Help Make These Materials Better!

I am actively working to complete and revise this eBook and the accompanying videos. Please consider using the following link to provide feedback and notify me of typos, mistakes, and suggestions for either the eBook or videos:

What’s the Point?

  • Understand the role of programming languages

  • Get to know a little about Object-Oriented Programming (OOP)

  • Use print() and println() to produce text output

Source code examples from this chapter and associated videos are available on GitHub.


A computer is basically a device that executes a set of commands—​and does so very quickly. Because the guts of a computer (a CPU) are kinda like a bunch of light switches—​and I mean a BUNCH of light switches—​it can only deal with zeros and ones: a switch that is off is "zero," and a switch that’s on is "one."

Never before has the concept of a modern computer been so recklessly simplified. I feel shame.

All of the information a computer handles ultimately has to be represented by some combination of 1s and 0s, which we call a binary (or "base-two") number system. The chapters of this eBook are numbered using binary to show basic examples of the numbering system: 0001 is, well, 1 in decimal. And 0100 is 4 in decimal. We won’t get into binary numbers, but it’s not very complicated and is kind of interesting if you’re a nerd.

Learn More

The amazing code.org project has a playlist of great, short videos on how computers work—​including binary numbers—​if you want to know a little more without going too crazy:

Imagine that your BFF is in your object-oriented programming class, but that cruel professor won’t let you sit together. When the professor turns his back, you can use your fingers to send a quick message to your BFF. Holding up your index finger might mean, "meet me in the library after class;" two fingers could mean, "send me a copy of your homework." As long as you agree on what each number means, you could pass along commands or information—​it would be like your own little language.

If you’re a sports fan, I have a better analogy. A quarterback and a coach could have a language based completely on numbers. The coach tells the QB "22" and the QB knows which play to run, because they’ve agreed on what instruction (play) the number 22 means—​and there are football teams that do exactly this.

Sending that number to the quarterback as a binary number would be a lot less efficient because the coach would have to say "10110" (which is the binary representation of twenty two) and the QB would have to know binary numbers,or have them written on his wrist-band thing as a cheatsheet.

Want to take the analogy one step further? A player standing on the sideline with their helmet on could represent a 1, and a player with their helmet off could represent a 0. Now the coach could just line up five players and tell the 2nd and 5th ones to take their helmets off. The QB could look over, see the pattern of helmets (10110) and run play 22.

Okay, that would be the nerdiest football team in history. And how is that relevant? Let’s see…​

Remember that a computer can execute commands super fast. Each command, or instruction (like a football play), is represented by a number—​a binary number, since that’s the number system the computer uses. The collection of instructions the computer understands is called machine language.

Interesting!

Just like people in different cultures use different languages, different CPU types use different languages. There are lots of different machine languages out there.

You could give the computer a set of instructions (aka, a program) if you just looked up the binary number for each instruction you wanted to use. Of course, even a simple program requires a lot of instructions, so you’re going to be looking up a lot of stuff.

Few people actually want to do that, so the rest of us use programming languages instead.

1.1. Programming Languages

A programming language is something that’s easier for humans to use than machine language, but is capable of being accurately translated to machine language.

There are many, many programming languages. Seriously, there are a lot.

The instructions you write using a programming language are called source code. Translating source code file to a machine language file that can be executed is called compiling, and is done by an application called a compiler. When the computer runs the program, it’s using the machine language translation created by the compiler. Clicking on the icon to open Microsoft Word runs a file that’s been compiled from source code.

Time To Watch!

Coding and Compiling

Some programming languages don’t get translated ahead of time—​they get translated "on the fly," as the program is running. That’s called interpreting instead of compiling, but it’s conceptually the same thing.

The C programming language is an example of a compiled language, and Python is an example of an interpreted language.

Java is an interesting case, because it’s both compiled and interpreted. The JDK compiles our source code into an intermediate language called bytecode. To execute the program, you use the Java Runtime Environment to interpret that bytecode file as it executes.

Bytecode is very close to machine language. In fact, it’s basically a "virtual machine language"--a machine language for a CPU that doesn’t actually exist. This approach allows Java to be cross-platform (runnable on many different machines). A compiled machine language file only works on a computer that "speaks" the same machine language, but if we compile our program to a bytecode file, it’ll run on any computer that has the Java Runtime Environment installed—​and that will interpret the bytecode as it executes. This "write once, run anywhere" ability contributes greatly to Java’s popularity.

1.2. Programming Paradigms

A paradigm is a model or example, or maybe better described as a way of seeing things—​which is helpful to think about, since we can all have different ways of seeing how a problem could be solved.

Imagine that your crazy uncle wants to pay you to go through the junk in his garage and organize his giant collection of vinyl records. Or imagine it’s a collection of books, if that’s what you prefer. How would you organize the collection? You could group them by artist and then arrange them alphabetically, from ABBA to Warren Zevon. Or you could group them by genres (keeping disco separate from rock \'n' roll), or just put them in the order they were released.

There are tons of different ways to do it. None of them are really right or wrong, it just depends on what you prefer—​or maybe on how you plan to find things later. Coding is similar, in that we all have different ways we imagine organizing a program or solving a problem. That’s kinda the idea of a programming paradigm: how do you think about the program you’re creating? How do you picture it being organized?

Just like programming languages, paradigms are numerous. In fact, some languages were created specifically to work well with a certain paradigm, and that’s one reason there are so many languages. But when someone is going to learn to code, there are often two paradigms we consider:

  • Procedural Programming

  • Object-Oriented Programming (OOP)

They have a lot in common, and in fact, OOP is actually a type of procedural programming. Programmers love to argue why one approach is better than the other, in the same way some of my friends might argue about Ford trucks vs. Chevy trucks. And just like Ford vs. Chevy, there’s nothing inherently better about one paradigm or the other—​sorry friends, but Ford and Chevy trucks are basically the same. Growing up, my own first coding experiences were exclusively with procedural programming, and I stayed in that world until I began teaching Java—​now I very much prefer OOP, both for my own programming and for teaching beginning coders. But that really is a personal preference, and I wouldn’t argue that OOP is better than procedural programming.

Well, I wouldn’t argue much.

1.2.1. Comparing Procedural Programming and OOP

In procedural programming, we break up a program into the tasks we need to complete. Each individual task is handled by a set of statements that we call a procedure. If we need to calculate a student’s overall course grade, for example, we write a procedure to do it.

The data for our program—​the stuff we’re keeping track of—​is stored somewhere else. If a procedure needs something to complete its task, that data is sent to the procedure, which then sends back a result. In short, information is kept separate from the code that uses it and is passed back and forth as necessary.

In Figure 1, the main procedure passes the values 5 and 4 to the adding procedure, which uses that information to calculate the sum 9 and return it to the main procedure. The subtracting procedure also requires two numbers. 10 and 3 are passed to that procedure, which returns 7 to the main procedure.

Diagram of data passing in procedural programming
Figure 1. Passing data in procedural programming

Many programming languages (including Python) refer to procedures as functions, and the term subroutines is also used in some cases; if you’ve done some programming in any language, you’ve almost certainly used procedures in some form.

In OOP, the focus shifts from procedures to objects, which are programming elements that bundle data with the procedures that use it, instead of keeping them separate. We’ll explore the nature of objects in great detail going forward, so we won’t worry about describing it too much for now.

I have my own biases about the topic. I tend to think OOP lends itself especially well to things like graphical user interfaces (GUIs) and games, as well as large projects developed by teams of programmers.

The bottom line is that, when faced with a programming task or project, my brain immediately starts thinking in terms of the objects the program will need. But that’s probably just a matter of habit; as I mentioned, I spent much of my life (including all of the time I spent as a professional programmer) seeing programs as a bunch of procedures.

It’s important that you’re aware of procedural programming, and the code we’ll write in the next couple of chapters is really written from a procedural perspective, but our overall focus in this book and course is really on OOP.

1.3. Software Development Process

Learning to write code means creating a lot of programs—​mostly small, straightforward programs at first. Remember those awful word problems where a train leaves Chicago traveling 40 mph, and another train leaves Denver at 35 mph? That kind of stuff; but in my course, we don’t get too caught up in the math part of it. But we care a lot about understanding the requirements of a program and implementing it successfully.

As our programs become bigger and more complex, we’ll need to work within a deliberate design and implementation process in order to keep ourselves organized and focused. Even the smaller programs we’ll develop while learning the basics will benefit from a thoughtful approach beyond just opening a new file and starting to type. It ensures that we use our time efficiently. And when we are faced with solving a programming problem that really intimidates us, the process will help make the task more approachable.

For big or small projects, a good general approach to software development is:

Analysis

Identify the goals and scope of the program. As a rule, keep it small and focused—​we can always add features later. Ask yourself, What does this program need to do?

Testing Plan

Determine how the final program will be tested. The testing plan will be useful, but most importantly, taking the time to establish a specific testing plan ensures that you thoroughly understand the program before you begin writing code. If you don’t know how the program will work, you’re not yet ready to begin coding. Ask yourself, How will I make sure the program works correctly?

Implementation

Write and test the code. We say that this is an iterative (or "repeating") process, meaning you’ll write and test one small piece, staying with it until you know it’s good. Then you’ll move on to the next piece and repeat. Ask yourself, What code do I need in order to get the next part of the program working?

Revise or maintain

If our needs or program requirements change, we’ll need to go back to the first step and begin planning the next version. If not, we’ll need to monitor that the program continues to perform as expected over time. Ask yourself, What’s next for this program?

We’ll flesh out this process as we go—​and as our programs become more advanced.

1.4. First Java Program

Enough of that, let’s write some code!

One of the (valid) criticisms of Java as a choice for beginners is that it’s a little complicated to create our first program. In Python, we just open a file and write our first command; in recent versions, C# has added that ability as well. But Java puts OOP front and center, and we can’t start writing statements until we first define a class.

Time To Watch!

Java File Structure and First Program

File from video:

Take a look at the code for a basic "Hello World" program; we’ll learn what all of these pieces are as we go, but we should at least identify them now.

HelloWorld.java - Hello World program in Java
1
2
3
4
5
6
7
8
9
public class HelloWorld { (1)

    public static void main(String[] args) { (2)

        System.out.println("Hello World!"); (3)

    } (4)

} (5)

Here are the parts of the program:

1 Class declaration and start of a code block. This is a publicly accessible class called HelloWorld.
2 main() method declaration and start of a code block. main() is where a Java program starts running.
3 println() statement to output the message.
4 End of the main() method code block, as indicated by the indenting and closing curly brace.
5 End of the class code block.

We’ll learn about all of these components as we go. But for now, we’re off and running!

1.5. Basic Output

The first programs we create in Java are console programs—​they are text-based programs that can’t really display any graphics. To start with, we’ll use two basic ways to output text to the console: System.out.print() and System.out.println() statements. print() outputs whatever text is in the parentheses, and we’ll need to put that text in quotation marks:

System.out.print("Mick Jagger");

This line of code outputs Mick Jagger to the console window. After print() outputs the text in parentheses, the cursor remains at the end of the output. This is just like if we type something in a word processor but don’t hit enter; the next time we start typing, the characters resume on the same line. In the same way, the next output statement will continue on the same line in the console.

A println() statement works exactly the same way, but it advances the cursor to the next line when it’s finished. Basically, it hits enter, and the next output statement will begin on a new line.

Interesting!

println() works by outputting the text inside the parentheses and then outputting a special character called a newline. The newline isn’t visible, but it moves the cursor to the next line.

To understand the difference between print() and println(), consider this program.

OutputExample.java - Simple console output in Java
1
2
3
4
5
6
7
8
9
public class OutputExample {

    public static void main(String[] args) {
        System.out.print("As the Rolling Stones might say,");
        System.out.println("you can't always");
        System.out.println("get what you want.");
    }

}

The program produces the following output:

As the Rolling Stones might say,you can't always
get what you want

After the print() statement executes, the cursor is still sitting right after the comma following say, so when the next line of code outputs you can’t always, that output just gets jammed onto the end. Notice that it doesn’t even add a space; if we want a space there, we have to include it within our quotation marks.

Because you can’t always is in a println() statement, the cursor advances and get what you want is on a new line.

We’ll use print() and println() in every Java program we write for quite a while, so it’s important to take time to experiment with them on our own to make sure we understand how they work.

1.6. Code Comments

The Java compiler goes through our source code file line by line, translating all of the code into something that we can execute (unless it finds something it doesn’t understand, which causes it to stop and output an error message). If there’s something in our source code we don’t want the compiler to process, we can identify it as a code comment and the compiler will ignore it. Code comments are generally used to provide information for any humans who might be looking at the code. And since it’s ignored by the compiler, it can be written however we want; so our code comments should be written in plain human language (English, if we’re submitting it to me). To indicate a comment, use two slashes:

// This is a comment!

Once the compiler sees two slashes, it just ignores the rest of the line. We can add a comment onto the end of a line of code:

Inline comment placed at the end of a line of code
1
System.out.println("Hello World"); // this outputs text to the console

The println() statement still gets processed and will execute when we run our program, but everything after the slashes gets ignored.

To make a comment that takes up multiple lines, start the comment block with /* (that’s a slash and an asterisk) and end it with */ (asterisk and a slash). When the compiler sees /* it will ignore everything until it finds */, and then it will resume processing as usual.

Multi-line comment block
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
/*
This program shows the difference between print() and println().
It is referring to an old Rolling Stones song.

Everything in this comment block will be ignored.
*/
public class OutputExample {

    public static void main(String[] args) {
        System.out.print("As the Rolling Stones might say,");
        System.out.println("you can't always");
        System.out.println("get what you want.");
    }

}

In general, code comments are used to explain or provide context for our code. Programming often involves going back to old code to make updates or corrections. Maybe it’s been a long time and we might not remember what the code is supposed to do, or maybe it’s someone different looking at the code and trying to figure it out. So code comments should be descriptive, especially when code might be confusing.

Code comments don’t cost anything, so use lots of them!

We often add a multiline comment block at the top of a file to provide information about the overall program or class.

1.6.1. "Commenting Out" Code

Coding is all about trial and error, and programmers spend a lot of time writing code in different ways until they get it working the way they want. In a process like that, it’s not unusual to delete something only to regret it and wish we could have that old code back.

Code commenting gives us a life hack to help prevent that regret. Instead of deleting code that’s not working the way we want, we can just mark it as a comment. As far as the compiler is concerned, we’ve deleted the code. But if we want to see or use the code again down the road, it’s still there.

Almost all IDEs have a keyboard shortcut for commenting out code—​and in most, it’s the same shortcut. Highlight a section of code and press Alt+/ on Windows or +/ on macOS, and many IDEs will add // at the start of each line. Highlighting a comment and pressing the shortcut again will usually "uncomment" it and remove the slashes. If that doesn’t work, check the IDE’s documentation to see if there’s a different shortcut.

Check Yourself Before You Wreck Yourself (on the assignments)

Can you answer these questions?

  1. What is the primary role of a programming language in the context of computer programming?

  2. Explain the difference between compiled and interpreted programming languages. Provide an example of each.

  3. Describe the basic structure of a simple Java program, such as the "Hello World" example provided in the chapter.

  4. What are the key steps in the software development process as outlined in the chapter? Why is it important to follow these steps?

Sample answers provided in Stuff That’s Tacked On The End.