8
$\begingroup$

I'm familiar with two schools of thinking for approaching an introductory level class in an object oriented language: objects-late, and objects-early. In objects-late, you teach various procedural aspects (variables, loops, boolean manipulations, etc) before you delve into objects at all, and then use objects as a way to organize larger chunks of code.

In objects-early, you begin with the object-oriented paradigm, and then delve into method construction, and finally into the procedural aspects of coding that way.

I truly don't understand this second approach or its merits. What are potential benefits of beginning with objects, and how can you structure the early parts of a course in order to even permit this?

Important note

I know that Buffy's answer (the one that I accepted) is quite long, but it is also one of the most comprehensive and insightful things I have ever read on StackExchange. If you are interested in this question, his answer, while long, is worth the time to read and absorb. Sometimes, life brings us unexpectedly beautiful things, and the best we can do is appreciate them and be grateful.

$\endgroup$
4
  • $\begingroup$ Read a touch of class by bertran myers. He covers object first (or a top down approach, starting big and adding detail. And using a very nice, text based, OO language, that avoids most of the issues). $\endgroup$ Jun 14, 2017 at 20:38
  • $\begingroup$ @nocomprende What is the textbook? $\endgroup$
    – Ben I.
    Jun 15, 2017 at 10:39
  • $\begingroup$ Here is Bertrand Meyer's home page se.ethz.ch/~meyer with a list of books. $\endgroup$ Jan 31, 2018 at 9:30
  • $\begingroup$ You might download a copy of Homeworld - the game was written in the late 1990's and still runs reasonably well on Windows 10 (and I have compiled it for linux in the past as well). It is written in ANSI C, but it is an awesome example of OO programming in a non-OO programming language, and something the kids might find fun. $\endgroup$
    – pojo-guy
    Feb 12, 2018 at 4:19

9 Answers 9

8
$\begingroup$

tl;dr: When you teach with the OO paradigm, you get to control the flow of ideas and the level of complexity at any moment.

Here we examine the first course in computing, no matter the educational level. Presumably this is for a formal course, though it can be adapted to self-study. Presumably the students have mixed ability and backgrounds, neither all superstars nor laggers.

In my view, the purpose of the first course is to teach students how to program. It is not to teach them a particular language, and not to teach them the esoterica of that language. How you proceed in practice depends on your own background (the teacher or learner) and on the language you choose. Actually the dependency is not on the language itself, but on the paradigm that the chosen language embodies.

In order to learn how to program, you must first have a concept of the nature of a program within a paradigm. But we are burdened by our history: the history of programming languages and the history of how the instructor learned how to program. So we first consider the question What Is A Program. The answer depends on the paradigm. Leaving out assembly language, in which the program is a sequence of simple statements and branches, we have several possibilities.

Fundamental Nature of Procedural Programming

Languages like C and Pascal were designed in an era in which it was discovered that go-to (branch) programming led naturally to unreadable and unmaintainable programs. Dijkstra, Hoare, and others came to the realization that Structured Programming was superior and sufficient. In Structured Programming the fundamental program structures are sequences of statements, selection of alternatives, and repetition. These can be represented explicitly in languages without reference to branching. They can be explained as branching, but it is not essential to think of them in that way. Combining this concept with the idea of (procedural) abstraction (naming coherent parts of a program and invoking them by name) produces the following way to think about the nature of a program:

Envision a problem, for which you do not yet have a solution, as a set of sub-problems. If they all had solutions a known synthesis would let you combine them into a solution of the whole. Note the two requirements: (1) the set of sub problems must be complete and cover the whole, and (2) a synthesis of solutions is known that would combine them into a solution of the whole. The sub problems themselves may have no known solution, but they must be solvable.

For each sub problem does not have a known solution, recursively decompose it just as above. A solution should be a simple program (procedure) that satisfies all of the requirements of that (sub) problem. If you cannot provide the solution, then recurse until you can solve all of the smaller problems.

Once you have solutions to all the small problems build up a solution to the whole from the lower level syntheses, which were known, and which drove the decomposition in the first place.

Thus the nature of a program is a tree of solutions, with each leaf a (hopefully) simple procedure/function. Each procedure/function solves some part of the original problem. The larger problem is now envisioned as a tree of problems and associated sub problems.

