Jargon/Vocab about variables--- yes or no?

Some of these words are entirely necessary, some (such as tokenize) you might want to avoid early on.  However, I would suggest this as a guiding principle: use vocabulary as is necessary to get at the core goals you hold for your students, but do not emphasize vocabulary for its own sake.  A great visualization or metaphor at the very start (after all, freshmen!) will take your students much further along than a series of fine distinctions.

Here is a fun little article about 10 Extremely Precise Words for Emotions You Didn’t Even Know You Had.  The title is correct; when you read through the article, you will find emotions that you have experienced, but never described.  Nevertheless, you were able to experience the emotions perfectly fully.

Similarly, with the help of a great diagram or metaphor, students will be able to utilize concepts that are more advanced than they can fully describe.  That's okay - great even! - and later coursework can help them nail down finer distinctions as they advance.


Book recommendation on human "computers"

It is not clear to me what exactly OP is looking for, but one relevant book is: David Alan Grier, "When Computers Were Human", Princeton University Press 2005. The author served for several years as editor in chief of the IEEE Annals of the History of Computing. He was inspired to work on the book when he learned that his grandmother had graduated with a degree in mathematics in 1921 and that some of her fellow female graduates went to work as human computers. The book covers about two centuries between the 1760s and the 1960s.
In June 2005 Grier gave a lively hour-long presentation at the Computer History Museum also entitled "When Computers Were Human", a video recording of which is available on YouTube.
One large early project, directed by Gaspard Riche de Prony, that ran from about 1790 to 1801 is described in I. Grattan-Guiness, "Work for the Hairdressers: The Production of de Prony’s Logarithmic and Trigonometric Tables", Annals of the History of Computing, Vol. 12, No. 3, Jul. 1990, pp. 177-185. The title makes reference to the following fascinating detail:

These calculations were done by the third section, a large team of between 60 and 80 assistants. Many of these workers were unemployed hairdressers: one of the most hated symbols of the ancien regime was the hairstyles of the aristocracy, and the obligatory reduction of coiffure “as the geometers say, to its most simplest expression” left the hairdressing trade in a severe state
of recession. Thus these artists were converted into elementary arithmeticians, executing only additions and subtractions.

A key personality in the final phase of the history of projects involving human computers was the mathematician Gertrude Blanch (1897-1996), described in David Alan Grier, "Gertrude Blanch of the Mathematical Tables Project", IEEE Annals of the History of Computing, Vol. 19, No. 4, Oct.-Dec. 1997, pp. 18-27, as follows:

Gertrude Blanch can be viewed as either the last and most important leader of human computers or one of the first numerical analysts for electronic computers. From 1938 to 1948, she was the technical director of the Mathematical Tables Project, the largest and most sophisticated of the human computing groups.

I originally came across Gertrude Blanch as author of the paper "Numerical evaluation of continued fractions", SIAM Review, Vol. 6, No. 4, Oct 1964, pp. 383-421.


A prerequisite to understanding pointers is a basic understanding of memory. At least on the broadest level, students need to know that when they declare a variable in their programs, that variable is stored somewhere, so they can use it, access it, update it, etc. Where that variable is stored also has some address, so it can be located (specific addressing techniques need not be introduced yet). The specifics of heap v. stack, memory size (int v. long long), and other such concepts are not necessary to understand what a pointer is (but they certainly would help).

All this background established, here is the easy way to think of pointers:

  A pointer is a variable that contains an address of a variable.

Simple enough on the surface. That sentence comes from Chapter 5 of K&R (The C Programming Language by Kernighan and Ritchie). This chapter has a great explanation of pointers and arrays, and I would highly recommend it for an understanding of pointers, at least in the context of C. One key point for C is the following:

  Since C passes arguments to functions by value, there is no direct way
  for the called function to alter a variable in the calling function.
  ... Pointer arguments enable a function to access and change objects
  in the function that called it.

Now, to get into the details of pointer arithmetic, passing by reference, syntactic sugar vis-a-vis arrays, pointers do become more complicated. However, always keep in mind the simple definition that gets at their essence: pointers store addresses for other locations in memory.


Should the first Programming/Algorithms class be taught in pseudo-code?

No, it shouldn't.  It's an appealing idea, but when kids are just starting in programming, one of the few straws they have to grasp at is that it is, on some level, very concrete.  I type:

std::cout << "Hello World!";

... and out prints "Hello World!".  Without the ability to run and troubleshoot code, I'm afraid that everything will become abstract, and most students will simply flounder.

You can choose a language with easier syntax, such as Python, or a visual language like Scratch, but the kids really need something to actually run and manipulate if they are to make early progress.


One site that I find helpful for basic examples of coding task written in a multitude of programming languages is RosettaCode. While it is not always a win when going there, I still keep it high on the list of sites to check when looking for teaching examples or code that demonstrates something.

In this case the combination of the programming language Scheme, an example simple enough to use in a classroom and the Lambda Calculus Y-combinator are satisfied by this example:

  Define the stateless Y combinator and use it to compute factorials and
  Fibonacci numbers from other stateless functions or lambda
  expressions.

(define Y
  (lambda (h)
    ((lambda (x) (x x))
     (lambda (g)
       (h (lambda args (apply (g g) args)))))))

;; head-recursive factorial
(define fac
  (Y
    (lambda (f)
      (lambda (x)
        (if (< x 2)
            1
            (* x (f (- x 1))))))))

;; tail-recursive factorial
(define (fac2 n)
  (letrec ((tail-fac
             (Y (lambda (f)
                  (lambda (n acc)
                    (if (zero? n)
                        acc
                        (f (- n 1) (* n acc))))))))
    (tail-fac n 1)))

(define fib
  (Y
    (lambda (f)
      (lambda (x)
        (if (< x 2)
            x
            (+ (f (- x 1)) (f (- x 2))))))))

(display (fac 6))
(newline)

(display (fib 6))
(newline)

output

720
8

Bonus answer:

When others want to learn more about Lambda Calculus the first reference I always give is "An Introduction to Functional Programming Through lambda Calculus"

Note: While the link is nice if you really do use the book often then please purchase the book.


When does excessive collaboration become plagiarism?

I'm presenting this as an answer to preserve it. It isn't a direct response to the question, I know.

Let me draw out a conclusion from @BenI.'s answer.

The plagiarism "problem" in education seems to flow from a (IMO) misguided notion that all student intellectual growth must flow from that individual only without any collaboration whatever. I used to believe that myself, especially when teaching math, but less so in CS.

Certainly work in isolation can lead to A-Ha moments that indicate growth, but can also lead to deep frustration and abandonment. But collaborative work while it may lessen the former somewhat certainly tends to eliminate the latter. Many years ago, when I was a math student, most academic papers were by individuals. That is much less so now, and in CS, collaborative work is the norm.

Try to teach and organize your course so that plagiarism isn't an issue. Encourage peer work, peer teaching, peer evaluation, and all the rest. Find a way to evaluate individuals without requiring that their work be done in isolation. It better matches the work-a-day world that many of them will enter eventually. It reduces headaches, guilt, punishment. It encourages learning, sharing, and growth. Be a shepherd, not a judge.

How you do it is a question of course organization and project selection. Permitting collaboration also allows you to utilize larger, more challenging, projects than you might be comfortable with otherwise. You can impose rules in programming courses, of course, requiring role changes while pair-programming (driver <-> navigator) for example. You can sometimes choose teams or pairs yourself, and sometimes let them choose. For larger teams you can even use sandlot-baseball team choosing, which I've found to work. (You choose captains, the captains alternately choose additional members until everyone is on a team).

Don't just permit them to work together. Try to find a way to require them to do it. It is harder for off-site assignments, but not always impossible, especially if your institution provides some sort of common workspace for students.

The cited research seems to be about improving teaching, not about detecting plagiarism. No student should be accused of plagiarism based on statistical measures only. The paper seems to correctly make that point.


I don't know how you frame the motivation for NFAs, but something I've found helpful is to put this up front, before introducing them.  Something like the following:

DFAs are the answer to the question "what does computing mean if we only have control and no memory of any kind?"  They are essentially flowcharts, an intuition every student understands.
NFAs are the answer to the "next" question, namely "What can we do if we can execute flowcharts in parallel?  Not just a little parallel, but unlimited?  Let's give them even more usefulness and suppose that we can extract the right answer if it appears on any thread, instantly.  Does this give us any advantage over just one flowchart?"

I've found my students are able to do quite well with this intuition, because they're willing to suspend disbelief regarding the conceptual hurdle that "magic" -- the primary mechanism that defines NFA execution -- cannot be implemented in a real machine.

Then, when they learn that the "magic" of an NFA gives nothing new over a DFA, many of them become quite excited.  As they should :-)

[EDIT]

To expand on my comment, I've found that I can carry this story throughout the semester, as motivation for every one of the theoretical devices.  Philosophically, I think of the automata theory course (at least the first, undergrad version) as centered around the question "what do we mean by the idea of computing?"  This in turn divides into two, interlocking questions:  what power do we get by adding certain capabilities (in memory, memory access, and concurrency), and what price do we pay for adding them?

I gave what I see as the answers to these questions for finite state automata above.

The next one in the story is the idea of adding memory, without worrying about how much, but with only limited access abilities.  Following Sipser and most every other automata textbook, this means memory with only stack access and no limit on concurrency:  i.e. NPDAs.

