I'm having a bit of trouble conceptualizing the whole thing, however. How would a class like this begin? What is a first activity that the students can actually do in an objects paradigm?
I'll try not to write a book as an answer here, but my experience with this is long and deep.
The first thing you need to know is that you don't start with just the programming language itself. If you try to teach integer variables and 'if' and 'while' statements before you get to objects you may fail. I'm going to assume that your intention is to teach a first course that is also objects first. The students in a course like that might have no prior computing experience, though some will have.
The key to a successful course is to teach object-oriented problem solving, and not an object oriented language. In fact teaching problem solving via programming should be the objective of any first course no matter the paradigm. You want the students to learn to use objects and you want them to learn to create objects and you want them to be able to define new kinds of objects. But you don't need to do those all at once. You can spread it out over a short period of time - days, not weeks.
The key is proper scaffolding, written (or found) by you. The students work within a defined framework that can be quite complete (even Turing Complete). Another big idea that you want to believe yourself and teach your students is that an object is a "bundle of behavior." Never mind instance variables (fields) at the beginning and never mind getters and setters. Define for the students one or more kinds of objects and their behaviors. I've done this with most OO languages and all of them can be introduced the same way. I'll focus on Java for the rest of this, as it is the language of APCSA. It is also a good, though not perfect, OO language widely used in industry.
I have a lot of experience with Karel J Robot (KJR) so let me describe how it can be used as an introduction, that might take half of the first course in computing and teach students how to program. It is not, however, specifically tied to APCSA, nor does it cover every topic needed by your students. But in about half the first course, students will be able to write serious programs that require deep thought. At the end, I'll try to list many of the things not covered.
The KJR world is a simulation in which one or more robots can be created and which have a few behaviors. The "world" of the robots is a rectangular grid and one or more robots can occupy an intersection. An intersection can also contain one or more movable "beepers" that robots might pick up or put down. Infinitely many beepers (effectively a beeper making machine) is also possible at an intersection. A robot always faces in one of the cardinal directions North, South, East, or West. A robot can perform one of five primitive actions: move, turnLeft, pickBeeper, putBeeper, and turnOff. Those are your primitive behaviors and when the student begins programming, nothing else is known, though some additional things are revealed later in the course. In particular, a robot doesn't "know" where it is in the world. The world can also contain walls between intersections that will block forward movement and cause an error if a robot attempts to move through them.
So, what kinds of programs can you write (using only
main and the primitives? Well, to a programmer they are pretty boring: Move forward three blocks, pick up the beeper that is there and return to the initial position and direction. The solution is just a sequence of primitive actions, of course: move(); move();...
Students see a bit of syntax in the language and think in terms of the behaviors and nothing else. The learn about statement sequences, the most primitive control structure of programming (arguable, I guess).
Next they get a much more complex problem (first day's homework), which if solved with only sequences of primitives is unwieldy. It is obvious that something better must exist. But if you choose that program correctly you can notice that there are patterns in the solution. Even in the first assignment the robot had to turn around twice and had to move three blocks twice.
On the second day you discuss the homework and find the repeated sequences of instructions. Now you introduce a new class (their first view of a class) in which you get newly defined behaviors. This class is a subclass of the most primitive class. You are introducing inheritance (too early perhaps, but essential in KJR). The new class has a few additional methods: turnAround(), moveMile()... Note that it is too early to introduce parameters. All of the methods so far, and for a long way in KJR, are mutators, the state of the robot is changed in some way. But the notion of a mutator is in no way linked to any idea of a "setter."
Now you have the basic framework of problem solving. Define a new class. Within it define new behaviors. Create robots with new... and exercise the new behaviors to satisfy some programming task.
Note what is NOT done. There is never any speculative class writing. All classes are purpose built to solve some small part of a larger problem. The book talks about the decomposition process in detail.
You are now in the third day of class and have covered three chapters of the book. The fourth chapter is much deeper and discusses polymorphism, largely by showing how the Strategy design pattern can be used to modify the behavior of a given robot without writing a new robot class. Instead Strategy classes (and Decorators) are used to build a much more sophisticated model of computing. This chapter requires several days. It introduces object-valued variables which up to now have only referred to robots.
The fifth chapter introduces selection and there the student learns about booleans as well as the fact that robots also have some self knowledge. However, there are no methods returning information about the current location or explicit direction. A robot can respond true or false whether its front is clear (no wall) or if it is facing North, or if there is a beeper on the current intersection, etc. All of these accessor methods return booleans, so the student can now write conditional statements, which opens the door to more sophisticated exercises. These accessors are not "getters" either in concept or in fact.
The sixth chapter is repetition, but note that the student already has a good knowledge of the nature of computer programming and they haven't seen any of the primitive data of Java other than boolean.
For loops are introduced here, so integers are used, but only in simple ways - step counting, for example.
Later chapters (they are all pretty short) cover recursion and even concurrency.
The key to all of this, however, was a well thought out scaffolding structure in which the students can learn deep lessons in a way that you can control and in which it is harder to go astray in the minute details that you find with integer operators, float/double, ... The point isn't to teach Java as a language, but how to think like a programmer - specifically as an OO programmer.
The BIG idea
Java defines a logically consistent virtual world in which students can program without reference to lower level (machine level constructs) and can create consistent mental models without having to mentally compile their code to bits. A well designed simulation defines a yet higher level virtual world that if (Turing) complete can be used without reference to lower level constructs to solve any problem. That is very powerful. Robots can sort (piles of beepers) for example.
A slightly smaller idea is that you, the instructor, should think about what not to teach, especially at the beginning, as you do about what to teach. Teaching a complete subset intensely can be more powerful than teaching "the whole enchilada" at a shallower level.
If the instructor skips the polymorphism chapter, students will come away with the unfortunate view that OO programming is all about inheritance as all of the robot classes must derive from a simpler such class. In fact, OO is really all about building "bespoke" or "tailor made" objects out of parts that are also objects. Skipping polymorphism also gives the impression that selection and repetition are all you need in order to know "how to program", that they are the real thing, an impoverished view IMO.
KRJ is not the only way that you can implement this general course framework. The Greenfoot system is a simulation rich world in which you can build similar (or not so similar) things and use the same general plan. There is an associated instructor site, the Greenroom, to which teachers have contributed many simulations. The general idea there is a World in which Actors can move, turn, interact, etc.
What is missing
The big one is counting with integer variables (other than simple
for loops). One issue with teaching int and counting early is that from then on every problem becomes a counting problem, so students wind up with a poor mental tool kit. If you teach counting later, rather than earlier, students need to think harder about problems. You can "count" with decorators and encapsulate the actions themselves, rather than just the count in a (strategy) variable. You also can teach recursion without having to justify it as an alternative to counting.
There is no discussion in KJR of many of the things we love, arrays, for example, collections, iterators, and such. There is a companion book that covers most of what would normally appear in a first course but it assumes the students can already write sophisticated programs.
In the past Karel was used a lot by AP teachers, but the course has changed as has the exam. I've never tried to use it to teach APCSA. I'm sure there are many things missing that the instructor would need to add to a complete course.
The book “a touch of class” — bertrand meyer. Teaches Object orientation in a first year undergraduate cause. He claims that in his course he teaches Eiffel, then a bunch of other OO languages at the end (C#, Java, …) quicker than any of the others can be taught alone.
This seems reasonable, as Eiffel is very well mapped to OO. There is on the most part a one to one mapping between Eiffel and OO. This makes it much easier to learn. There are few gotchas (there is one), few work arounds.
What is more all the nice new stuff from C# (possibly also Java), came from Lisp or Eiffel (generics, contracts, get/set properties).
class HELLO_WORLD create make feature make do print ("Hello, world!%N") end end
Every keyword word can be explained in lesson 1
classsays we are declaring a class, maybe the hardest to explain in lesson1. A class is a mini-program / sub-program.
createsays here comes a list of creation methods, that is methods used to create the object (constructors for those used to other OO languages).
featuresays here is a list of features (methods).
dotells us that the make feature is a method (not a variable).
endends a feature or a class.
In Java we also have
) all of which you have to persuade your pupils to ignore, because it is not time to explain them today.
My advice is about removing unnecessary complexity. I believe that much of the complexity of OO is unnecessary.
I have used the following approach successfully. Know the outcomes you are teaching to, and use your materials and tools to achieve them. My goal is to develop strong computational problem-solving skills and methodologies.
This is the foundation I use to leverage an early objects approach with no prior experience:
- Introduce the idea of objects and interact with them by sending messages to them to get them to "do work".
- Use a visual representation of this.
- Create examples where the students are required to solve simple problems - and teach them a repeatable process for solving problems.
- Introduce the idea of an algorithm and the fundamental operations any/all algorithms use: sequential; conditional; and iterative.
- Provide demonstrations of each of those operations in exercises.
- Transition to a scripting language or block structured programming that supports those operations.
- Shift into an actual programming language and development environment.
- Add new OO ideas and language mechanics within this framework, by making changes to the classes, or adding interactions between objects. I have found it highly effective to re-use many of the samples by adding on features or enhancements to the functionality or interactions. Like a spiral approach to teaching, adding additional depth or details in subsequent iterations.
I would take 6-8 weeks at the start of any intro class to establish this foundation and way of thinking.
I make use of a custom version of the Greenfoot Karel J Robot simulator, but any similar environment will do (see references below).
As project work I encourage my AP students to design and create their own working versions of these Robot Simulations from scratch.
"Ontogeny recapitulates Phylogeny" and so teaching should follow the path that technology developed. It only takes nine months for a fetus to 'recapitulate' millions of years of evolution, so it should only take a few months for students to learn how computer technology developed over a few decades, and then really understand it, instead of "standing on the shoulders of giants" with no comprehension of how they wound up there.
So, if you have been questioning how to do an objects-first curriculum, perhaps there is good reason that you have not done it already: it would be difficult for the students to leap to abstractions if they have no idea what is going on underneath. The textbook I use introduces Object Oriented programming ideas (classes) in Chapter 4, before If and Loops. What can be done at that point? Perhaps some of what you want to achieve: show that a sequence of steps can be made in to a Method that can be invoked by other code. Show that Instances with their own data can be managed -- two Employee objects for example. Show references to said objects.
But students have to start with the basics: a computer is a simple electrical machine that functions deterministically (as Ada Lovelace said) and cannot do other than what it is told. Further, all of the activity essentially involves comparing numbers and than branching. Nothing more. The very first thing that students should realize is that all of this technology is something that they could understand, that sensible people developed it in tiny steps over time, no super-geniuses were involved -- as Dijkstra would tell you -- and the students themselves could in fact arrive at most of the development themselves given time. And it did take a lot of time: the Normal Forms took a decade to be developed.
Students need to be able to own the whole thing, down to the register level, or they will not really comprehend what they are doing. Otherwise, there will be a "Let them eat cake" attitude because, like Marie Antoinette, they will be ignorant, and shielded from the truth, by those who should be instructing them.