If you teach in C or a similar procedural language in the first course then the most important task is to give students practice with this process. Never mind all of the intricacies of int values and mutation, and pointers, etc. They must learn to understand the nature of a program. Everything else is in fulfillment of this goal. If they learn that, but not the whole language, they can fill in those details later, or on their own. Without that structure they will write terrible programs with long and unwieldy structure, and impossible-to-decipher functions.

Fundamental Nature of Functional Programming

The first Functional Language was Lisp (List Processing). It was developed based on Church's ideas on the Lambda Calculus. Functional languages are provably as powerful as those based on Turing Machines - a famous result. Lisp was originally thought to be inefficient since it incorporated an inefficient garbage collector, and that unfortunate judgment has stuck, though modern functional programs can be as efficient (or even more so) as those of other paradigms. Lisp has many modern successors, especially Scheme and Clojure. While Lisp traditionally uses only an abstract syntax (parenthesized lists), other successors have a concrete syntax that appeals to many (including this author). Languages like Standard ML and Haskell fit in that category.

A functional program is best thought of as an expression, which, if evaluated, produces a value. Since functional languages tend to be incredibly regular, the "value" returned by evaluating an expression might, itself, be another expression. I will used Scheme to explain ideas as we continue. In functional languages with syntax, things will look different, but reduce to the same ideas.

In Scheme, a program and its data are represented by lists: (a b c d). If the list is evaluated it is a program in which the first element is a function (expression) and the rest are the arguments (also expressions) to that function. However, the list need not be evaluated, in which case you can think of it as data (or as an expression to be evaluated later).

Different functional languages differ in when the arguments to a function are evaluated. Originally they were evaluated eagerly, before the function itself is invoked. However, it is also possible to design a language so that evaluation of expressions is delayed until they are actually used. Each has advantages and disadvantages, so functional languages usually compromise (using special forms and macros) so that some expressions use their own distinct rules.

Another feature of an expression only language is that you do not have side effects, only values. Output to a printer and graphics construction are not functional concepts, so special forms can again come to the rescue to provide the possibility of side effects, though most programs work to minimize and localize them.

A pure functional language (or the pure core of a more complete language) will be without special forms and side-effects. In a pure functional program the programmer constructs an expression which will produce the required solution to the problem if evaluated. Smaller scale problems are represented as the arguments to that initial expression and they can also be (recursively) arbitrarily complex expressions themselves. Evaluation of the original (top level) expression implies that the arguments are also evaluated in some order dependent on the language.

Since people do not like to write arbitrarily complex expressions, it is also possible to name expressions (abstraction) and invoke them by name. These names are usually called variables but normally they do not (cannot) actually vary. Once a name is bound to an expression (creating a variable) that variable cannot be bound to another, though the name can be reused - a confusing distinction, of course, until you understand scope. Data in most functional programming languages is immutable. One constructs new lists from old, rather than modifying a given list.

So, beginning functional programmers need to understand the expression, subexpression concept and practice it. They also need to learn at least a few special forms and how they behave differently though they actually look the same. For example, an if-then-else selection structure is normally a special form since eager evaluation of the "then" and "else" expressions is usually not desirable (especially if either has side-effects). As their experience with the language grows they need to learn more about the special forms and their individual rules.

There is an additional task for the beginning functional programmer. Normally repetitions (while, for) are not used in functional languages. They are replaced by recursion, especially tail-recursion. So the beginning programmers need to learn how to pose complex problems recursively with a special focus on tail-recursion. This results in some beautiful idioms that can be mind-blowing when first encountered. For example, reversing a list in Scheme can be done in linear time if you know how, but a naive program will likely be quadratic. The programmers do not need to learn more of the language to do this - there is very little "language" to learn - but must learn more of how to use the language, often by thinking recursively in powerful ways.

Fundamental Nature of Object-Oriented Programming

The first object-oriented language (OO) was Simula, which was developed to facilitate the creation of complex simulations, say of industrial equipment or governmental systems. This may be a key to how to teach the paradigm to novices. See this answer to a different question, for example. C++ was conceptually based on Simula. The next OO language was Smalltalk and most object-oriented languages derive from it. The most direct successor to Smalltalk is Squeak, which is a beautiful choice for teaching, but seldom used outside a small circle.