ASIDE:   I first learned this stuff out of Floyd & Beigel's magnificent text, "The Language of Machines"", and they insert an intermediate study between FSAs and NPDAs, namely the capability of memory that can do nothing but count up and down (what they call "counters").  These are strictly more powerful than FSAs (they can solve the balanced parentheses problem), and strictly less powerful than PDAs, either deterministic or not.  It's kind of a cool thing to add if you can, because it gives an easier to read yet fully formed notion of the idea of simulation as a mechanism for studying expressiveness.  There's also at least one, very practical application that I know of, from language implementation:  checking whether a break statement is correctly placed within a loop.  About half of my compilers students try to do this with the same technique they use for checking nested comments in the lexer:  incrementing a counter when a loop is entered, decrementing it when a loop is exited, and checking that the counter is positive  when a break is encountered. If your language supports nested procedure definitions, this won't work, and the nonequivalence of counter and stack machines explains why.  This side topic takes time, though, and I've only ever seen it in the Floyd & Beigel text, which is, sadly, long out of print.

Anyway, memory with only end access and unbounded concurrency gives you the class of CFGs, of course.  By the time we get through that and the CFG pumping lemmas, I've found my students enjoy the overarching story enough that they appreciate the detour into DPDAs enough to revisit the question "with end access memory, does concurrency give us any advantage?"  I've never found time to really study deterministic PDAs (which is okay for me, since I also teach our compilers course :-) ), but students do seem to enjoy learning that the answer to the concurrency question for stacks is that is does make a difference.  I even managed once to show how the existence of an inherently ambiguous context free language gives an an alternative proof of the nonequivalence in expressiveness.

Finally, there are Turing machines, of course, which represent the answer to the question of what we get when we combine control flow with unbounded memory and no limit on access.  The fact that concurrency once again becomes irrelevant to expressibility is mind blowing to me, and it seems to be to those students that aren't exhausted by the semester, since we're always near the end at this point.  If one needs a good story to explain this, it's in the fact that concurrency can always be implemented by threads and sufficiently powerful thread scheduling (which is, essentially, what the proof of simulation of NTA by DTA is).

At this point, I try to include the Universality Theorem, at least a mention of it.  More than any other result, I find that this one ties Turing machines to real programming languages in a very effective way, because it guarantees that every "real" programming language can be implemented with the minimum tool set of deterministic control flow and random access memory.

Including the Universality Theorem also has the nice advantage of making the non-computability results more concrete.  It's not just that Turing machines can't answer such questions: no real programming language can, and the combination of the Halting Problem and Universality explains why!


How can I help students develop intuition about a programming language?

I think this is a structure of knowledge problem. I suspect the disconnect is that you have organized your knowledge in a way your students haven't.

You understand that strings, lists, dicts, and deques are all something called containers. You also understand that all containers can be accessed with []. Therefore, it's straightforward to consider that [] could be applied to any new container you come across.

But do your students understand this organization of types in terms of containers? I bet they don't yet. They are still thinking about each type as an individual entity, disconnected from others.

Experts' knowledge is organized much more effectively than novices'—— that's what it means to be an expert. (Cite: Relevant section from How People Learn, summary from Cal State Northridge)

On the other hand, novices' understanding is tightly tied to shallow features like syntax. It will take a while for them to see the deeper organizational features.

You can help your students become more like experts by explicitly helping them organize their knowledge. If it's not overwhelming for the students, teach them what a container is and what all containers have in common. More generally, connect concepts together to help support students' development of those expert-level connections.

Good luck!


Thoughts on language for Intro to Data Science?

The biggest strength of R when it comes to Data Analysis is in its data visualization. As you've mentioned it is a more or less dedicated tool for statistical analysis.

The thing with Python is that you can easily go a bit off course with the lectures because for Statistical Analysis you'll have to understand, install and work with different libraries/APIs for plotting (matplotlib/pandas/plotly) and processing your data (scipy/pandas again/numpy). These may take different approaches for installing and working with besides being tools on their own.

RStudio already sets up everything for you for the most part so you can just focus on implementation; if you happen to need something extra installing packages from CRAN is incredibly easy letting you do it from the script itself rather than opening a terminal with conda or pip or whatever.

My notes:

If your interest is teaching more Data Science, as a tool in itself, go with R. It will let you focus more on concepts which are general.
If you're interested in teaching General Programming as a tool for Data Science and maybe other things, go with Python.
If you like both ideas, I'd start with R and replicate results with Python later to show its integration with different tools. This way your students will see both approaches are feasible in the case they go out there and see it in the job market.


What are some examples that could be used when teaching subroutines or methods in the context of OO?

I almost always teach programming by connecting each component of programming with something in real life. For instance, when explaining variables, I ask the students to imagine them as boxes in which you put things, like food items or gifts or something similar.

For methods, I ask them to think of their friends. For instance, there will be a 'rich' friend, and then there are 'stingy' friends, 'useful' friends and so on. So, bring up a scenario. For instance, lets say the challenge, you are in trouble and you want to ask for help.

You have 3 friends - rich, stingy and useful. Instead of friends, think of them as methods, and you (as in the individual) is the program or the main method. Now, you need help, which friend aka method are you going to call...you will obviously call the 'useful' friend/method.

So, essentially, whenever you want something to be done, you design/code a method for that, just like how in life, you want something done, you call upon a friend. So, methods are like friends who help out get things done.

Of course, in an actual classroom, I pick students, make them do role-play (pretend that they are functions) and make it all very active (and hopefully fun) and it seems to work for me.

and of course, once they get the concept, I jump into code right away, building small methods that do simple print statements, then upping it to display simple variables and then complex stuff including sending and getting values


There are two reasons (at least) for note taking

creating a shorter, abstracted, version of your sources that you can save to return to later without recapitulating your whole education.
learning something about the topic - getting it in to your head.

For the former, you can type up notes as you go. Try to focus on the main points, not the detail. Leave lots of references in your notes so that you can easily return to the source as needed.

However, if your objective is to actually learn the material from an operational perspective - using it - then typing up notes doesn't help nearly as much. Writing out things long hand is much better - but you may need to practice with the pen. And the fact that it is slow is also an advantage, since you engage with the material over a longer period.

If you are studying for a field in which you want to become a professional, take notes by hand with a pen on good paper. In fifty years you will still be able to use those notes whereas the computer notes are likely inaccessible.

