What would be a good analogy for IP addresses and ports?

I used seats in the room.

The classroom has an address. So, if someone wanted to come and talk to one of the students they would come down the hall and into my room.

But, that only gets them to the room (server). They need to talk to a specific person, so they go to seat 17 so they can talk to Bob.

So Bob's socket is room.123:17.

I tried once to continue and the floor became cable runs, each hallway was a subnet, the corners were routers, and the school map was DNS. That pushed it a little too far :)

Did find though that most kids had at least a passing understanding of ports. Most of them had opened ports on their home routers to play games over the internet.


Good, Motivating Examples for Algorithmic Complexity

I attack this problem with three "visits" over the course of two years with my students

At our first brush with Complexity, I don't spend a ton of time motivating the study of it.  I introduce the notations of $\Omega$, $\Theta$, and $O$ (as well as briefly touching upon $\omega$, $\theta$, and $o$).  I show the difference between linear and binary search, and then explore four sorting algorithms: bubble, selection, insertion, and bogosort.  (This is fairly early on in the curriculum, and we haven't dealt with recursion yet, so I skip out on quicksort and mergesort.)  The last one makes them laugh, and makes the material at least have a point: some algorithms are just worse than others.
Later in the year, we look at quicksort and mergesort.  At this point, again, we use this only as a chance to review the concepts and the notation.
Near the beginning of the second year, I talk about why algorithmic study matters.  Computers get insanely faster over time, right?  (See Richard's answer for some eyebrow-raising numbers).  Since our computers are getting faster, it only stands to reason that things that are slow to compute today will also just get faster.

"Au contraire!" I cry, "as our computers get faster, our algorithms are getting slower, you see!"  What do I mean by this outrageous claim?  As our computers get faster, our hard drives also get bigger.  By necessity, we perform calculations with larger and larger data sets.

So, let's use high-end rendering as an example.  In 1980, Apple came out with the Apple III computer, which shipped with a whopping 5 megabytes of diskspace.  It also used the 6502B processor.  It could perform about 0.43 million instructions per second (MIPS).  Today, hard drives come in at about 6 gigabytes, and 305 billion instructions per second.  My numbers don't have to be exact to make this work, though.

If we processed a complex graphic that took about .5% of our hard drive using a $O(n^3)$ algorithm in 1980, that would be about 2,500 bytes of data, and it would take us roughly 9.25 years to complete.  That's awful!!  But if we did that today, (roughly 30 megabytes and 305 billion computations per second), it would take us over 28 thousand years to complete.  We're trending the wrong way!  The problem is that, even at a relatively cheap function like $O(n^3)$, the growth due to data creep is just far faster than Moore's Law.  Faster computers can't deal with correspondingly bigger problems if the $O$ sucks.
Finally, a few weeks later, I talk in grand, futuristic terms about the Big Picture.  This is more to excite their curiosity than anything else. The three drivers of possibility with computers are, I argue, smaller transistors, better battery life, and better algorithms.  If you take a $O(n^3)$ algorithm and find a way to accomplish a similar task in $n^2$ time, that's a foundational enabler.  You don't become individually famous, but you change the world.  The Google Maps team didn't solve the Traveling Salesman problem, they developed algorithms that could get likely best answers without the guarantee.  The bottom line is that developing algorithms with better complexity literally enables us to do new things on practical timescales.  To paraphrase Heroes, change the algorithm, change the world.


The advantages of using VCS from a content-creation point of view are already written about in depth, so I'm providing only arguments for why this is advantageous to you - regardless of how well they utilise it for their own workflow.

Lost work

If all students are committing their work to a repository you have access to, you will never need to worry about somebody losing their USB and with it - their entire coursework. If the work is stored in the repository, you always have something that can be salvaged for a hand-in, even at the last minute.

Reduced Plagiarism

When marking a single hand-in, you potentially have no history to work from. You are seeing the cleaned up, finished product and hoping that they came to those conclusions themselves. If on the other hand you have their work, as they make it, you can more easily identify "odd" commits where the quality of code has changed dramatically - it is much harder for a student to plagiarise, and much less likely that they will try.

Reduced Last Minute Sprints

As with the reduction in plagiarism, by having continuous check-ins of their work - you are encouraging them to work on their code throughout the term. Avoiding a last-minute sprint to get the hand-in ready is ideal, and not only will this help encourage them not to do that, it gives you a tool to check they are not getting into that situation before it's too late.

Debugging

When a student approaches you with "code that doesn't work", it can be hard to identify exactly what the cause is. Even if the problem that needs solved is clear - it can be hard to see how they got themselves into that mess. With VCS you now have a tool to check back, ask for their last working commit, and see what they changed/ask them why. It may be clearer why some bad choices were made based on what they already had.

As an aside: using VCS such as git does not mean the students need to know the VCS inside out. A simple cheat-sheet of how to commit, branch and pull is all they really need; anything else can be done with your individual help when needed. Teaching proper use of a VCS is not necessarily required to get a lot of its initial benefits.


Using Processing as an entry point in an Introductory Course

I am currently designing an intro to programming course for middle school students using Processing. In particular, I am using these two resources to focus the curriculum:

Make's Getting Started with Processing: A Hands-On Introduction to Making Interactive Graphics

Raspberry Pi Foundation's "Introduction to Processing" Resource

Make's resource moves all the way from simple, one-line programs like ellipse(50, 50, 80, 80); to OOP, file IO, JSON, data visualization, etc.

To supplement these resources, I am using videos from Daniel Shiffman's YouTube channel The Coding Train. Of particular value are his short coding challenges where he completes a programming task in the allotted time while talking through the design process.

I find that Processing's power comes from its scale combined with its ease of entry. I can confidently say that students will be writing "real" code on day zero and getting instant results on something other than the command line. Plus, there's the satisfaction of starting to learn programming with a text-based language instead of something like Scratch which can feel restricting and elementary to some students. And, as Daniel Shiffman's videos show, there's really no stopping how far you can go with it.


What belongs in a low-math undergraduate AI elective besides ML?

I took both the AI and (basic) ML undergrad courses at Princeton and currently teach an AI elective at the HS level for some very bright students. I've seen some good online material from Berkeley (CS188) and MIT (6.034), and of course Stanford's ML lecture series is amazing. Russell & Norvig's textbook is basically the bible for these sorts of courses.

From what I've seen, AI undergraduate courses have changed a lot in the past decade to focus on ML, since much of the recent breakthroughs and publicity are in those areas. AI is a very broad and historically rich field beyond just Data Analysis or ML. I would say a comprehensive AI course would start from Alan Turing's classic (and often misused) Turing Test and ground itself in an ongoing definition of rationality as effective problem-solving.

From there, there are lot of "classical" AI fields that are very approachable without any calculus; most of their discrete algorithms are intuitive, and you can wave your hands and say the continuous (calculus-involving) counterparts are basically the same idea. Here's my shortlist of essential first topics:

Goal-based state-space searching algorithms (e.g. DFS, BFS, Greedy, A*). These are a great start since the notion of searching is very universal and lays the groundwork for the next two:
Adversarial Game-playing AI (minimax and alpha-beta pruning)
Constraint-Satisfaction Problems (ARC-3, backtracking search) and/or Boolean SAT (DPLL, WalkSAT).

These three areas form my HS curriculum, and provide really rich applications and philosophical fodder ("is this how rational humans think? Is it intrinsically better, or worse, or completely unrelated?")

Some courses might go from these topics into Bayes Nets and/or Hidden Markov Models, though I think this leans math heavy since its all about probability.

Usually by this point AI courses have become more or less completely focused on ML, often starting with k-means clustering, basic classification/regression using perceptrons or decision trees, ensemble learning/boosting, reinforcement learning (usually in the framework of Markov Decision Processes), and maybe deeper neural networks.

EDIT: A follow-up; my course has now changed its third unit topic from CSPs/SAT to Markov Decision Processes (Value Iteration and Policy Iteration) and Reinforcement Learning. Its more exciting, leads into ML, and flows out the Adversarial Games nicely because of the shared concept of finding a "policy", especially if Expectimax is covered.


How should the paradigm shift associated with functional programming be approached?

Any true paradigm shift requires literally re-wiring the brain. Thinking functionally is not the same as thinking procedurally (for example). The neural pathways of the brain need to be connected appropriately for the new paradigm to become natural. When you were a kid you were, if typical, used to walking and running. Then you probably got a bicycle (or a skateboard if you are young enough). You tried, you fell down, you tried again. Your brain got used to the subtle balancing required. Swimming - same deal. Differentiation - same deal. Haskell - same deal.

As an instructor, the above implies that you should provide guided practice at the beginning - a skateboard park for the mind. If your students solve a lot of simple problems (not syntactical, but logical) they will skin their knees on these but if they are well chosen will get the skills. In scheme, reversing a list with only head and tail is simple enough. Doing it in linear time takes a bit more skill, but the technique is both cool and satisfying. Writing the code wires the brain. And, like riding a bicycle, it is hard to un-learn it once you get it, since the brain is now different.

So, make it possible for the students to fall a lot, but to get up without getting discouraged.

To add a bit of specificity to this. Assuming you know the paradigm well yourself, what are its 100 most important techniques? Can you come up with a 10-30 minute exercise for each of them? Try to have each exercise focus on just one thing (mostly anyway). These are your Etudes. Can you come up with 10 exercises for each of the 100 techniques, even if they vary only slightly?

Acknowledgement: At SIGCSE 2004, Owen Astrachan (of Duke) convinced Microsoft Research, through Jane Prey, to give every attendee the book The Art of Changing the Brain by James E Zull.


Use of programming aptitude test in CS program admission

This is a great idea. We should definitely help people determine in advance what fields they are likely to succeed in. It would be far better for them, the economy and the employers to admit only people who are likely to be good candidates for schooling and employment.

The work training program that I have been employed to teach -- training adults with physical disabilities for entry-level programming jobs -- has just be discontinued partly due to the recent US Workplace Innovation and Opportunity Act (WIOA) requirement that job training programs result in a recognized industry credential leading to employment or advancement in a job. (We could not find a credential that was reachable with around a year of training.) As far as I know, this job training program was unique in the US, and it used to be quite successful, when it was possible to get a programming job with a few months experience in COBOL. This is no longer true, and we were short on incoming candidates and not having much luck placing them either.

We have now decided to offer training leading to the Microsoft Office Specialist (MOS) certification instead, which is faster and much more likely to get people in to jobs, and we can serve far more people a year that way.

I am just a little curious though, as to why someone didn't see this coming long ago -- the calls for prequalification for education and for screening of employment candidates -- back when the US Supreme Court passed that decision in 19711, making it illegal for employers to use screening tests that "could be biased"? (The decision that led to employers simply requiring a college degree instead, which has been implicated as a cause of the mushrooming demand for and cost of college and university education.)

Many experts in the field of computing are calling for Apprenticeship programs. Any takers? We could again try using the method humanity has relied on for thousands of years to produce experts, masters and professionals.

1: http://northcarolinahistory.org/encyclopedia/griggs-v-duke-power/


Best way to install and maintain windows 10 in a computer lab

I have experience managing a lab for student-use. We utilized Deep Freeze. I was not responsible for configuring it, but based on what you say you would like to have in terms of OS management, I believe it would check those boxes. We could set specific times for booting up and shutting down. Additionally, we could restore a non-corrupt image each day if something happened. It allowed extensive control and security. I'd encourage you to look into it. I also don't know the cost, so I can't speak to what you'd be paying per device. However, it worked incredibly well across campus.


Is it worthwhile to teach assembly nowadays?

I think so, yes. However, I also believe teaching assembly isn't valuable because it could hypothetically teach students how to write "faster programs" -- compilers these days are smart enough that most of the time, you're just better off using a systems language and relying on the compiler if you're interested in that.

Rather, I believe the value in teaching assembly (and systems in general) is it gives the students a much deeper understanding of how computers work, which is highly valuable if they want to move on to other subfields of computer science.

For example, suppose a student is interested in exploring security. If they want to learn how things like buffer overflows work, what ASLR is, be able to understand the latest innovations in kernel research, how whatever the vulnerability-of-the-day works (right now, it seems to be Spectre and Meltdown), it's essential they have a good understanding of how exactly their computer, the hardware, the OS ticks.

Teaching assembly (and more importantly, things like calling conventions, the stack vs the heap, and so forth) is a pretty decent stepping stone to help prepare students travel down this path. Of course, I'm not claiming teaching assembly is the only way, but it's certainly a well-trodden and popular route.

We can do the same kind of analysis for other fields -- systems knowledge is potentially valuable for people interested in compilers/PL research, in software validation and correctness analysis research, for people who want to build on top of new tools like Webassembly, for people who are interested in writing hardware accelerated code (using GPUs, FPGAs, SIMD instructions, etc)...

Of course, not everybody is going to be interested in these fields, and even if they are, that doesn't necessarily mean that assembly is going to be directly useful or relevant to them.

But I don't think that's any excuse not to teach the material -- the goal of teaching, I believe, is to prepare students to be successful in a wide variety of different fields, whether that's industry, research, or something else. And if that means sometimes teaching them material that they won't directly need for the foreseeable future, I think that's fine. It's better to be over-prepared then under-prepared, yeah?

tl;dr: having systems knowledge is useful. And if you're going to teach systems, I would imagine that you're basically obligated to teach at least some assembly.


My teacher said that java is pass-by-reference when the type is not a primitive

I've encountered experienced C and C++ developers who are convinced that Java is pass-by-reference for objects. One example I've used is this one:

void changeInt(int x){
  x = 42;
}

void changeString(String x){
  x = "hello world";
}

void testChanges(){
  int i = 0;
  changeInt(i);
  System.out.println(i); // still 0

  String s = "test";
  changeString(s);
  System.out.println(s); //still test
}

The changeInt() function fails to change the value of the parameter, because it's pass-by-value. But then the changeString() function also fails to change the value of the parameter- because it's also pass-by-value.

I also really like Cup Size -- a story about variables and its follow-up Pass-by-Value Please to explain the difference between pass-by-value and pass-by-reference from a Java perspective.

Now, as for whether you actually bring this up to your teacher, I'm not sure. If I were you I'd probably just bite my tongue and move on with my life.


Mnemonics to remember the TCP header fields

The first bit is where it is going. An intermediary needs this to forward it. It goes first so that at least in theory it can start forwarding before it has finished receiving. Next is the symmetrical data (where it is from). This is common to most protocols (ethernet mac-addresses, IP addresses, tcp/udp ports, …).
Next the two sequence numbers, in the same order as before: to (the sequence number of this segment), from (the sequence number of the last segment that I got from you).
Next the length of what remains, you need the length before you can start reading the rest (there is no other way to know where the the end is.
Then various flags, the window size and the rest.
Of this I only remember the first two (the two addresses). The rest I look up.


What are some good examples of using a stack data structure?

I once had to implement a limited undo function (undo changes to the current field, or addition/deletion of records).

The lists of undo deltas (one for field changes and one for records) were stored as stacks.


Objects Lab Before Inheritance and Polymorphism

Inheritance and Polymorphism are basically the motivators for Objects in the first place

I think this is where you're getting stuck. Neither of those are necessarily first-class motivators for Objects, but they are useful things you can do when you have objects.

Work-in-progress textbook chapter on OOP (aimed at students aged 16-18) and why we use it: https://en.wikibooks.org/wiki/A-level_Computing/AQA/Paper_1/Fundamentals_of_programming/Object-oriented_programming

Some alternatives:

"Object = Code + Data"

It's easy to show examples where global functions cause problems because they accidentally trample on each other's data (they're using the same data, but making assumptions about it)
...especially easy/fun to show how two unrelated functions can accidentally choose the same name for their variables (they're using different data, but happen to have chosen same name, e.g. "x" for x-co-ordinate, but also "x" for number-of-items-to-multiply)
Via encapsulation (and optionally: hiding) objects wipe-out many of these common, painful, frustrating bugs that beginner programmers often discover themselves when using global functions

"Object = aggregation of functions"

How do you organize your source code when you have more than a few dozen functions? Objects help enormously

"Object = classification of data" (Object as ADT)

How do you organize your data when you have three different meanings of "x-coordinate": Position, Velocity, and Acceleration? Objects make it easy to create ad-hoc, named, data-types that massively simplify this problem
i.e. Objects-as-Abstract-Datatype


What are good sample programs for learning to use a debugger?

A few Java specific examples come to mind:

Using % with a negative number - I recently came across this and had to remember how Java treats modulus v. remainder (cf. this thread)
Listing switch statements without the proper break; at the end of each case - maybe something that can be seen right away, but stepping through each line would be good to visualize this process
Integer division is also a classic - using the conventional Celcius-to-Fahrenheit (or vice versa) conversion program with the formula broken down over several lines would force them to see line by line what is happening when you evaluate 9/5 or 5/9
Operations with increment/decrement operators in prefix and/or postfix position throughout a program - I like this one a lot because of how variables may change without that change always being seen

I'll edit and add ideas as more occur to me.


How to adapt pair programming to a shared terminal environment like Cloud9?

I tend to avoid multiple students working on the same code simultaneously (Google Docs style) because it's really difficult to assess what has been done by each student or to stop one student dominating whilst the other doesn't understand what's happening. Either that or students tend to get distracted by what the other is writing.

Having said that, you could try:

One person writes code whilst the other writes comments. This forces the two to discuss both what they're doing and what they're planning to do next.

Other paired programming techniques that don't involve simultaneous access:

Allocating a 'driver' and a 'navigator' to each pair of students: the navigator isn't allowed to touch the mouse of keyboard. The driver has to follow the navigator's instructions. Students swap after a set time.
Sabotage and share: get students to make deliberate syntax / runtime / logical errors in their code then share a link to their code in a shared document / forum. Get students to record each error they find and fix. Award points per bug fixed.


Scheme vs Haskell for introducing functional programming

I suspect there'll be more universities switching from Scheme to Haskell for introductory functional programming (FP) courses, mainly for the 'real world' appeal of Haskell. I see 15 mentions of Scheme and 16 of Haskell in the recent SIGCSE programming language poll results, although Scheme (as Racket) still has the edge in introductory courses.

We've a little FP in one of our A-level (secondary school leaving exam) CS courses in the UK, and Haskell seems the popular choice; indeed I'm not aware of any schools using Scheme for this. I know of one school that's been using Haskell with six year olds(!). In the US at school level, Scheme (as WeScheme) features in Bootstrap World, but they're using Pyret for some courses now.

There are some good Haskell texts around, e.g. Hutton's Programming in Haskell, and Lipovaca's Learn You a Haskell for Great Good! (free online version), but these are introductions to the language rather than introductions to functional programming - it still seems hard to beat SICP, which is Scheme based. What text are you using at present?

Interestingly, this critique of SICP from 1987 identifies four issues with Scheme, all of which are addressed in Haskell:

Pattern-matching.
A syntax close to traditional mathematical notation.
A static type discipline and user-defined types.
Lazy evaluation.


What qualities should be considered when designing a front end project?

As a student I would find this assignment uninteresting and a waste of my skills. I would feel the professor is just trying to be lazy and not having to properly grade assignments.

If they really should know HTML and CSS by now, don't treat them like babies. Just ask them to build a complex responsive page that works as their resume and/or portfolio. They will be glad to make something beautiful and actually interested in your assignment. You can of course set minimum requirements like having transitions and animations, media queries, etc.

My point is: don't create an assignment to try to make your students fail a few points off your check list, but create one that will make all your students interested and proud of their creation.


This is difficult to answer in general. I have personally used a lot of different solutions depending on the course. For low level courses it may make less difference, but maybe not. I still have many of the text books from fifty years ago that I considered important to my development, and have consulted them.

There are courses in which there are truly classic books: The Dragon Book for compilers, for example, which is dated but still valuable. It would seem a mistake to me to try to teach a class in Scheme without at least one of the two classic books. But there are other courses in which there simply are no textbooks, the material being too recent or in flux.

One reason for not using your own materials exclusively is that your students get to see a view other than your own. That seems to me to be a good thing in itself. Some of your students might use the exercises or worked examples in a textbook for review and exam preparation.

If you intend that your materials won't be valuable to them after they leave your course then informal materials are fine, in my view, but if you want them to have a resource that they can use later then make sure that it is one that will stand the test of time.

I also used extensive materials of my own, but mostly as a supplement to more formal materials. Like you, I seldom referred to the formal text, but it was available to them whenever I was not, including after the end of the course. Think about your student's future, not just their present.

It might be enough, in some courses, to provide an annotated bibliography including, especially, classic works. But if your students aspire to be professionals in the field (academics or not) then they should build up a library starting in their early years. I'm guessing that you have done that yourself, as I have.

There are, of course, situations in which the cost of modern textbooks can't be ignored. Providing low cost or free resources may be essential in these situations.


Are There Exercises To Build Software Development Research Skills?

This article contains advanced google options to refine searches, you could make them into exercises for a work training simulation using Jupyter Notebooks such as "Search for stackoverflow intext: ag-grid AND module.ts", or exercises to walk git branches to become more familiar with the project.

You could also teach them to create a personal database of questions they've already asked, and how to search it, just so they aren't asking senior developers the same question twice.


How can I determine if a student would enjoy or has an aptitude for CS?

You shouldn't "test" somebody to check whether they're interested in something. You should give them some stuff you think they might enjoy, and you let them decide for themselves.

There are a ton of programming languages designed for novices, including:

Processing. This is my personal favorite. Shameless self-promotion: I've written a series of tutorials for people exactly like your nephew, available at HappyCoding.io.
Scratch. This is geared towards younger kids, but might be a good "game-like" introduction.
Game Maker. If your nephew is interested in game development, this might be worth checking out. I suggest not limiting him to game dev though.

See also:

What would be a good first choice to teach game programming to beginners?
Using Processing as an entry point in an Introductory Course
Order to Teach Topics in an Intro Programming Class


Array or vector? Two dimensional array or matrix?

First, see this question on being pedantic. Second, consider the fact that you are teaching Computer Science and not Mathematics. The former is not a subset of the latter. There is some overlap, of course.

Next, I see no issue with being precise about terminology when students might be studying both fields. If you want to clearly distinguish between vector and array, I think that is fine, though you may possibly just be stressing the wrong thing.

Vectors in mathematics are used to understand things. (That is the core of pure math, after all). Arrays, call them what you will, in CS are used to build things that are useful.

But lots of things vary between math and CS. Addition of integers means one thing in math. The fact that it normally means modulo addition (with a fairly large modulus) is seldom stressed initially and is irrelevant for many (not all) purposes. Likewise real values mean quite different things in math and in CS. If you spend too much time on the details of the differences you may not have time for what are, fundamentally, more important issues in novices learning CS.

But, the reason that Matrix isn't a fundamental type in a language like Java is that it isn't needed often enough in the work of professionals to make it part of the infrastructure. You can, of course, build a Matrix class and provide the mathematical operations that might be wanted for some applications, just as Mathematica has done.

But, mathematics is like CS language structure in a lot of ways. In math the Peano axioms are, for example, enough to define the structure of the natural numbers. Other things can be defined and built on top of that structure. Likewise in Java, a Vector of Objects is a (somewhat) simple bit of infrastructure that can be used as the basis of more complicated and useful things. So, in both, one has a simple basis that can be extended for the purpose at hand.

I'll note also, that few general purpose programming languages have anything like a matrix as a primitive. Normally a two dimensional structure is more like an array of arrays (vector of vectors) and so in the second dimension the index limits can vary. But OO languages can, of course, control that and have "true" matrices, though a "row" and a "column" in such a structure are quite different in the implementation. But, again, in mathematics the row and the column are ideas, and in CS they are implementations (built things).

Well... I suppose that any Turing Complete language is "general purpose" in some sense.


Incorporating algorithmic complexity in grading

I wouldn't want to penalize kids who are really relatively inexperienced for not coming up with the fastest solutions on a test. Even if they're in 11th grade and have a couple of years under their belts, they likely haven't been in real situations where run time is important.

If I were to want a specific run time on a test I'd say something like "for full credit make sure your solution runs in $O(blah)$ time."

If I give an open ended solutions and I don't specify any restrictions on run time, storage limitations, or data set size I tell the kids that I won't penalize them for efficiency unless it's so grossly horrible. For example, if they were to write a sort in their code (and I wouldn't really ask this but it makes for an easy example), I wouldn't penalize a kid for coding an $N^2$ sort even if we covered $n log(n)$ unless I talk about a large data set size. On the other hand if they sorted by say an $N^3$ solution or worse, they would lose some points.

In any event, if you're requiring certain run times you have to be careful that you're not just getting kids to memorize and spit back what the teacher expects.

Also remember that there are plenty of times where a simpler, slower algorithm is both clearer and more than sufficient and that complex fast code that doesn't work isn't nearly as good as simple code that does.

To encourage creativity, give multi level assignments. Create lessons where you can have them develop a solution, see that it's too slow, and then refine it. I do that with finding the mode of a data set (https://cestlaz.github.io/posts/2014-11-17-hidden-complexity.html).

You can also create assignments that encourage this and make test data sets and situations that force kids to work on time efficiency issues.


How to illustrate scope problem when creating variables inside `if` statements in Java

I like to use an analogy from Finding Nemo.  I tell them their programming language has the same problem Dory has - short-term memory loss.  When a variable is declared within a block, Java will forget about the variable (just like Dory) after reaching the end of the the block.  So a block declares the "scope" of Dory's short term memory.

I've been concerned that students would think that the variables assigned in a block would lose their value after the block has ended, but I've never run into that problem for some reason.

What's interesting about your example is that it won't even compile without the print statement!  Java doesn't allow you to have a single declaration statement in an if or loop.


Rubber Duck Debugging.

A few years ago we bought a bunch of cheap rubber ducks. Students with questions have two options. They can either ask their neighbor or explain to the duck what they're trying to do. If the duck didn't help, then they can ask me.

I've moved to a different school since then and haven't bought any ducks. I really need to buy some ducks.


Book recommendations for rigorous CS books

The Art of Computer Programming in four volumes by Knuth is an obvious choice.

The first chapter of the first volume is a pretty solid course in discrete mathematics all by itself. If you can do all of the problems in that chapter you can earn a PhD in CS. (Some of the problems remain unsolved, I think - at least they were when the book was first published.)

Knuth is a Mathematician turned Computer Scientist and gives the mathematician's view of the field about as well as anyone can. You can depend on the accuracy of the book as the author has induced the community to drive out all inaccuracies using bounties.


Is it worth to learn to make a MD5-hash cracker?

I have used a similar idea - writing an SHA-1 hash cracker - as a mini-project for students learning Java. These students had previously learned to program in other languages, so they had experience with variables, if/else, loops and functions; the main goal was to get them used to Java's syntax, but some of the specific things they had to do were:

Import and use a library method (DigestUtils.sha1 from the Apache Commons library).
Write a for loop over a range of characters instead of a range of integers.
Use nested for loops to generate every combination of characters, of a fixed length.
Use recursion to generate every combination, where the password length is a parameter.
Estimate how long it would take to crack a password of a particular length by brute force.
Read from a text file with one word on each line.
Test their code.

Your question implies you are thinking of writing your own implementation of the hash function itself. I think that's probably less worthwhile, since you'll just be directly translating from the hash function's specification into code, or from an implementation in one programming language to another. You would be practicing your skills in reading and making sense of specifications or code, and you might learn some things about bitwise operators; but the design of a hash function is arbitrary and opaque to almost everybody, and there would not be much real "problem solving" required.

I think for a learner-programmer, there is more to gain from using a library for the actual hash function, and writing the rest of the cracking program yourself - i.e. the part which generates the candidate passwords to feed into the hash function. For example, the next mini-project I got those students to do involved generating all combinations of playing cards to work out probabilities of winning in a simple card game; this is not entirely unlike generating combinations of characters for a password, and some students did notice the similarity.


Framework choice for AP CS A students: Swing or JavaFX?

Disclaimer: some do consider this a war like emacs/vim. I don't.
I'll quote you on this: "I'm looking for something that allows students to get up and running relatively quickly and easily with something small yet meaningful".
From this: JavaFX. Along with IntelliJ, and Scene Builder, students can build a GUI very, very quickly. The FXML file which "creates" the GUI also gives an introduction to XML file structure.
It also teaches many Java 8 things. This is vague, but here are some examples:

A lot of lambda expressions.
Work with Collection. The students would need to use the collections in java 8, if they learn JavaFX. This is handy, because those classes are obviously useful outside of AP CS A
The Stream API (which gets buffed in Java 9, coming out soon) has a lot of usage as well in JavaFX.

I could continue this rant forever, but the main point is that JavaFX is self-dependent, which means that it only requires itself and java, unlike Swing, which requires AWT.
I hope this give you some idea about putting a GUI library in your curriculum.

As was pointed out in a comment, JavaFX has an added bonus: It's more likely to become the library your students would use, if their careers lead them to doing GUI in Java. I say this because Oracle said so:

6. Is JavaFX replacing Swing as the new client UI library for Java SE?
Yes.

The link contains more details, but the core of that part of the faq is that it is a replacement. (Which is in no way saying that Swing will not be included in future Java releases, because of backwards compatibility).


What screencasting tools can be used for online teaching

Fingers crossed that this one doesn't get closed. I've tried to do something similar, but it hasn't come out well. Hoping that some others have suggestions.

It looks like they're using some sort of overlay or whiteboarding software, and I assume a tablet or stylus. I can see a cursor where their pen is drawing.

I've tried this, and it didn't go well. But, I think that's more a factor of my handwriting than of the idea. Enough years of typing being my main method of written communication has made my handwriting terrible. And it's even worse on a Wacom tablet. Same thing with some student created videos. They're just hard to read.

I'd like to find whiteboard software that also allows typing. Haven't found one yet, although I haven't looked all that much either.

A couple things that have worked...

If I'm in a hurry, Powerpoint has enough animations built in that it's possible to do a fairly decent job. And, they can be exported to videos if you want to upload to YouTube.

When I've had more time I've used Flash. It's deprecated now, but I still have an old copy on my computer. Takes longer, but gives me a little more freedom in what I build. Also can be exported to a video, which is especially important since browsers are starting to frown on Flash.

Edit:

Just played around with the pro version of Acrobat and it looks like it has a pen and text tool that might work for what I'm trying to do. Most of the time I'm just trying to annotate what's already typed out.

Edit 2 - After "screen casting" was added

This year I started capturing my screen as we work through problems and then uploading to YouTube for kids that missed the day or just want to go back for a refresher. I'm using a program called OBS. Works really well. A little Googling brought me to a Windows program called ZoomIt that will let me write and type over the screen as I'm demoing. Think I might bring my Wacom tablet to class tomorrow and give it a try.


Execution time is unreliable due to variations in hardware and, especially, operating systems. Paging and multi-level cache can make such things worthless. That is why theoretical measures are used.
The actual execution time depends on the specific implementation of the algorithm, not its structure. Implemented poorly in Java it will run slower than if implemented well in C (and conversely). Paged operating systems, such as Unix and its variants (and others) put an extra load on algorithms at scale. Multi level cache can speed things up but vary between processors.
Efficiency of an algorithm is a theoretical concept and so is measured theoretically, perhaps by counting comparisons. This might mean something if you compare two algorithms on the same hardware, but may even be misleading if the implementation causes, for example, page thrashing.
In addition, most modern OSs are multiprogrammed and a given program has little control over whether it has complete control over the processor while it executes, or even over a single thread.
But most operating systems will have a way to give you the actual running time of the execution of a program. A few thousand executions will give you an accurate picture for that algorithm on that set of inputs, but might vary widely if you double the inputs.
See the Linux date command for example. You can integrate it into a shell script that executes a program a few thousand times and get some averages.


Assignments for Introductory Level Processing

I did a 4 half day "camp" for two high school girls a couple summers ago. We spent the first two days doing Processing programs. Etch-A-Sketch and Tron are a couple good assignments for beginners. The Etch-A-Sketch simulation leads nicely into making a game based on the light cycle scene in the movie Tron.

Here is some information about what we did in the camp


What to teach in an Advanced Computer Networking course?

I created an Advanced Computer Networking course offered at Master's level which follows an earlier undergraduate course in networking (which I also created and teach).
I'll offer some insights, suggestions and thoughts, but they will just be off-the-cuff rather than a formal curriculum plan (I've done enough of those).
The first thing to start is to not assume that the students have fully absorbed and are usefully fluent on everything in Tanenbaum! Start with revision, focusing on those parts of the material that would be essential to grasp to move on to the advanced material. Do not revise by just going through it again, but do it through asking questions and raising problems so they can determine if they understand the material well enough. In particular I brought out routing at the network layer as being critical, as well as multiplexing at the transport layer, as well as the whole 7 layer model again.
I then focused on larger issues that students may not have encountered when administering their own machine. Things that happen at ISP level and internet backbone level, such as BGP, AS numbering and the protocols and databases involved.
A lot can also be done with security, such as the law and ethics. What is a network administrator permitted  to do and when does managing a network exceed the authority allowed (such as entrapment). I looked at honeypots for example, as well as logging.
In a more advanced course I also put more emphasis on self-learning. Things such as monitoring media for incident reports; making presentations on security incidents over the last 12 months, for example.
In terms of network management SNMP and tools that use it can be covered in more detail, including network discovery, network mapping and so on. As practical work I get them to program an SNMP tool to learn about the object encoding mechanisms and also about packet capture.
I have more ideas, but this might get you started.


Using online courses instead of / in addition to traditional lecturing

What you have described is about half of what is known as a flipped classroom. This concept has been explored in other questions here and at the Academia forum. The idea is that instead of lecturing, face to face time is filled with activities that can only be done face to face and the students are given "assignments" to read or explore video and other online information outside of class.

What would normally be practice and experience on the student's own time (standard classroom) is now done during the class periods where you get a chance to observe them. You also get a chance to permit group work and sharing, but in an environment in which you can see that any rules are adhered to.

The flipped classroom is very handy in the beginning CS courses where students need to get a lot of practice, but also get stopped when they get to questions that they can't answer and then wait for a chance to have them answered.

But your face time needs to be more (much more) than just you answering questions. That is only serving one or a few students at a time. You need to design activities in which they can all benefit. Group work in a flipped classroom is also useful as many of the questions that arise in the course of an activity can be answered by the students themselves and their team mate(s) and so don't need to come to you.

Many instructors flip the classroom for the entire course, never lecturing in the traditional sense, but you can also apply it to specific topics. The upside of doing it just a bit is that you get practice with it yourself, but the downside is that the students will be awkward with it initially and won't likely do enough outside class periods.

On an orthogonal track, online courses are a mixed-value resource. For certain kinds of learners (like yourself) they can be valuable. For others, they don't work at all. The typical drop-out figures for online courses are appalling. I don't think that is primarily due to the quality of the material but rather to a mismatch with learning styles of the students. I don't have research on that, however, but would love to see it. One problem with video is that a student can't ask a question in the middle of it. If they miss a point, they can replay, but can't really get a clarification. I also question whether students are able, in such courses, to get appropriate practice and (more important) feedback on their practice.

But combining an online "course" with good practice-and-feedback can be a plus, provided that you design it properly, taking account of the different needs of different students.

Here us another question on Flipped Classroom. A simple search for "flipped" at Academia will turn up a wealth of information.


Is it a good idea to have students see syntax much earlier than they write it themselves?

Boldly Go...

First, I'll just say yes, it is a good idea to introduce things (let students see them) before they have to deal with them in detail. There is actually a Pedagogical Pattern, See Before Hear, that suggests that it is a good idea to let students see things before you even lecture on them. This isn't true about just syntax. The essence of the Spiral pedagogical pattern is that you teach things repeatedly to different levels of detail over a course and a curriculum. I'm pretty sure you would think it foolish if the first time the students hear the word "compiler" is when they need to build one.

Research

But to address the question of "Research" is a different issue. I think the kind of thing you might mean by research would likely be unethical. Educators, like doctors, have a "do no harm" directive. You can't run an experiment in education in which you even suspect that some technique might be worse than another, but apply the two techniques to two groups. You run the risk of doing harm to one group. You can only apply techniques that you believe to be best practice.

The only kind of experiment that would be valid is to poll teachers on their practice and then either (a) ask them how their students do or (b) somehow measure their students actual performance. The first is just opinion based and the second is very difficult to arrange, partly because it can be disruptive to the educational process. Another reason why such research is usually not repeatable (hence basically invalid) is that there are too many variables in education: between teachers, students, environments, etc.

An alternative: Patterns

Patterns, are a kind of "experiment" in that they are a means to capture the practices of experts, vetted through a process (the patterns process) by other experts. The process is quite involved requiring many re-writes to have a pattern accepted. This is true of all patterns of course (design patterns, org patterns, etc.), not just pedagogical patterns. The pattern not only includes the what should be done but the why this is the right thing to do (resolution of forces).

Another pedagogical pattern that pushes your syntax idea to the max is the Fixer Upper pattern in which you give students a fairly large program that (a) has good structure overall, but (b) you have broken in some well determined ways. The student task is to repair the program. This can be a first day exercise, in fact. The students first look at any syntax is a complete program that they need to work through.

One of the reasons that this sort of thing "works" is that (a) much of what you want to teach them they may already know or will pick up instantly, but (b) which particular things that is differs for each person. Letting students see an organic whole lets each of them draw on his/her strengths in understanding it, leaving you only the task of filling in the holes as needed. Each person needs to learn different things from the class; not all the same thing.

Another reason that the opposite thing does not work is that everyone learns differently. If you make the assumption that people learn by seeing or hearing something and then immediately "knowing" it you are treating the brain like a disk drive. I doesn't work that way. The brain works by reinforcement. So, if your teaching style is to teach everything only once and completely, then you guarantee that you will reach only a tiny fraction of your students, and many of those don't need the instruction anyway.


Should one study programming by doing hard problem?

It is probably a mistake to always do one or the other. If you are learning a hard task (becoming a competent programmer), it isn't helpful if you mix in another hard task as well (hard problems). Initially, it is good to write programs for problems that you already understand well, so that you can focus on the creation. A program has both form and content. If you work on very hard problems exclusively, it is possible that you will wind up just hacking a solution together without any elegance.

But if you never solve hard problems it won't become clear to you why advanced programming structures and paradigms are needed.

My advice would be to start out your programming education with fairly easy problems - that you can get your mind around easily. But mix in a harder problem or two as you go. Then when you become more proficient with the forms, move to harder problems and occasional very hard ones.

You are stretching your brain in two dimensions here. Eventually you want it to be very flexible. But you can stretch more in one dimension than the other at a time. If your problems are so difficult that you get frustrated then you may not make much progress on any dimension.

And, of course, problems that seem hard to a novice programmer, may not seem very hard to a pro. You learn a lot of tricks-of-the-trade as you go along.

Also the problem that you mentioned doesn't result in a very big program. It is a bit tricky, of course, but very small as programs go. You want to reach a place where you can intelligently create very large programs.


How do I deal with students being unkind to each other when I'm not there?

I have a couple thoughts of how I'd handle it:

Address it with the bad actors 1-on-1, but don't assume bad faith. We might not know the whole story and there might have been a good reason to walk away from a situation or it is possible that the bad actor has poor social skills. Give them the benefit of the doubt, but explain why that kind of behavior creates a hostile environment that is not good for education.
Discuss in class what makes for a good working/learning environment. Not necessarily directly mentioning the situation, you can still emphasize a need for students to take agency in being part of a nurturing environment. I haven't had the exact same circumstances, but I have found it helpful by acknowledging that most jobs require interpersonal skills and that I've known even talented developers who have been passed up for good jobs because no one wanted to put up with their attitudes. In that same notion, I tell my software engineering students that I expect them to behave like professionals and like the class is a part-time job. That includes treating others with respect, even if they don't consider each other friends.

If you find it is a continuing problem, you might consider working into your assessment plan some way (even as a small percentage of the overall grade) to evaluate individuals' professionalism in-and-out of the classroom.


Since there are two slightly different questions here

one in the topic

  What student exercises force them to modify and extend their own thinking process and methods?

and one in the detail section

  In the context of extending their thinking and problem solving skills, what particular problems and exercises would you suggest to use at the novice level for teaching computer science?

I am going to give an answer about exercises that focus on problem solving skills. The odd thing when I was building this list is how much it reminded me of those aptitude test they give you in grade school.

When it comes to problem solving one first has to be aware that there is no one way to solving problems that always works and there may not always be an answer to a problem or there may be an answer but getting the answer is not practical.

Algorithms commonly used
Depth First Search
Breath First Search
Divide and Conquer
Inferencing - Analogy: Connecting the dots

and also thinking in orthogonality of dimension/field.

For one of the simplest exercises of using depth first search is the game Unium which is to simply draw a line connecting a set of selected squares. This basically has only one dimension, a line and one method, depth first search. The puzzles get harder and harder, but you basically start drawing the line, see a problem, back up to where the problem occurred and then choose a different option and keep going and repeating until you complete the object and onto the next image to cover. This teaches that for some problems you can go back to a decision and change it to get the correct solution.

For breath first search the game checkers works as you can't make your next move until your opponent has made theirs and so can't resort to DFS. OK I know it really is a min-max game but BFS still applies. This teaches one that you have to look at all options available before moving.

For divide and conquer you will needs something that has simple rules and allows you to move off a sub-problem if it is to hard but still allows you to solve the problem. For this MineSweeper is a good game. This teaches that if you get stuck on something hard try some place else and you can still get the answer; in other words some paths to the solution are easier than others.

For something a little harder try A Good Snowman Is Hard To Build as this requires at least one good a-ha moments to build a snowman. The rules are simple but is uses three dimensions. When I did this with my small class it seemed most of the students had the same a-ha when building a certain snow man because the way to the solution seemed illogical, but until one learned to do the illogical they were stuck. I won't say what lead to the a-ha moment but I suspect that if you play the game you too will be saying a-ha at one point.

So far the way of thinking has been procedural but to add some functional thinking take a look at the Great Permutator as this adds functions, e.g. partition using every other, accumulate, dup, swap among others. I like this one also because you can try out different combinations of the function parts before solving the whole problem.

For a game that adds the dimension of concurrency take a look at SpaceChem. While this doesn't look like programming if you know how to program with locks and fork-join you will see the patterns and the best part is that it is visual. If my teacher had used this when teaching OS design it would have been a lot easier.

Getting back to procedural and adding in variables and the Jump instruction take a look at Human Resource Machine. One of the better parts of this is that it has challenges for the least number of steps and the least number of instructions. The answers to these challenges are not intuitive but get you to realize that machines don't have to work like we think to get a better solution.

For more advanced procedural/functional and back to the essence of what a microprocessor/ALU does check out Silicon Zeroes. This one also covers the idea of parameters and state.

To get out of the algorithm type problems have fun with the Crazy Machine Elements collection. This will make you think and sometimes you can even find solutions that don't use all of the parts. What is nice about these problems is that some of the elements affect others in nonintuitive ways like reversing gravity. This teaches that you can't always have orthogonality of dimension.

When you start playing with the dimension of time things really get interesting but finding a game that is simple but alters just time is not so easy to find, but The Misadventures of P.B. Winterbottom seems to do the trick. This game reminds me of a single person composing a song by recording a melody, playing the melody back and adding on another melody and so on. Get one melody wrong and you have to start over. This is interesting in that it teaches one that time is also a critical dimension for solving some problems.

Speaking of playing with different concepts what about having cooperating concepts? That brings us to Portal and Portal 2. I only wish they took the idea of cooperating concepts further and used other fields such as time, color, etc, and also have them competing some how. This is really interesting because it bring lots of a-ha moments if you don't look for the answers online.

The Turing Test changes out different dimensions/fields for solving the problems in different rooms but makes them harder as you go so that you are continuously being challenged. This helps to teach you that different properties of certain things can be used for other than their primary use, e.g. a block has weight but it can also block a beam.

For more of a real world problem but still simple enough for learning an essential concept common with neural networks being classification would be Papers Please. I have not yet played this one, but if it doesn't live up to what other say I will strike it from the answer.

Another game I have yet to check out but seems to deal with graphs which are essential to so many data structures in computer science is Mini Metro.

For the concept of composition I have on my list Infinifactory; again one I have not personally vetted.

So as you can see to learn how to problem solve start with simple methods and limited dimensions and keep adding on slowly with fun using games and one can learn a lot about problems solving.

In the real world when there are known to be exact solutions to a problem I tend to find that brining in combinatorics helps to solve the problem and one puzzle that quickly jumps to mind here is a Rubik's Cube. If you know the basic moves and how to apply them you can even find God's Number which will teach you a lot of good math and computer programming algorithms.

For more look at puzzle and logic problem books as they have lots of exercises. I did one of these books decades ago using Prolog before it had constraint satisfaction and after seeing how constraint satisfaction worked with Prolog find it to be one of my favorite languages for problem solving when dealing with closed world assumptions.

So by now for problem solving with computers you can see the need for algorithms (methods) and data structures (dimensions/fields) which is why the book Introduction to Algorithms is so popular.

If you have reached this far then check out the book "How to Solve It" by G. Polya. While it is useful to both students and teacher, it is limited in that it was written with math in mind.

If you are learning programming and reading this, I can not stress enough how much you should learn other paradigms of programming, e.g. procedural, functional, logic, and other concepts like matrices in MatLab, neural networks and learn as much math as you can.

One last point that AFAIK seem to be the only one I know who uses this rule when faced with a problem I can't solve. Most advise is to back off, break the problem apart and tackle a simpler part. However at times I find that finding a harder problem and reading about it then makes my problem easier and more enjoyable. So go regularly read about quantum mechanics and theoretical physics, etc., and you hopefully you will see that your problem is not that hard.

I can spend much more time on this question but hopefully I have given you enough to get started and shown you the path to expanding on how to build out ones problem solving toolbox.


Abreviation of practical work assignment?

Yes, lab is frequently used as a term to denote a medium size assignment. Exercise would be used for a shorter one, and project for something more extensive.

But the terminology isn't standardized so you can use your own terms, as long as the reader understands them.

But I'll also note, that just as in programming it isn't the typing that makes writing hard, so, IMO, abbreviations have limited utility and are often counterproductive. Written work is normally, and appropriately, a bit more formal than conversational work. This is due to the fact that the audience is wider and you don't know as much about it. So clarity over brevity should probably be valued.