Imagine a problem that you can conceive of as being solvable by some set of things, each of which has the ability to act on request and to return some information based on those actions. Think of how you would design those things. Each of the things itself has a problem, its piece of the original, and that smaller problem is solvable by additional things with the same sort of capabilities. The things are heterogeneous (many kinds), some simple and some complex. Simple objects can be coded in a language, but complex ones need to be further decomposed.

An object-oriented program is envisioned as a web of objects (things), perhaps just one, that cooperate in the solution of a problem. An object itself is a bundle of behavior that provides services normally for other objects. The web arises from the fact that any object can hold a reference to other objects with which it can communicate - eliciting behavior. Each object takes responsibility for some part of the solution. An object is a value that can be queried for information to solve its own piece. Additionally, it can be directed to act in creation of the final result. Communication with an object is called a message. Both the queries and the actions often (usually) cause additional messages to be sent to other objects, which aid it in fulfillment of the query or action.

Additionally, and this is the important point, objects are themselves constructed, mainly out of other objects (recursively): their parts. They communicate with their parts in the same way (messages) that they would communicate with an "external" object. Thus, the structure of an OO program is a web/graph of communicating objects that are themselves (recursively) webs of objects at a lower level. The execution of such a program is a flow of messages that cause actions and return results from queries.

To create such a program, from scratch, you define one or more objects (using classes in Java or prototypes in JavaScript, etc.) and send a message to an object to start the computation.

OO languages have many features, usually including inheritance, which is often thought to be the biggest idea in the paradigm. In fact, it is not. The big idea is that OO enables the programmer to consistently build complex objects out of simpler parts by composition, keeping the parts essentially invisible to the clients of the object (encapsulation). Variables, other than references at the top level, are used to refer to the parts of an object so that it can maintain a consistent internal state and provide the public services.

In effect, an object provides an abstraction layer, above that of the language itself, in which the programmers building the system can think and extend, without reference to lower-level constructs, even those of the base language itself. Thus a set of objects provides a world that is self-consistent and complete enough to solve the question at hand. Once such a world exists, even novices can program within its framework and can think at that new virtual level. Thus, once a world with, say wombats, food, predators, etc has been provided, perhaps by the instructor, students can extend it, and can solve complex problems within it by creating objects and their web of interactions.

A beautiful OO program is one in which the objects themselves are simple, with simple methods. The complexity is not in the objects themselves, but in the interactions. When I am writing an OO program, I start to get "itchy" when any method has more than about three statements. Any structure nesting (if, while, ..) beyond two is cause for concern. McCabe's cyclomatic complexity metric should give you really small numbers. An implication, of course, is that there are lots of objects, and often, lots of classes. Fortunately, modern IDEs make these easy to create and manage.

Teaching the first course

You can teach the first course in just about any language and within its associated paradigm. If, however, you confuse your students about the nature of a program in that language you have failed.

The students should also write beautiful programs that their mothers would be proud of. The techniques you teach them should scale to larger programs than what they write in the first course. It should never be necessary for any student to unlearn bad habits and bad practices. If they can only program by writing two-page functions/methods filled with deeply nested selection and looping structures they are failing. The parts they build in whatever language/paradigm need to be small and understandable.

Consequences for teaching the first course (focus on OO)

If you need to teach a course and intend to do so without any preparation, the procedural paradigm is likely the easiest for you. You need a suitable language, a compiler, and an editor. The language provides the "stuff" of programming in its few data types and program structures. To be a success here, giving students the essential idea of procedural programming, you will need to find interesting problems. This is difficult since your tools are so primitive. You will also need to guide them into the problem decomposition and program composition to build up the two trees (problem - solution). They often tend to do too much in a given function. Make them factor out every difficult bit and apply intention revealing names to the parts factored. Require then to use short functions, limited nesting of program structures, etc.

If you want to teach OO programming, on the other hand you need to prepare before the students begin. You need to have in hand one or more virtual worlds found, or constructed by yourself, in which they can do interesting things. Making it interesting is easier, since the structure of the world is up to you. Students programming in one of your worlds can start out with nothing more than sequences of messages to one or more objects to get some desired effect. If your world is graphical, all the better, since the students can see the effect of their program, and hopefully where they go wrong when they do.