The reason for long hand writing (even printing) is that your brain is more engaged in the process than it is with typing. That is how you learn - engaging the brain, not the motor muscles in your hands (unless you are learning a physical act like rock climbing or a martial art, where muscle memory is equally important.

Moreover, to learn some subjects you need to also use the knowledge you are gaining. In math you solve a lot of problems. In CS you write a lot of programs. I History you pose a lot of theses. Whatever is appropriate, but it involves problem solving and creation in some way.

See https://cseducators.stackexchange.com/a/1168/1293 for additional comments, including the other answers to the same question.

If you search this site for "changing the brain" other hints will reveal themselves.


Training students to give better feedback, when remote teaching

Since you are working remotely, I might direct them to a Google Form that asks followup questions.  So, if they initially chose "Something doesn't work!" the form would follow up with a series of questions:

What, very specifically, doesn't work?
What is it doing instead?
What have you tried so far?
Please paste only the relevant parts of your source code here.  (Don't give me parts of the source code that you are sure are not relevant!)

It's almost like (gently) easing the kids in to SE norms :)


Is there a good textbook for writing an interpreter in an imperative language?

For the "intermediate code" version of an interpreter there is no finer example in a small book than On Pascal Compilers by Per Branch Hansen. You need to be able (or a least willing) to read Pascal of course.

This book is a rare instance of CS Literature. Hansen is one of the masters.

The way the code in the book is developed you actually see the difference between compiling and interpreting as he does "code generation" to an intermediate language and then provides a separate interpreter for that language. So you see what you need to do to get to the point at which interpretation is efficient and then see how the interpreter part actually works.

The book is out of print. Check around for a used copy. Amazon currently has it a bit cheaper than Abe Books. If you have a good University Library nearby they may have it. You might also be able to get a copy from interlibrary loan that is supported by most libraries.


Evaluating resources for teaching myself reinforcement learning

If self-learning is a goal, you don't need to necessarily choose between resources at all.  I had to self-teach a tremendous amount of material this year, and to do so, I roughly borrowed the methodology from Barry Farber's incredible How To Learn Any Language.

The basic idea is to grab multiple (quality) resources of different kinds, and begin to work through all of them.  Do a little bit of each one every day, and make all of these activities as active as possible.  (For instance, create flashcards of concepts you want to review.  While reading physical books, don't be afraid to underline things you don't understand and revisit older underlines.)

Every content creator attempts to get at the material in a way that they feel emphasizes what is most important. This means that you end up learning multiple central conceits, and you develop a deep and capable understanding relatively quickly. If you find yourself getting stuck on one source, do your underlining, and move on to the next one.  The next day, you can revisit the first source with the new understandings that you have gained from the other resources, and thereby continue to progress.


Teaching high-level versus low-level concepts

TL;DR Build a world, let the students program in that world.
This is largely a history lesson which, at the end, will give hints about how to teach students to become effective in a modern OOP language quickly.
A deeper principle than Higher to Lower abstraction, however, is the principle of teaching in a Spiral manner. This principle says that the student's education should not be linear, with each thing taught completely only once. Things should be reinforced repeatedly, with each turn of the spiral adding new concepts to old, but those new concepts themselves returned to later, each spiral reinforcing older lessons as well.
Another principle here is that students learn by doing, not by listening or reading. There are a few exceptions, of course, and teachers often fall into the exceptional class, but it is rare. I've written in answer to other questions here that learning involves physical, biological changes in the brain, requiring reinforcement. There is supporting research of course.
History
With that, let me take you back to about 1975 or so. The language Pascal existed then, but C did not. Pascal was not, at that time widely used in education. FORTRAN was. Early attempts to teach using Pascal resulted in "poorly spelled FORTRAN" programs, since that matched the thought processes of programmers and teachers well versed in FORTRAN. It is said that a new paradigm only takes hold after the people holding to the old one die out. This was actually the case with the Theory of Relativity in Physics. Einstein was dismissed (that "clerk") by the superstars of the physics establishment until Poincaré's influence waned (and he died).
Pascal was created with the purpose of having a tool to directly implement Procedural Programming (PP). The essence of PP is this. Envision a Problem, P, as decomposed into a set of sub-problems, P1, P2, .... The sub problems have one of two characteristics. Either they can be immediately solved, Sk = solutionOf(Pk), or they can be, recursively, decomposed into yet smaller problems. Additionally it is assumed in PP, that there is a Known Composition method for putting the solutions to the smallest, undecomposed, problems together into a solution of the larger problem of which they are a part. In other words, decompose into sub problems going down and then recompose solutions going up.
Thus, a Pascal program was intended to look like a collection of simple procedures that invoked other simple procedures until you reach a state in which the lowest level procedures can be written in the primitives of the language. This was also called Top Down analysis and programming.
HOWEVER, early Pascal programs didn't look like that. There was a single massive procedure, or even just a BEGIN ... END. block that did everything, with only trivial parts factored out, usually those things that needed to be executed more than once. Hence, misspelled FORTRAN. Advice in early teaching materials was to factor out a procedure when it could be used several times, otherwise just inline the logic.
That was the state of affairs in about 1980. Then something magic happened. Richard (Rich) Pattis wrote a book called Karel the Robot (1981) that showed how it could be done. The book came with a simulation program in which students could write "Karel Programs". The Robot Programming Language defined in the book and accepted by the simulator did not reveal primitive, machine level, constructs such as integer and real. There was a single robot that moved in a virtual grid-like world. There were five primitive actions: move (one block), turnleft (90 degrees), pickbeeper, putbeeper, and turnoff. Nothing else. beepers (a primitive kind of thing with no behavior) could be carried but there was no protocol for asking how many the robot carried. That was implicit in the program state, not something that could be queried. Beepers could also be found on the corners of the world. It was an error to try to pickbeeper with no beepers present.
In addition to the five primitives, the robot had a rudimentary sensing capability. It could sense a beeper on the same corner and it could sense a wall directly in front. Trying to move through a wall is a program error.
Notably, the robot programming language has no variables. Repeat: no variables. You can treat a corner, conceptually, as something like a variable since it can have several beepers and that can be treated something like an integer, but there is no protocol for converting it to an actual integer, and no way to build it.
With these tools, the programmer is able to write procedures (returning nothing) and predicates (returning booleans). There were no parameters of the procedures. Using the sensing capabilities, the student can utilize selection and looping to build sophisticated programs. Karel the Robot defined a Turing Complete language. More important, the book had a wonderful set of exercises. My contention is that if a student could solve every problem in the book they could, with their learned creativity, write any computer program (Turing Complete, remember). The book built programming skill, not just familiarity with machine concepts and language features.
The book has five chapters and in the original it was possible to cover it all in a bit over two weeks, at which point the path to Pascal was trivial. But at that point students could already produce a correctly structured PP program. No more misspelled FORTRAN.
The result is that students, in their first turn around the spiral, learn program structure with few low level details (five primitives, procedures, predicates, if, and while). The second edition of KtR by Pattis, Stehlik, and Roberts (1995) contains the first edition and adds specific hints on PP such as how to go about the problem decomposition and how to build IF and WHILE structures. But you can do anything. Sorting is fun, with beepers standing in as a kind of surrogate for integers, though you can't really count. Recursion is supported, though not discussed in the original. An interesting problem is to search an infinite space for a beeper.
Creativity Under Constraint
Another aspect of the teaching philosophy underlying this principle of Creativity Under Constraint. A naive view is that you can do more with more tools. However, learning to use a few tools to a very high level of skill builds mental structure that a fuller tool set will not. If a student depends on solving the next problem with the next tool, they will be a bit lost when there are no more tools available and you have to really think.  Creativity Under Constraint tries to avoid this.
As a simple example, consider poetry. If I ask you to write a poem you have few constraints. But that problem is hard hard. But if I ask you to write a Haiku, I give you constraints, but I also give you guidance and structure. The problem, though constrained, is actually easier (but not trivial, of course). This is a Big Idea.
It was vital that KtR provided this rigidly constrained world in which programming occurred, but not so rigidly constrained that any programming idea could not be expressed.
And of course, no one suggest you should only and always write Haiku.
Paradigm Shift
It is natural when a new paradigm arises (Relativity, Procedural Programming, OOP, Functional) for the practice to be thrown into a state of flux for a while, but hopefully not forever. The paradigm shift from a simpler form of imperative programming (FORTRAN) to PP was long and hard. Rich provided a tool that showed the way. It was widely adopted and helped teachers over the hump.
The interesting thing about a true paradigm shift is that it renders the earlier paradigm obsolete. A mounted knight in shining armor stood no chance of success against Henry V and his army of peasant longbowmen. And in turn they stood no chance against properly deployed musketeers. But deploying longbowmen the same way you deploy knights is just dumb.
In CS, however, a paradigm shift may not have such a profound effect, but over time, it will. Actually the last English king who was fully trained as a knight was Henry VIII and that was about 100 years after Henry V and the battle of Agincourt.
But, my way of thinking and teaching is to treat a (lesser) paradigm shift as if it were truly profound. Learn it. Adopt it. Teach it. Your students will be looking forward, of course, not back. And as I've said here before, my job isn't to teach them what I know, but what they need to know. Today that is a good solid view of OOP, for the most part.
And, programs no longer look like FORTRAN, but they, sadly, too often look like Pascal.
The Present State
We have gone through another Paradigm Shift, though it is now quite old, but too many people have not made the jump to OOP from PP. Too many programs are just PP programs with a few classes. Moreover, I see methods that are too long and too complex, putting the complexity into the methods themselves, rather than into interactions between objects viewed as bundles of behavior. Java, and later languages enable this, but using it effectively is an acquired habit (and taste).
The successors to KtR are Object Oriented. Karel J Robot (java), Karel R Tuesday (ruby), and Monty Karel (python), by Bergin, Stehlik, Roberts, and Pattis, all provide a structure, along with a simulation, in which good OO programs can be written using inheritance and composition, but with only a few ideas other than the essential ones. None of the books use integer primitives in any way. Variables are references to objects. These books are more complex than the original and require about half of a first course to cover. But at the end, the student has a clear grasp of the structure of an OOP program and can think about problem decomposition into a set of interacting objects. (These books permit the creation of several robots, not just one.) Once they deeply learn what is presented in the books it is a relatively easy task to introduce lower level concepts (int, array, ...) but also things like Collections and within reach. One drawback of the OOP Karel books is that inheritance is, perhaps, overemphasized, at the expense of composition of objects to build other objects. My personal view is that OOP enables composition primarily and inheritance secondarily, though the latter is more obvious in the syntax provided. Early on, however, Polymorphism is discussed deeply and implemented via composition using primarily the Strategy design pattern. Concurrency is also discussed briefly, since there are multiple robots.
Another feature/bug of the current books is that they use the actual languages (Java, Ruby, Python), rather than a constrained subset. While only a subset is taught, instructors are free to add things not in the books, such as integer valued variables and counting. This is a mistake, as the example below will demonstrate. One of the important (vital) choices of the designers what what NOT to teach or even include in the book. The Java book has a follow up, however, which fills in quite a lot for a full course.

Example:
To illustrate some of the above ideas and extend them a bit also, consider an exercise from Karel the Robot.
The robot, Karel, is at a corner facing East. Somewhere directly in front of the robot is a beeper (possibly even on the same corner). The Karel's task is to move to the beeper, pick it up, turnleft and move the same distance that was traveled to get to the beeper initially and put it down again.
Note: no variables, no integers, no counting is possible, except via recursion with the count held in the runtime stack, implicitly. And, of course, the previous sentence is an explicit hint.
The advantages of this are legion. You have a deep way to talk about recursion, especially the fact that recursion has two "phases": winding - to get to the base case, and unwinding - to return all the calls. To do this exercise you need to do actual work in both phases, so you can talk about the fact that both are useful (and can introduce tail recursion which this example does NOT exhibit).
It is interesting in a way in which a standard recursive computation of, say, Fibonacci numbers is not.
It is an interesting problem because solving it changes the brain of the solver. However. If the student already knows how to count and has tools (int variables...) to solve it, this problem is completely boring and adds nothing (other than a bit of reinforcement) to changing the brain.
Moreover, later on, the instructor can return to this example (around the spiral) when counting is later taught and show how counting both simplifies it and makes it more dangerous, since such things as off by one errors are now more likely.
So, what seems simple, becomes profound because it is introduced into a constrained system. The constraints both give guidance/structure AND deepen learning in ways foreseen (we hope) by the designer.
Copacetic.

Notes: While Pascal set out to be the "best" language for  PP, it turned out to have flaws, especially for team based work. Modula-2 is much better, but is a true successor. However, it took lots of users writing lots of Pascal software to reveal the flaws. C++ started out as a better C+Simula. Object Pascal (from Apple) started out as a simpler Smalltalk, and Java is in that family, as are Python, Ruby, and Scala.


Writing a fully functional application, even if that application is 'trivial' quickly becomes complex and will need some good thinking on paper before starting your code. I would suggest learning a software development proces that starts with requirement analysis and takes you all the way to technical design from which you can start your code. The one I know is called ICONIX (for object oriented programming) described in "Use Case Driven Object Modeling with UML - Theory and Practice". The book uses a bookstore as an example application and is very hands-on. The application is developed using Java and the Spring framework. It is essentially a step-by-step guide to application development. Through object oriented analysis, you will create a detailed design in the form of a class diagram with attributes and methods allocation, and sequence diagrams for the most critical features. You will work through one use-case at a time and iteratively develop a fully functioning application.


Creating a rubric for computer arithmetic

I missed this question!
I will attempt to provide feedback in parts:

I am concerned that there are too many critiera.

I don't understand the reason for this concern, so I cannot comment upon it. The criteria seem reasonable to me.

It also raises the question of how a student shows they know how to, say, convert between decimal and two's complement. Do I keep testing them until they show me one successful conversion in each direction, or do they have to demonstrate that they can consistently do so?

I would personally be happy with a one-time demonstration within my own classroom (see below)

Is this too trivial of a skill to test, given that they'll forget the details, which aren't really important, five minutes after the test?

I think it's perfectly acceptable to explain to students that you are asking them to learn a skill that you expect will be temporary (converting a floating point number to IEEE) in order to help them get their heads around a deeper, more profound understanding that you hope will be permanent and intuitive (e.g. the general nature of floating point in practical computation).
In my classroom, I have students reproduce proofs with a similar explanation. I explain that, after memorizing a proof and reproducing it for me, I do not imagine that they will be able to reproduce it again 5 years later.  But I expect that they will come to understand the structure of the proof well enough that the next time they encounter such a structure, they won't be immediately lost, and I also expect that they will roughly remember that the fact that they proved is, itself, true.
In this case, while none of your students will presumably remember, give years out, exactly how to figure out what the least significant bit would be in an IEEE representation, you can expect that the students will (long term!) remember the tiered nature of the IEEE structure, and the broad-strokes, general elements of what it stores.
I think those are good and sufficient goals, and I think that the students will be okay with learning it as long as you break down the expected long-term benefits of the short-term learning.


In a course about Turing machines, how many questions like "Construct a Turing Machine that does X" should I include?

I integrate many, many simple TMs into both my lecture and as homework.  I also force them to use descriptors such as $\vdash$ and $\vdash^*$ on their machines.  I've found that it takes a long time for students to get used to basic operations.

They have no problem converting a given TM to its tuple members ($\delta$, $\Gamma$, $\Sigma$, etc.), but have surprising trouble seeing the performance implications of transitions on machines that I provide to them.  With practice, they get much better at this, but it takes (in my experience) a surprising amount of practice, both in encoding and decoding simple Turing Machines.

Some particular traps for my students have been:

navigating halting states (since they cannot transition outwards)
identifying ending conditions of loops
making comparisons between two strings stored on different parts of the tape
learning when it is appropriate to overwrite your data.

All of these take practice.  I do this in-class so that I can assist and guide, but I also have many hours of facetime with my students.  In a more constrained timeline, I would give out homework assignments instead.


Explaining to students why to use double instead of float (unless there's a very good reason)

Luckily this is quite simple to make clear, even if you are steering clear of the IEEE standard.  Honestly, even binary is not needed here.

I would start by borrowing a page from Scheme, and say that we can't make blanket guarantees about the exactness of decimal numbers.  For instance, when we try to express $2/3$ in decimal, and it doesn't work!

All the more so when we are restricted to 10 digits.  We write $0.666666667$.  Why?  It's not that 2/3 is $0.66666667$, it's just that we can't precisely represent $2/3$ in decimal, and at the 10th digit, we just round to get as close as we can.

This is really a problem with any number that has a decimal place.  There are infinite numbers that we can't represent!

The computer has the same problem with decimal numbers as we do.  This isn't a fault of the computer, it's just a feature of floating point numbers, and the computer has to work around it, just like we do.

Now, we do have a way of increasing that precision: we can increase the number of digits allowed.  It doesn't solve the problem, exactly, but it does get us closer to the true numbers.

That's the difference between a float and a double.  A double allows more digits.  And that's why it's usually a better idea to use a double.


This question is for anyone who has read Introduction to Algorithms by MIT press 3rd edition - Exercises, how to make them easier?

While it isn't necessary to do every exercise in a book, it is important to be able to do every exercise in the book.

Similarly, while it isn't necessary to write every algorithm, it is necessary to be able to write every algorithm.

But learning is another issue. Reading alone isn't enough to learn something. I think you already understand that. You need practice with what you've read to make sure that you have a deep and long lasting understanding of the topic. So, as you've already discovered, you need to do a lot of well chosen exercises.

But even that isn't enough.

You need feedback on your attempts. You need someone to look at your work and tell you where you have done the right thing and where you need improvement.

Reinforcement and feedback are the key to learning.

I'm not sure where you will be able to find this feedback. That is the real value of taking courses - the feedback is built in. Unfortunately not every course gives enough feedback, of course. If it is just grades, it isn't enough. You need it pointed out where and why something didn't work so that you don't build bad habits. (Reinforcement without feedback can be counterproductive).

Perhaps there is a professor who would be willing to look at your work. Perhaps you have another more advanced student available. Some people create study groups to give feedback to each other. Even an online "buddy" who can evaluate what you've tried.

And note, also, that having the answers available isn't really sufficient feedback until you learn how to find the misconceptions that led you to the wrong answer. It is little misconceptions that can throw you off and someone giving good feedback can help you get the insight to avoid them.

Find someone.

As for making it easier, only reinforcement, feedback, and time will do that.


Python function has access to global variables, and doesn't need passed arguments

Your example demonstrates how to declare and use a function with a parameter, but not why they should do so.

Actually, there are no reason (for them) why they should bother with a new concept (function) instead of writing

name = input("Enter your name: ")
print("Hello " + name)

which can be done with the programming elements they already know. And is both shorter and simpler,

So, how to sell functions with parameters to beginners?

they avoid code duplication (the example should contain several calls)
they are called with different values (so parameters is the simplet way to transmit information)
they implement a decomposition of tasks into subtasks (the sooner they practice the procedural approach, the better)

Here is an example:

def draw_line(width, end, middle):
    line = end + middle*(width-2) + end;
    print(line)

def draw_rect(height, width):
   draw_line(width, "+", "-")
   for  line in range(height-2):
      draw_line(width, "|", " ")
   draw_line(width, "+", "-")

def draw_square(side):
    draw_rect(side, side)

def main(args):
    draw_square(3)
    draw_square(5)
    draw_square(7)

Actually, I use Processing with a group of students. Most of them total beginners. The first motivation for functions is decomposition.

After they draw a simple figure with a few predefined function calls, as fill() to select a fill color, rect() and ellipse(),  they are taught to split the work into user-defined functions

void draw() {
    draw_sky();
    draw_beach();
    draw_sunset();
}

and parameters are then used for similar parts occurring at different places

void draw_seabird(int x, int y) {
   ....
}


The APCS community maintains an active web site and mailing list. It has many users who ask and answer many questions.

Start here to learn more: https://apcommunity.collegeboard.org. Find your community from there. Note that the site has separate lists for APCSA and APCSP. You can join several of the communities.

You need to join (free) and then just ask for the experience of others with CS50.


Is learning C++ recommended for beginners?

I wouldn't fuss too much over whether a language is "hard" or "easy".  There are plenty of reasons to learn a language.  Learning for a career is a great reason!

Languages are usually organized around certain central ideas.  Haskell is a pure functional language, Eiffel is a pure Object Oriented language, and C is designed to reflect very closely what a processor does.  C++ is designed to be a cross between C and object oriented programming, so there are several different paradigms at work at the same time.  That can make it a little more difficult to learn because there are simply more concepts at play.  However, the early basics should be fairly easy in any language.

C++ does appear to be the most heavily used language in the gaming industry.  However, there are a few caveats:

What sort of games would you like to be involved with making?  Browser games rarely use C++.
Languages change, but concepts are long-lasting.  While learning, keep pushing yourself to learn new ideas, not just new procedures.  That way, you'll be better positioned to switch over to a different language if it turns out that the wonderful gaming job you land is actually in HTML5, or Python, or in some language that hasn't even been invented yet.


Any good resource for introducing kids to programming using Python's Turtle Graphics?

I have found that Python is not the best tool for teaching elementary and middle school students an intro to programming.  Turtle is nice, but you run out of things to do pretty quickly.  If you move on from Turtle to console based coding, many students find it less engaging.
Scratch and similar visual languages are much more engaging for younger learners.  You will be surprised how full featured they are.  There is a lot of great algorithmic teaching that you can do with these.
If you really want a traditional text-based language, you might check out Greenfoot (for Java).  But again, younger learners get lost in the symbols pretty quickly, so it would not be my first recommendation.  Scratch can be much more intuitive for them.


Breaking down the operations when auto-casting gets complex

I suspect that you handle such situations by informally building the parse tree of the expression in your mind. Maybe not all at once, but a bit at a time, perhaps. I'm not a cognition expert, of course, but it might help him if you teach him to do it explicitly on paper. He needs a table of operator precedence, of course and needs to be able to deal with parentheses, but otherwise it is just a mechanical process. Put the lowest precedence operator at the root of a tree and then work on the operands. The interior nodes are operators and the leaves are operands.

Can't promise it will work, but it would be my next step. With time, he may learn to rely less on the paper. Or, he might learn how to build a tool to do it automatically. That might be nice to have.


Use the for when you know how many times to execute it, such as counting, or iterating over an array. Use while or do .. while if you don't. The choice between while and do .. while is if you need to do the loop one time before the test use do ... while otherwise use while.

A full explanation can be found on Stack Overflow in this accepted answer.


Best Practices for introductory teaching

I think you have left out two essential elements here. Your first two points leave the students passive consumers. The last is about testing. But there is no guarantee of any learning in between.

In some ways, the two most important pedagogical ideas are

Active Student
Constant Feedback

You need to ask your students to create things and you need to give them individual feedback on how they did. The fraction of students who learn by listening to lecture is actually quite small. Taking notes (by hand) makes them more active, but using the face-to-face time to work with them in artifact creation is much-much better.

But students are unlikely to get everything right the first time and each student will need individual direction, whether they are struggling or excelling.

Note that teamwork is an attempt to combine these two things. The team creates something and give each other feedback as they go along.

My constant mantra while teaching was "It isn't important what I (the teacher) do. It is only important what you (the student) do."  Focus on their activities, not yours. Perfect their exercises, not your lectures.

I'm not sure how relevant this is to CS, but one of the most important and memorable courses I had in my first year of college was a writing course. The prof never talked about the process of writing, but pointed us to a lot of good writing. However, the crux of the course was that we wrote a theme for every class (3 per week). We spent quite a lot of the time in class reading these aloud and getting feedback. His particular trick was to pick out the best ones in his judgement for review, not the ones that needed the most work. We also got detailed feedback in writing. No lecture at all. Lots of activity, lots of feedback. He did his job.


How to retain technical information about new features?

"Memorizing" doesn't do much to help you retain information or build skills. In order to really remember it you have to move it from short term memory, where it is pretty volatile to long term memory. The trick for doing this is to practice it. The reason teachers give students lots of exercises is to help them with this process.

In order to learn anything, the brain needs to be physically changed, connecting neurons with synapses in a new way. This is only done with repetition and practice.

See The Art of Changing the Brain by James E Zull  for a run-down on the science behind it.

Do, if the course provides exercises do them all. If you have a book available that also has exercises on the material, do  those as well.


What are the tradeoffs of allowing students to submit test corrections?

Our district has a policy that any student that scores under a 70% must be allowed to retest. You take the retest score, average it with the original, and cap it at 70%.

Catch is that I teach all AP / Honors classes. Typically these aren't students that score a 60% and want to bring their grade up to passing. They're the kind of student that gets 88% and is unhappy they didn't score an A.

I go beyond that and let anyone who wants to do test corrections instead of a retest and they'll get half their points back. We have another AP teacher that does a square root curve if they turn in corrections.

To get credit they turn in a document with a screenshot of the question (tests are all in Canvas), explain why they picked the answer they did (sometimes "I guessed" is okay), what the right answer is, and most importantly why it's the right answer.

3 reasons why I do corrections.

1 - It lets me throw a few harder questions into a test. I start putting in AP style questions early in the year, which students may not be used to. As the year progresses more and more AP style questions get put in. If the longer questions go in, especially early in the year, the tests might be a little too difficult.

2 - I don't really care what they know Tuesday at 10:30. I care what they know when they leave my class at the end of the year. If they can come back after a test and prove they know the material, that's much better than just leaving it unknown.

3 - Everybody has a bad day. Maybe their dog died last night and they're not in a good mindset to take a test.

With all that though, I'd rather do retests. Still for half credit. The problem I'm facing with that is I'd essentially need at least one more full test for every unit. Otherwise they're retaking the same test. What I'd really like is to have enough questions banked that students could take a retest 2 or 3 times and I'd average everything together. But that would take hundreds of questions for each unit.


Use money.  Tell your students to image a country has bills that are in denominations of powers of 2:  1, 2, 4, 8, 16....  Now tell them this:  For a given number, count out that money with as few bills as possible.  You use a "greedy algorithm:"

Use the largest bill possible.
Repeat this until you have counted out the amount.

Questions to ask:

Did you ever use more than one bill from any denomination?

They should observe this is never necessary.

Now write a 1 for the largest bill.  If the next denomination down is not present, put a 0; otherwise, put a 1.  Repeat until you descend through the denominations.  You have the binary expansion of the integer you specified.

This is concrete and very easy for students to grasp.  This "greedy algorithm" works for any base: Use the largest bill you can can count out as many as you can at each stage.


A meaningful exercise that requires using a destructor

Create an object that creates a new file and writes in to it over several method invocations (not just one). Assure that the object has been deleted before continuing (Make the object go out of scope on the stack or delete a reference and let the reference go out of scope.) You need to assure that he file was closed. The destructor is the proper place to assure that this happens.

To verify that it works correctly, create a different object that reads from the file. If the first object didn't properly close the file this won't be possible.

In some, at least, operating systems you don't even need the second part. The file won't appear in the file system if it was never closed.

The reason for wanting the file written over several invocations of some method(s) is that, if it is just one, an explicit close would be natural in that method. The reason for wanting any references to go out of scope is to assure you that the first object has no effect on the second.

Edited for clarification.


What professional development events or conferences are out there for CS educators?

In UK England, there are CAS Computing At Schools events. They are regional events. They are focused on primary and secondary schools.

They are usually inspiring, but can be a bit simplistic if you have done programming for a job. The events I have been to I have ether chosen the groups that are teaching focused (as opposed to technical focused). Or in smaller events steered it towards teaching techniques. Each event has been multi-threaded (choose your thread), or small and adaptable.

You can sign-up to their e-mail mailing list, to be informed of events in your area.


"Franklin" Method for learning good programming?

I have thought it strange that we teach students to write programs before we teach them to read them.

A short time ago I read about some research about this. It stated that the problem is finding good programming works that is of a standard similar to the standard of great literary works. They may exist, but no one has compiled a collection.

They would have to be at least:

Free Software / Open Source.
Well written.
“Reading age” appropriate. (That is programming reading age)

I will try to remember where I read it, and report back.

Could be one of these:
 - Mind-storms — Seymour Papert (page < 116 (I am up to page 116) )
 - Hacking The Curriculum — Ian Living Stone & Shahneila Saeed (page <= 72)
 - Hello Word magazine issue 3
 - Somewhere else.

Sorry I can't find it. It is most likely in the 1st, then the 2nd etc. If I find it then I will update.


Actually, your tree explanation is fine, except that it is the low precedence operators closer to the root. In Java, the "." operator is the strongest/highest and the assignment operators are the lowest precedence. The arithmetic operators are all higher precedence (bind tighter) than the booleans, with && having higher precedence than ||

A semi-official list is here: http://operator-precedence.com/java

In fact many compilers will translate an expression (the entire program, in fact) into a tree structure either explicitly or implicitly.

But, "binding tightly" is pretty traditional for an explanation also. The scope of an operator is limited by the end of the expression or the occurrence of a lower precedence operator. Therefore the RHS of the OR in your example is the end of the expression, but the LHS of the AND is bounded by the OR operator.

In the tree explanation work from lower to higher. In the "binding tightly" work from the higher to the lower precedence operator.

Odd historical note: To a logician, AND is logical "multiplication" and OR is logical "addition", hence the typical relationship in programming languages.

However, Pascal took that idea a bit too far and OR had the same precedence as addition with AND having the same precedence as multiplication, requiring parentheses in many more expressions than you would like.

On the other hand, having to write things explicitly in a programming language is usually a good thing as it lessens the likelihood of an oversight error.


Curriculum Design for a Unit on Alan Turing and His Impact on CS

With only a few weeks, it's hard to cover much in depth, but you can skim the surface of a few topics.  I would focus the unit by talking about the problem of computability that Turing and Church (and others) were facing.  It's a nice problem, because it is easy to describe in broad strokes, and the implications border on the mystical.

I would then go on as a class to look at how Turing attempted to explore the problem.  I would start with creating Finite State Machines, and run a few class periods of this to help them get the hang of it.  I might mention, but not really explore, the idea of a grammar, and talk about the equivalence of FSMs with regular expressions.

Then I would skip PDAs and move right into Turing Machines.  Have them spend some time building them in class, and finally introduce the Busy Beaver problem with this video.  Be prepared to stop and talk a few times during it to help them keep up to speed. The payoff at the end is totally worth it.

I would finish up by describing the Halting Problem, and talk a bit about what the implications of an Oracle would be if it could somehow exist.

At the very end of the unit, I might mention that Turing created his solution using mutability as a core idea, but that there was another approach created by Church, Turing's mentor from Princeton, that used pure mathematical functions to accomplish the same thing.  The two of them proved that their systems were equally powerful in the Church-Turing Thesis.  And as funny as it sounds to have computation without mutability, there is an entire branch of programming languages devoted to exactly this approach called functional languages.

Obviously just mentioning this won't get them to understand functional languages, but it will set the stage for them later on in their undergrad CS years to appreciate why they are learning functional programming in the first place.


Techniques for encouraging pair programming

Having them do it for homework, and pair program is a big ask. However here is some of my experience with pair programming.

While working as part of a software team, we tried to introduce pair programming, but got lots of resistance, even from the evangelists (no one had done it before, but it seemed like a good idea).

What worked

Pairing with someone that had done it before: At one point we had a contractor that had done pair programming before, when I worked with him, I did pair programming. This experience showed me that it could work. The only people, that are available and have done it before are the year above. A good way to lean is to teach. Therefore pair students with someone from the year above. This way the student in the lower year learns to pair program, and the one in the upper year learns by helping. [You need some intensive to stop the upper year student doing too much work. There is also a bootstrap problem.]
We had read that it takes sometime before pair programming pays off (2 weeks of full time programming, if I remember correctly). We kept giving up on pair programming during this investment phase. However we did discover that if the task is sufficiently hard, then the pay off was immediate. These were problems where we both had enough language experience, the problem was well defined, but nether of us knew how to solve the problem. e.g. setting up the MMU on an ARM processor. One of us knew what they wanted it to do. The other knew what an MMU does, but nether had ever set one up before. Therefore once they have learnt to program, give them a task that would be very difficult to do on there own, and get them to pair it.
Non programming activities: for various design tasks (algorithms and higher level than code), we worked in pairs or small teams (2,3 sometimes as many as 5). This worked well for tasks that are hard. Therefore start pairing with non-programming tasks.


Buffy's answer is already spot-on, but here's another $0.02.

  We would take on any willing instructors with backgrounds in coding that would be able to use the students as a means of developing their personal projects, while simultaneously teaching them how to code. Everyone benefits.

I think you're vastly underestimating how much work it is to delegate tasks, to bundle those tasks up in a format that another person can approach, and to generally manage other people. It's also very difficult to deal with time management (or lack thereof), and to manage expectations (and decide what happens when expectations are not met).

You're asking instructors (who are already extremely busy) to work as program managers, for free, on projects staffed by people who are going to need a ton of hands-on help. There is a huge time cost here.

You've basically just described an internship, and generally both parties are paid for their time. If you aren't planning on paying the people involved, then I'm afraid you aren't going to see many volunteers.

Your heart sounds like it's in the right place though, so I'd recommend doing another round of brainstorming. The best advice I can give you is to start smaller.

For example, you might rethink your project to be something more like a way to connect students to open-source projects looking for help. This question has a bunch of resources you might want to check out.


Is stressing too much on formalism acceptable?

Moving from formal to informal is almost always a mistake.  Let me see if I can show you why.

When you consider how you think about sets within your own mind, I am reasonably certain that you rarely use the formal definition.  Instead, you visualize or otherwise imagine something more akin to some abstract sort of bag, box, or group.  The specifics of your visualizations are not so important here.  However, the internalization that you use must be, in some sense, physical.  Members can be in or out.  Things can be added in, or removed.  Your mental imagery may be only partially fleshed out, or it may be much more definite, with form, color, and texture.

This mental model gives you a strong set of intuitions regarding sets that allow you to work with them quickly, efficiently, and correctly, allowing you to move to formalisms only when you really need them, such as when you are attempting a proof, or when you are trying to enhance your understanding of some novel property that you hadn't understood before.

Why do you suppose that we always draw out our Turing Machines instead of writing out their formal definitions? (I searched online for a long time, and I honestly can't find a single example of a TM entirely written out.)  Similarly, why do we normally draw a geometric diagram instead of simply writing out the formula for a diagonal bisection of a square?

The answer is obviously that the concepts are far eaiser to understand when turned physical.  This property will hold true for basically every abstract concept we've mastered.  Our minds are wired towards the physical.  We can figure out a reasonable path in a crowd of moving people almost without effort, but take months (or even years!) of training to be able to reliably find the sum of multiple-digit numbers.

Taking this idea to an extreme, you could construct a fully formal, mathematical description of Chess.  Squares are sets, numbered from 1-64, and $Pawn_{i}$ where $1 \le i \le 8$ can always move to $Pawn_{i}loc + 8$ iff $current + 8 = \{ \} \land current < 57$. Similar descriptions can be made for every other legal class of moves, but by using such an approach, you would take a game that any 8 year old can learn, and you would make it inscrutable. The poor 8 year old would never be able to learn the mechanics of the game. (And mechanics is not a coincidental word here!)

Visualizations and strong analogies allow us to make concepts instantly clear.  As Buffy points out in his answer, mathematical work moves from concept to formalisms, almost never the other way. To do otherwise is to ignore the way that our minds learn.


I don't understand all the hate this question is getting. I'm guessing the answers depend on the context a lot.

Context of my answer

I regularly hold company trainings. Adult education. These are full day IT trainings, that means 9 AM to 5 PM. In the contract we offer 90 minute blocks with 15 minute breaks between and a 45 minute lunch break.

Importance of breaks

A break is not a waste of time. Researchers disagree on the amount of time an average human can uphold focused attention for, but all agree it is measured in minutes. I have learnt 4-5 minutes at the university, and I have read some researchers claiming it to be up to 20 minutes. But you can't expect an average human to uphold focused attention for hours at an end. It is possible to renew attention, this is where the teacher comes in by changing the rhythm, the tone, the visualization, the exercise. But from time to time, breaks are needed. (The 8 second attention span you hear about is different, it is the burst attention span or whatever it is called.)

It is not just the attention though, but moving/stretching as well. Most workplaces have recommendations, and though there are slight variations, most revolve around the "work for 60 minutes, get up and move for 15". This is not only beneficiary to the health of the individual, but also (many studies point this out) improves work performance.

Answer to the original question

My actual answer is: explain to them why breaks are important, explain to them how getting up, stretching, moving can help them concentrate, but don't try to force them to do so. If sitting is the new smoking, then dealing with it is similar: you can't just forcefully take the cigarette out of their hands. They know their own bodies and what type of break refills them. And they will learn the importance of breaks the hard way.


Resources for flowchart programming for young, new programmers?

Honestly, I would be surprised if this method bore the kind of fruit that you hope for.  While flowcharts seem like a nice way to make ideas more concrete, I contend that they will actually become another level of abstraction that makes the task harder for middle-school students, who are only now making the transition from concrete to abstract thinking.
You're moving from boxes that represent ideas (Scratch, already one layer of abstraction) to boxes that represent arbitrary groups of boxes (now two layers, with fuzzy bottom-layer boundaries designated in the bottom later), and then making macro-decisions using those larger boxes (two layers plus fuzzy boundaries plus a lot of flexible thinking).
In short, I don't think you're going to find a big coding speed-up, or even higher quality output, from the students.  In this regard, it's a trap.
However!  I'm not going to suggest that kids can't use flowcharts.  In fact, I'm not even going to suggest that it's not valuable.  Kids who are beginning to develop abstract thought need to practice that skill-set in order to develop a richer ability to grasp abstractions as an adult.  However, I think that to do it well, you would have to be okay with the idea that it probably won't particularly help the kids with the actual coding tasks themselves, and furthermore decide that it is still worthwhile for other reasons.
If you still wanted to proceed, I would take this backwards approach:

Have the kids code in Scratch first, which gets them started with as little abstraction as possible.
Next have them construct flowcharts of what they have done, including a one-sentence description, and a NAME in the box (getting a good NAME can be quite hard)
At this point, they would be better able to manipulate those boxes.  You can ask them to present their flowchart structures (and the accompanying programs, of course!) to the rest of the class.  You can also use the diagrams that they have created to help them if they get stuck (though they may have trouble applying the solutions for all of the reasons listed above).

If you want to help them work in the other direction, you can provide a flowchart that works well, and then have them implement it in Scratch.  That can provide support for the concrete -> abstract transition they're undergoing, and also help them learn to move in both directions (Scratch->flowchart, flowchart->Scratch).
I wouldn't ask them to work with poorly designed flowcharts (such as the ones that they themselves would make) from the start -- it's not clear to me that you'll get any sort of good result from an unsupported approach like this in a classroom setting.


What are good models for a Tutorial System for lagging CS students?

When I started my last job, there were many problems with the CS "tutors" at the CC and university I worked at:

Tutors actually didn't know the content that well themselves.
Tutors "explained" a lot, and used the sessions as hangout time with other buddies, or as a sort of show-off time.
Attendance at tutoring sessions was (unsurprisingly) low.

If no one knows the content, no one knows how to teach the content, and no one is welcoming to new students, what can you do?? I opted for a fairly time-intensive solution because it fit within my role, but others may benefit from at least parts of this model.

I started a Peer-Led Team Learning program, with training in

CS content
CS pedagogical techniques
supportive culture

PLTL Leaders didn't just hold tutoring hours. They also led weekly PLTL sessions where they helped students learn CS in a structured setting. This provided a way for students to meet the Leaders, and a context that ensured the students learned something and that the Leaders were trained. PLTL leaders also helped out in the classroom.

PLTL is a proven model with a handbook, a research tradition, and support. I had to make my own exercises for CS1 / CS2, but the model for how to run a PLTL program is already well-established---simply follow the handbook. PLTL emphasizes collaborative work (usually on paper), and Leaders prompt and direct students, but do not give away the answers.

Being a PLTL leader was advertised as a high-status position, a leader in both content knowledge and professionalism. I was inspired by Section Leader programs at many universities. PLTL Leaders were paid hourly. At the university, I was able to set up a system of interviews to hire new PLTL leaders--this gave another level of professionalism, and also gave students much needed practice in whiteboarding and interviewing, even if they didn't get the job.

Weekly trainings bootstrapped the tutors' content and pedagogical knowledge. We worked through the packet of problems for that week's PLTL session ahead of time as a group. This ensured that everyone knew the content, and also knew how to prompt students to solve the problems. We practiced pedagogical techniques like tracing code, drawing memory diagrams, and prompting students to collaborate. We typically spent 30 minutes talking about issues like making sure students didn't feel afraid of looking stupid or asking questions.

This model does require buy-in from instructors to motivate PLTL attendance. Some CS1/CS2 teachers made PLTL attendance mandatory, others offered extra credit. In an ideal world, the CS1 / CS2 teachers would write the PLTL materials and help run the program, but it fell on me in my setting.

Over time, student coordinators took over running the training sessions. Once problem sets were developed, they were re-used.

Starting this program was one of the highlights of my job. I'm happy to say that these students did become a strong part of the department's culture over the 2.5 years I ran the program, raising the bar for what professors thought their students could be capable of. Many of those students now have great jobs in industry. I miss 'em :')


What should be included in a best practices C course?

I think an important aspect to any best-practices list is the rationale behind it.  It is entirely too common for a programmer to, for example, insist that gotos and global variables are evil and then proceed to use exceptions and singletons to create the exact same problems that got those features proscribed in the first place.

So I suggest that when introducing a rule of thumb, you don't just give examples of code that follows the rule, but rather examples of the sort of awful code that led to the rule being created.  Let them understand why the rule exists both so they can avoid making similar mistakes and also recognize when the rule isn't applicable. (Of course, no examples will be as helpful as allowing them to write terrible code and then try to modify it, but you have limited time.)

A related recommendation that is somewhat tangential to the best practices lecture, but related to the question of how to help them complete the course successfully:
Don't assume that the more abstract explanations of topics are necessarily easier to understand than the ones that get into the gritty details.

I've had a number of students who were completely confused when we tried to explain pointers using diagrams of boxes and arrows, but as soon as I sketched out a table of memory (with addresses as indices), explained that a pointer is just an integer that is used to "index memory", and then walked through a block of code, updating the table as I went, they understood it almost immediately.  (We put the abstractions back in place when it was time to work with higher level data structures, after they understood the fundamentals.)


How to overcome the TDD/BDD time fallacy

I believe that the reason why students tend to come out opposed to using TDD/BDD (testing) is because they've been assigned to use it when it isn't necessary. Testing a "Hello World" program is 100% a waste of time. Tests only become useful when you have a reasonably complex program. The way that you can avoid students disliking testing is by not assigning it on projects when it isn't needed.

A specific way in which you could do this would be by combining all the project you would assign over the year into one larger cumulative project. Eventually, as they're writing code, you can be fairly certain that they'll induce bugs or begin to find manual testing to be a pain. Once that starts happening, you can introduce automated testing to relieve that pain. That way, they'll see testing as a way to save work rather than create more of it.

In addition, I think the issue may be with this part:

  TDD and BDD have high upfront setup costs in ... thinking up test cases for all the various scenarios.

If you are spending time thinking of test scenarios, you're doing TDD wrong. You should never just take time to think of test cases. You should think about how you want each new piece of code to behave, and then testing should be a way of writing down how you want it to behave. That's just good planning, and you should be thinking about that anyways.


Helping students adjust to using industrial-strength IDEs

IDEs are tools that are designed to solve specific problems.

They're great for stuff like:

Compiling multiple projects that contain a bunch of classes.
Dealing with dependencies on multiple libraries.
Handling stuff related to coding, like starting up servers.
Packaging and deploying your application.

If the students haven't encountered these problems, then honestly they probably aren't ready to use an advanced IDE. They don't have a need for it, and they should probably stick with whatever works for them.

Another consideration is that students need to understand what's going on "behind the scenes" before jumping into using an IDE. At a bare minimum, they need to understand:

Basic command line interaction: How do you navigate over directories? How do you run programs?
System Path: How does your computer know how to locate Java? How can you change this?
Compiling and Running code: How do you compile a .java file via the command line? How do you run a .class file? What is the difference?
Classpath: How do you use a library from your code, from the command line?
Errors: What is the difference between a compiler error and a runtime error? How do you read a stack trace?
Documentation: How do you consult the docs to figure out what functions a class has?

I say they need to understand this, because too often I see students who don't understand what the difference between path and classpath is, or who don't know what the red squiggly lines in their IDE are telling them, or who rely on auto-complete and copy-paste for everything.

All of that being said, I think you should start with a very basic text editor and the command line. Spend some time there and make sure they understand the basics. Then as their projects get more complicated, they'll naturally see the benefits of using an IDE.

Present the IDE as a solution to the problems that they're already experiencing.

"Who here is sick of specifying the classpath argument whenever they compile their code?"
"Does anybody wish it was easy to see what functions a class has without needing to do read through the docs?"
"Now that we know how to export our application via the command line, let's see a quicker way to do that."
"Now that we've learned how to debug using a piece of paper and a pencil, let's see a way to do that automatically."

Then introduce the IDE and point out specific ways to solve their specific problems. Throwing them in the interface and saying "here are 100 different things this can do" is going to be overwhelming. Build on what they already know, and solve the problems they're already experiencing with a more basic editor.

This makes sure that they understand what's going on behind the scenes, which helps demystify the process. It also gives them a good reason to use an IDE, by framing it as a tool that helps make their lives easier, which is what it should be.


Event-driven or polling for beginning programming environments?

On the face of it, event-driven programming seems far easier to explain. "This code will run when the button is clicked" seems obvious, and similarly, visual environments that favour this technique seem relatively intuitive:

It would seem obvious to explain that the code below that block runs when the sprite is clicked.

Similarly, in Node.js, an event-driven programming language:

app.get('/', function (req, res) {
  res.send('Hello World!')
})

With some basic knowledge of the framework used (Express), you can tell that when the / route is accessed, Hello World! will be sent.

So, without looking too deeply, event-driven programming is the obvious choice. But, this isn't the end of the story. If you're not used to event-driven programming, the fact that your code might not run in the order you expect is very confusing.

fs.readFile('foo', 'utf8', function (err,data) {
    console.log(data);
});
console.log('Hello!')

Two things will print here: the contents of foo and the word 'Hello!'—but which prints first? The answer is: you can't tell, despite the intuition that many students have that would suggest the order is file then 'Hello!'.

Event-driven programming starts to encounter a lot of these 'gotchas' because it's difficult to predict in which order things will happen. Ideally, each event wouldn't need to consider any other event happening, but in practice it is necessary.

Let's say you wanted to end the game if your spaceship was touching two others at once. With events, you could need to subscribe to 'Touching [spaceship1]?' and 'Touching [spaceship2]?' and synchronise them (not terribly straightforward). But polling like so would be far easier—for each update loop, just test if(touching(spaceship1) && touching(spaceship2)).

Getting to your original question, I would personally introduce event-driven programming first, since it's so straightforward for trivial use-cases. As the problems start to appear with events, then introducing polling in an update loop would be wise. Most of the major introductory programming environments seem to follow that (Scratch -> Greenfoot, etc). The same principle should apply to your own environment, I think—consider your audience and what they'll be using your own environment for, and you'll have an answer that suits you.

You might also find Polling vs event driven input on Game Development Stack Exchange interesting for reference on the problems faced by professional game designers regarding events vs polling.

The only alternative, perhaps, would be to batch events from inputs so that they can be handled in the next update loop—that's something to consider if you're looking for another way of handling the issue, but it is more complex than the others.


What is a good analogy for pass by value vs by reference?

Since I was tired of the easy IT examples which all revolved around sharing files and documents, I started using the following analogies to explain pass by value and by reference.

My cat ("Mr Doorknob") sometimes wanders off to my neighbour. They call him "Cirmi", but of course he is still the same cat. If they feed him, he comes home fat and satisfied, if their dog licks him, he comes home covered in saliva.
This is a bit like passing a variable by reference: they might give him a different name, but it is the same cat. Whatever is done to the passed cat in the neighbour's garden will be visible on the cat when he finally comes home. (I actually like this because it helps them understand the "different name thing".)

As for passing by value, my neighbours really liked my new sunshade. They asked me where I got it from, and they bought one themselves. It looked identical in the beginning, but theirs got pooped on by a bird. This, obviously, didn't affect mine, it is still as shiny and clean as it was.

Many things can be used as analogy for pass by reference: renting books from a library, and seeing the marks in it someone else made; lending some item to a friend, etc.
I find it harder to come up with real life examples for passing by value, but one example is photo copying course notes, or artists (or forgers) copying famous paintings.

So, lending someone my course notes VS letting them make a copy of my course notes, then see them pour coffee over the notes while they are learning from it - in case one, my originals are ruined, in case two, my originals are safe. (Instead of pouring coffee, we can have them add improvements/comments to the notes, to make it positive instead of negative).


I don't think you're going to find a good data set that contains what you're looking for.

The reason is, teaching and learning are very subjective. I don't think there's any one definition of what makes a "good" explanation. An explanation that I think is helpful might not be very useful for you, and vice-versa.

For example, maybe one person just wants to get something working and doesn't care about what it's doing behind the scenes. For them, a simple "copy this line of code" would be most useful. Compare that to somebody else who is much more interested in the background of why things work. For them, a more in-depth analysis including history and lower-level details would be more useful.

  I can use a crowdwork service such as Amazon MTurk to generate ratings

I don't think you can. The only way you can do this is by having people read the descriptions and then rate them: but based on what? How easy they were to read? How much detail they went into? Whether the person learned something?

Comparing curricula is a bit of an apples and oranges comparison. What would you compare? Student grades?

You might be able to get something vaguely similar to what you're describing if you use Stack Overflow's data. Stack Overflow releases all of its question and answer data, and you can query that. Start here or google "Stack Overflow data" for a ton of results. Maybe take all of the answers to every question tagged with for-loop and compare them based on how many votes they got?

But in the end, learning is subjective, so you aren't going to find an objective data set.


Students frequently distracted by peers and games

There are a variety of measures, or counter-measures, that you can employ. Some are technology-based, some come at a financial cost, some require the right level of cultural and institutional authority to implement.

The least expensive, and tech-free alternative is to set rules with consequences. When the instructor is lecturing the students are expected to be listening. Listening is done with the mouth closed and the ears open and eyes on the instructor, not the "game". During "lab" time on-topic discussion is acceptable while discussion of current events (current pairings, etc.) is not considered on-topic.

If the students are expected to use paper for notes, rather than the computers, during the lectures, you can also require that they remain powered down until the "lab" portion of the class begins. Once they are working on the computer, the rules can say "No Games" and that can be explained to include both the Windows per-installed games, and online games of any variety.

Still non-tech, and possibly within a limited budget is the installation of mirrors. One or two strategically placed bubble mirrors can allow you to "see" the monitors even when you are on the other side of the row from them. Granted, the image in the mirror won't allow you to read their screens, or probably even know what program they have open. Even with the limited quality of view they offer you should be able to distinguish between an IDE and a video game, or a music video, etc. Even the difference between a web page being used for research and a chat/IM window is probably distinguishable that way. The version that hangs on a chain should be install able in almost any classroom, and without much effort from maintenance, possibly even on your own.

If the room's shape and the outlet distribution allows it, you can consider the tables mentioned in another answer. Even the pre-computer versions of the half-hex tables can accommodate a trio of flat-panel monitors if you can have the CPUs on the floor. There is the trade-off of loosing writing space for the keyboard, but if they take paper notes during lectures, with the computers remaining off, the keyboard can be moved out of the way.

The cost for the tables depends on what's currently collecting dust in the warehouse and what is purchased new.

Adding technology to the mix, there are other measures that can be pursued. First off is the uninstallation of all the games that are bundled with Windows. There seems to be no real reason to have them on computers that students are supposed to be using for schoolwork. It might cost the IT Dept. some time, but it won't cost them anything else.

Depending on the school's policies, it's also possible to restrict the sites that are reachable from the school's network. This shouldn't require any new software for the system, just the configuring of what's already there. Most of the popular games for your students are likely to be from a highly limited set of domains, domains which server no other purpose. Blocking traffic to those few IP addresses can be handled by even a simple home router, whatever is in use at your school ought to be capable of the same. If your school is setup with each room on its own VLAN then they could configure your lab's network to block those sites while allowing them for the rest of the school, and for the WiFi access from student devices. I don't think there's a legitimate need for access to such sites from the school's network at all, but the school policy might not allow a global blocking of such sites.

The most expensive, and probably the most complicated to maintain, is to install some form of "parental control" software on each student computer. (Removing, or disabling, unwanted software at the same time can't hurt, or course.) I have no recommendations for which one to use as I've never bothered with any of them. It's likely that the cost and licensing of them will have a larger impact on choice than features in any case. Institutional bureaucracies tend to move in that direction, even when it means getting something that does half of the task only half as well as something else would.

Still, no matter which measures, at whatever costs and technology level, are used, they only make sense when used to enforce an existing rule. If there is no rule against playing games during lab time, blocking game sites is not appropriate. That realization just returns the subject back to the top of the list.

With the understanding that there are some rules to follow, which are explained to the students in the beginning, you can still attempt to keep things "light" for their first real exposure to CS. If the class is for programming, you can work towards developing a game as part of the progression of the class. Obviously it will be a simple game compared to what they like to play. Being part of the team that makes it, however, can add the excitement lacking from the game itself. I suspect that even today's kids know what tic-tac-toe is, and its rules. Making a quick version of that early in the course can cover a lot of the language basics without needing major investment into complex libraries and programming. If developed early enough in the course, it ought to fuel their fire for making a "better" game during the remainder of the course.

Whether the end is a game, or something else, the sooner you get the students where they have "made" something which does something and they can see the results of their work, the better your chance is of getting them engaged and invested in the material. I believe that is one reason web design classes do so well - the view-able web page, no matter how "basic," is so easy and fast to create that there's nearly instant engagement of the students.

One final suggestion, to encourage them to see computers as a "game" of its own, a game where the computer is made to imitate what people can do, while giving them a bit of computer history as well, you can show the movie The Imitation Game about Alan Turing and breaking the German Enigma machine's code.


What do I do if my computing teacher does not teach the subject properly?

All of that is in the key-stage 3 syllabus (it is not all programming). However it may be that the teacher is over focused on one bit.
What is in the new computing syllabus
The new computing syllabus (post ICT), consists of three parts: Computer science, IT, and digital literacy. The timetabling people often make up name, so not wise to get to hung up about it.
You can download the syllabuses, here are some resources:

https://www.computingatschool.org.uk/data/uploads/ComputingCurric.pdf
https://www.computingatschool.org.uk/data/uploads/cas_secondary.pdf
https://www.computingatschool.org.uk/data/quick_start_secondary/progression_path.pdf

Where does copyright fit in
Within digital literacy there is a small section on, aspects of the law and ethics: copyright, patent, trademark, computer misuse, privacy, plagiarism sharing is caring, free software, etc; internet safety; evaluating resources (e.g. Wikipedia articles).
Copyright is a small part of the syllabus. Here is where copyright is mentioned (indirectly):
“They need to be aware of their legal and ethical responsibilities” — page 15 of https://www.computingatschool.org.uk/data/uploads/cas_secondary.pdf and “Explains and justifies how the use of technology impacts on society, from the perspective of social, economical, political, legal, ethical and moral issues” — last column grey section of https://www.computingatschool.org.uk/data/quick_start_secondary/progression_path.pdf
What to do next
Check to see if you teacher is only teaching part of the syllabus, then consider helping by sharing some of the resources below.
There are also a lot of teaching resources, here are a few.

https://csunplugged.org/en/
https://helloworld.raspberrypi.org/


Statistics on functional programming in CS1

While it's not complete and almost certainly not the reference mentioned in the paper, Philip Guo compiled a list of programming languages used in introductory courses at top 40 departments (as ranked by US&WN). The key result is this table:

which shows that the only functional language, Scheme, is used in roughly 12% of departments.

There are two problems I see with using this as a statement about CS education at-large: first, this is a sample of the top 40 research institutes, which may not be representative in terms of teaching habits.

Second, Guo (by his own admission) is counting both CS0 and CS1 courses in here. For example, he counts CS303E at UT Austin as an intro Python course, although it's intended as a half-semester language intro for non-majors. This may skew the appearance of certain languages in his data.

Finally, a note: in the comments section of that article is a statement that says

  What we need is someone to resurrect the more comprehensive annual survey that I believe Jean E. Sammet used to do up to a few decades ago...

I wasn't able to find any record of this survey, but if "a few" means just one or two, then that might be the source you're looking for.


App Lab/JS confusion between strings and variables

As always with javascript, show the right&wrong:

Show them, using the exact piece of code from your example, but add another line:

var greeting = "Hello ";
var first_name = prompt("What's your first name?");
var last_name = prompt("What's your last name?");

var reply = greeting+" "+last_name+", "+first_name;
console.log("reply");
console.log(reply);

And run it.

Then they see that when they log something with " ", the output is literally what's inside the quotes.

However, if they have a variable (this is important to note that reply is defined with var), the output is the contents of the variable. Truth be told, the output is the string representation of the object, but I fear that's too advanced at this point.

Further explaining that when they use the word var (or const etc.), you create a something that holds information. On the other hand, using quotes "", you are simply representing that information.

But no matter how well you explain it, it's still far more effective to show examples like the one above, and to give the students exercises that will allow them to experience the point you try to teach.

For example, let them try to do that with a Date object:

As an exercise, teach them about Date in JS:

var d = new Date()

and then explain that d holds info about the date and time that the line was executed.

Once the students understand the very basics of the date object, ask them to print it. The difference between

console.log(d)

and

console.log("d")

are very, very big.