Next, in the OO world, students can extend one of your (say class) structures to add some additional behavior. They can do this by inheritance if the language permits or not. I would strongly suggest that you not overemphasize inheritance. Certainly avoid deep inheritance hierarchies. Ignore the concept of "reuse" and instead just extend the made-to-order world with interesting behaviors and/or objects. Since you have built the virtual world, you can control the order in which ideas are presented to the students and can control the complexity of what they must deal with at any moment. You can introduce deep concepts in a simple way in order to achieve some local small/scale effect as well. Not every program needs to be math-like as you have richer things than integers, etc.

If you want to teach them OO programming, do not think that you first have to teach them procedural programming. Some of the ideas of procedural programming naturally occur in writing methods of OO programs, only in a smaller scale. It is easier to move from OO to procedural than the other way, actually, since the methods written are a lot like the procedures/functions of the procedural paradigm. It is also not quite as likely that the students will write monster methods, though you need to guard against the SEE-ALL-DO-ALL class, just as you need to guard against the ONE-TRUE-FUNCTION in procedural programming.

The beauty of the OO paradigm for teaching is this. While any language defines a virtual layer in which to program, the objectives of the language designer were not pedagogical. When you define a higher level virtual world atop the language level, you, in fact can use pedagogical principles to construct it and provide a world in which the key concepts are easier to learn. If that world is also Turing Complete, all the better, but it is not essential - especially if you intend to use several smaller worlds rather than a single framework.


Note that a few additional paradigms have been omitted here - concurrent programming, in particular.

A paradigm is a way of thinking. Adopting a new paradigm may require a radical change in how the students think. This is much like the change in warfare from aristocratic knights on horseback to a peasant army of longbow archers that was first recognized at Agincourt in 1415. However the change did not become complete for about 100 years, Henry V to Henry VIII. After Henry VIII, English kings were no longer trained as knights.

Paradigms are by nature distinct. They are not ordered. A longbow-man did not need to have any of the knight's training to be successful. The computing paradigms are also distinct and self-consistent, not ordered. It is not necessary to learn one before any other. Nor is it necessary to mix them. In fact, the second paradigm learned is always difficult, as you already know how to do things, so the new structures seem superfluous to you. That is not a reason for not learning several, but it needs to be kept in mind to help explain the difficulties. The first course, however should be pretty pure to avoid confusing students.


It is a fundamental principle of modern computer languages that they define an internally consistent, Turing complete, view of programming that needs no appeal to lower level constructs to be understood. While it is true that such languages are in fact compiled to lower level constructs it is inherent in the concept that understanding does not flow from compilation, but the other way about. In fact, most of us (non-compiler-builders) would have a hard time understanding the intricacies of what really goes on in an optimizing compiler. The basics are easy to get, and the details are very complex. If you had to understand all of that to write a C program you would never know where to begin. You make assumptions, but they may be wildly wrong in light of modern systems with multi-level cache, co-processors, etc. That understanding is not needed if the language itself is complete and consistent.

Many languages are designed around a particular paradigm, sometimes just due to the time of creation. C is procedural. Java is Object-Oriented. Haskell is Functional. Some, however are multi-paradigm; C++, for example, is neither duck, nor dog.

$\endgroup$
7
$\begingroup$

Students latch on to the familiar which is usually what they're introduced to first.

So... teach objects first and unless you work hard at it, the kids will tend to use an OOP hammer on every problem regardlessof appropriateness.

Teach procedural / language constructs first and the kids will tend to write HUGE main functions and static methods if left to their own devices (assuming Java).

The truth is that you can do it either way.

When I've done objects first, start with a simple object - maybe a "greeter" that returns as string that says hello:

public class Greeter{
  public String returnGreeting(){
   return "Hello";
   }
} 

Then you can add an instance variable, constructor, setters etc. to build up the tools.

You can then add language constructs in your classes.

$\endgroup$
3
  • 1
    $\begingroup$ +1 for your bit about the dangers of both paths. I'd never thought about that. $\endgroup$
    – Ben I.
    Jun 14, 2017 at 21:06
  • $\begingroup$ One possible way to avoid the problem is to alternate, right at the beginning, between OOP and procedural coding solutions to similar problems, if your chosen programming language allows. $\endgroup$
    – hotpaw2
    Jun 17, 2017 at 20:13
  • $\begingroup$ It is too bad that there are competing paradigms. That is probably not true in many other fields that young people are introduced to. In areas like Economics, where there are so many theories and bases for ideas, and new ones emerging every decade, most people catch on that it is all gobbledegook and marketing. We haven't figured that out about computer science yet. $\endgroup$
    – Scott Rowe
    May 29, 2020 at 10:44
7
$\begingroup$

I'd definitely go for objects-late, or even objects-never in the introductory course (as you seem to mean "class-based OOP").

To teach programming, and work with a particular language, you first need to establish the basic syntax and builtin types and operators. (If there's a REPL, you can start with expression syntax and keep statements for later). You'll want to start with numbers (integers) and booleans - basic math and logic, the evaluation of which most students will know from their electronic calculators.

Then introduce variables, to "give names to things" - a concept which most of them will already know from math education as well.

Now there's three important next steps, which you can teach in any order and depth:

  • Mutation: assignment statements, loop syntax, IO
  • Abstraction/Modularity: function declarations and calls, local variables
  • Data structures: objects - and by that I mean POJOs for Java and structs for C

Along with those, you can introduce more advanced topics like references/pointers, recursion, DRY, object identity, interfaces, and further builtin data types (e.g. strings), as far as you see fit.

With those concepts, they will know what programming is all about and what you can do with it. Grokking pointers and recursion is considered hard enough to probably be the conclusion of an introductory course.

I don't think there's any reason to teach classes (data + methods), encapsulation, inheritance, file modularisation and other code organisation methods yet. The OOP mentality has its merits for designing larger systems, but that's not what will happen in an introductory class.

$\endgroup$
4
  • $\begingroup$ Ben, Java 9 has REPL, so it's a win win. $\endgroup$
    – ItamarG3
    Jun 15, 2017 at 7:54
  • 2
    $\begingroup$ @Bergi - there's a good reason to teach OOP in an early class - ok, actually it's a lousy reason but so so many people buy into it. It's APCS-A and the college board. $\endgroup$ Jun 15, 2017 at 11:46
  • $\begingroup$ @MikeZamansky Apparently I'm not one of them, I haven't even heard of APCS-A until today :-) (I'm based in Europe). But yeah, if OOP is part of the curriculum and Java is required, one doesn't have much choice. $\endgroup$
    – Bergi
    Jun 15, 2017 at 11:58
  • 3
    $\begingroup$ Here in the US, the College Board (a non profit in name only that a number of us oppose for many many reasons) has an outsized influence on education in the US. Schools have been bamboozled into thinking AP classes (the colloege boards offerings) are inherently good and in fact they've created cash cows by having municipalities pay for their exams. It's about money, not education but one of their two CS courses requires OOP in Java $\endgroup$ Jun 15, 2017 at 12:01
5
$\begingroup$

I'm not a teacher, but my experience is that OO (and other related encapsulation techniques) teach you to write what you want the computer to do, while procedural coding teaches you to write how you want the computer to do it. OO is a powerful way to ignore the how until you need it.

As a result, anyone learning in an objects-early approach is going to struggle unless there's some benefit to learning to think this way. If your course starts with several helpful libraries (like perhaps a sprite-manipulation library), it could benefit from object-early (or any form of early encapsulation).

Personally, the challenge I've had with object-late is the side effect of telling the computer how to do tasks: you get used to the idea of telling the computer exactly what to do. The mental models which are built around telling the computer exactly what to do are tricky unless you're willing to take the time to push all the way down to the transistor level. At some point you have to admit that you're just telling the computer what to do and you trust that it knows how to do it. Objects-early teaches you that lesson from day one. Objects-late teaches it later.

$\endgroup$
1
  • $\begingroup$ Concrete thinking is easier, so how is more straightforward than what. Thinking what includes the idea that there might be an infinite variety of hows, as Pascal said. Few people are ready for that. $\endgroup$
    – Scott Rowe
    May 29, 2020 at 10:39
4
$\begingroup$

I looked into this very issue when I researched different books/curricula to consider integrating into my AP CS A course. One of the books I discovered was Objects First with BlueJ (book website). Here is an excerpt from their justification:

One of the reasons for choosing BlueJ was that it allows an approach where teachers truly deal with the important concepts first. 'Objects early' has been a battle cry for many textbook authors and teachers for some time. Unfortunately, the Java language does not make this noble goal very easy. Numerous hurdles of syntax and detail have to be overcome before the first experience with a living object arises.

...

With BlueJ, this is not a problem. A student can create an object and call its methods as the very first activity! Because users can create and interact with objects directly, concepts such as classes, objects, methods and parameters can easily be discussed in a concrete manner before looking at the first line of Java syntax.

You can access the first two chapters of the book here as an evaluation of the approach.

If you explore those chapters, you'll see that there is a lot of starter code provided for students. (Indeed, you can download the code for all the projects from the website for your perusal.) That is the key for how you structure a course this way. Students have to have pre-baked programs that they can interact with. BlueJ as an IDE makes this extremely easy with its graphical interface for creating objects and calling methods. If Eclipse were your IDE of choice (or if you preferred to compile via CLI), then this wouldn't work nearly as well if at all.

The idea it seems is that students can start to understand methods, return values, parameters, etc. by exploring a fully functioning example a program that follows the principles of OOP. Additionally, all syntax is taught in the context of classes and objects. That said, it is dependent on the choice of IDE and the ability for students to work with already-completed programs.

$\endgroup$
3
  • $\begingroup$ This is a good idea, but seems to be a graphical layer over java. I could suggest Eiffel, as it does not have the problems, that this is getting around. $\endgroup$ Jun 14, 2017 at 20:43
  • 1
    $\begingroup$ "it allows an approach where teachers truly deal with the important concepts first" Authors' justification relies on the claim that OOP is more important than other concepts. This need to be justified in turn. $\endgroup$
    – beroal
    Jun 29, 2017 at 12:31
  • 1
    $\begingroup$ Just to add a correction to the comment of @ctrl-alt-delor; BlueJ doesn't actually add a graphical layer over Java. It is an IDE explicitly designed for introducing OO to novices. However, one of its distinctive features is allowing visualisations of objects to help students understand the nature of objects. I am one of the authors of the book, Objects First with Java, mentioned in this particular answer. BlueJ doesn't have to be used with the book; indeed many people use it without adopting an objects-first approach. David $\endgroup$
    – kentdjb
    Jan 31, 2018 at 9:44
4
$\begingroup$

Objects can be more intuitive than procedural programming for children. Think about the huge success that MIT's Scratch has had in introducing programming concepts at all ages. To pick up the basics, all you need is an understanding that "if I tell the sprite to move, it will move; if I tell it to speak, it will speak; if I tell a second sprite to move, the first one won't."

On your question about "how would you restructure a class"

My first Java teacher started by telling us about how we could create a Frog in Java. He then went on to tell us that we could give the Frog a variable so that we knew how many legs the Frog had. Then he talked about creating a Frog named Kermit who has 2 legs, and a Frog named Bob who has 4 legs (assumably Bob is not an anthropomorphic Frog). He talked about keeping track of where the Frog is in space, and then adding methods that allow the Frog to jump to other places. We slowly built up the idea that an object can have state, identity, and behavior, without having to resort to hardly any procedural code.

It's actually pretty easy to teach this way, as long as you remember that you haven't taught things like variables and flow of control, and you don't assume the students know more than you've taught them.

Mike is definitely right about the "one size fits all" hammer problem, although I'm not sure when an OOP solution isn't appropriate. ;-)

$\endgroup$
4
$\begingroup$

The Justification is simple: this is how programming is largely done these days. Everything that people learn should be practical, something that exists outside the classroom. Whatever the students are taught should be something that they can use in many situations, and as others have said, should not have to be unlearned in order to learn something else. So teach what is.

I apparently have an extremely reductive attitude towards learning. When I was a small child (over 4 decades ago) my persistent questions about computers were:

  1. How could they possibly function?
  2. What on Earth are they good for?

(We still have these questions and they apply to people as well.) So I think that instruction should answer these questions conclusively. 1: Computers work because they are deterministic machines. Explain to some level of depth about how that is so and how it was developed. The first topic in any course should be History, to answer the "Well, how did we get here?" question, which is just simple respect for thinking beings. Nothing should be assumed or hidden. 2: Computers are used to solve [these types of] problems in a business context. They do math and store and retrieve data, basically. They perform useful processes to free humans of drudgery. Perhaps beautiful inside, most people really do not care.

As has been mentioned, people have a wide range of ability to do abstract reasoning, and this ability grows if it is cultivated, but, like the light bulb in the therapy joke, the person has to want to change, to learn to "think different". And that is very hard work indeed. Some ways of thinking are easier to grasp than others. My experience is that people do best when given concrete scenarios with understandable steps to take to solve a problem. One thing that will vex them is to confuse levels. When I first learned a fairly pure form of Lisp in college, the professor seemed pretty excited and/or smug that one could create anything at all out of Lisp. And all you needed was Lisp to do it with. Essentially he seemed to be saying: "Here are your parentheses, now go forth, be fruitful and multiply." (Division was covered in the next semester.)

This completely mixes up syntax and semantics and will boggle most people's minds. If I hadn't already learned APL, Fortran, some varieties of Assembler, and several BASICs (in reverse order) I would have been lost, and most of these students were lost, and many quit. Not good teaching. Not a good paradigm. No one says that you make thesis papers in English by creating your own English: there is a level of "The Given" and then there is the level of "Your Ideas". This works for people and they can write programs on that basis.

But giving them a constructed world is not setting them up to succeed after they leave the course. Students need to see what is actually used, how it is used in production in scenarios where they might possibly get jobs. We have made a hash of this and constructed a tower of Babel with the many high level languages, tools, frameworks, operating systems, and so on. This was a bad move. Sure, we are creative beings, but there is only one set of traffic laws, and to get around in the world one must follow them.

The solution seems to be Apprenticeship, which I read that many large companies have adopted, as positions go unfilled and even college graduates do not have enough experience to start work. Thank Heaven that we finally decided to go back to an approach that has worked for 100,000 years!

$\endgroup$
3
$\begingroup$

This started as a comment, but got too long, and I realized I was moving well into answer land. Understand I'm not a teacher with a class full of kids, so this may be too esoteric of a way to look at the question.

However I have worked with students at different times from different types of backgrounds. Those who were in classes where OO programming is taught first took longer to produce their first working application, but when there was a working application it was far in advance of what their peers in a functional programming first class are doing.

I admit I learned functional programming first, then progressed to OO programming later, but that was because in 1975 there were not many OO languages available to a high school student using the school's teletype. Xerox had decided that Smalltalk was cute but had no commercial value, so the paradigm appeared dead.

Start with the understanding that Object Oriented Programming is a way of analyzing and structuring problems, and is not tied to any language.

You don't need an OO language to write OO programs. I have seen OO programs written in COBOL (not OO COBOL, which is neither OO nor COBOL). I built OO frameworks in K&R C, back when C++ was mostly an academic novelty. I have seen and built OO programs in BASIC (as in "10 let x=1", not the modern Visual BASIC which is a blending of BASIC and PASCAL).

Teach the concepts of dealing with an entity. There is the entity, its attributes, and methods for it to interact with the outside world.

In COBOL, you might embed the entity and attributes in a copybook, then the methods in nested programs (the lack of scope in COBOL sucks).

In C, it might be a struct in a .h file and a function library.

In OO languages, use the languages natural paradigm.

Personify your objects. Use pronouns like "he" and "she".

Teach to build the logic in the entity's method, and keep the methods very simple.

Show that a complex method means that the solution is either housed at the wrong level or not clearly borken out. If they are taught this from the beginning, a lot of issues that require retraining can be avoided.

$\endgroup$
1
  • $\begingroup$ I agree that the best way to write programs is the way any sensible person would do it, given enough experience, and all the paradigms are just marketing gone wrong. We want to somehow impart experience and insight directly, but that is impossible. Pronouns have become a minefield, so hopefully anthropomorphizing will slowly disappear. $\endgroup$
    – Scott Rowe
    May 29, 2020 at 10:35
2
$\begingroup$

An Early Objects approach should focus on problem solving techniques based on object interactions.

If your focus is to teach a (specific) programming language you should indeed have an objects late approach.

The key difference between early/late objects is the thinking paradigm you establish for your students. You want the most important ideas and skills to be the ones most frequently used/repeated. Sometimes it can be more difficult to "unlearn" something.

There is a good and relevant post elsewhere (How to START an Objects-First Course) that has some useful ideas worth considering.

$\endgroup$
1
  • $\begingroup$ Can you please summarize or add some important excerpts from the link? We want the answer to still be valuable even if the link dies. $\endgroup$
    – thesecretmaster
    Jan 31, 2018 at 2:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.