How to help students avoid being distracted by bells and whistles

This is a very common problem. Students tend to focus on the stuff they can see, which can be to your benefit (visual programs are more engaging than command line applications), but like you've discovered, it can also be very distracting.

I think a lot of the problem can be prevented by adding a disclaimer at the top of assignments. Something like this:

  Please note that I am not grading you based on what your program looks like. It can be tempting to obsess over the look and feel, but try to resist that urge! Graphic design is an important field, but this course focuses on [insert focus here]. If you want to explore topics like graphics and design, please do so only after you've finished the main assignment. You also might want to check out [insert graphics course here] after you finish this course.

You might also include guidelines on what's "in scope" for an assignment and what's outside the scope. Something like this:

  Although this assignment includes visual elements, please note that I'm only grading you on your core logic, not what it looks like.

  The following are in scope for this assignment:

  Changes to server-side files.
  Showing the correct components on the client side.
  Getting input from the client to the server.

  The following are not in scope:

  The look and feel of the client side.
  CSS changes.
  Layout or style changes.

  If you're interested in exploring the out-of-scope topics, make sure you do so after completing the in-scope topics.

Or maybe something as simple as this:

  Make sure the basic functionality works before working on the look and feel of your program! Remember: it's better to have an ugly program that works correctly than it is to have a beautiful program that doesn't work.

You might also explain the concept of minimum viable products. It might also be useful to mention feature creep and bike shedding.

A lot of this just comes down to communicating your expectations.


None of the reasons you suggest really get to the heart of why we use zero-indexing in CS. Dijkstra's EWD831 explains why this convention works out the best. It comes down to the fact that we want to represent sequences of integers as half-open intervals that are inclusive on the start side.

  To denote the subsequence of natural numbers 2, 3, ..., 12 without the pernicious three dots, four conventions are open to us
  a) 2 ≤ i < 13
  b) 1 < i ≤ 12
  c) 2 ≤ i ≤ 12
  d) 1 < i < 13

To paraphrase Dijkstra:

(a) and (b) have the advantage that subtracting the bounds gives you the length, which is convenient because you don't need to remember to add or subtract 1.
(a) and (c) have the advantage that sequences starting with zero don't need a negative lower bound -- and negatives are no longer natural numbers.
(a) and (d) have the advantage that if you create an interval that starts with zero and shrink it down to zero-length, you don't need a negative for the upper bound.

Because of the above, we want to write all of our intervals as (a).

Once you accept that (a) is the correct way of specifying intervals, indexing an array of length N as [0, N) is much nicer than [1, N+1).

Two additional notes in favor of using (a) for intervals.

The first point above is important because half-open intervals nicely decompose into other half-open intervals. This makes implementing divide-and-conquer algorithms like merge sort significantly less error prone.

For example:

[4, 14) can be broken into the equal-sized intervals [4, 9) and [9, 14), and the middle index is computed as $9 = \frac{4 + 14}{2}$. This is quite clean and nice.
[4, 13], decomposes into [4, 8] and [9, 13], where you get the end of one sequence as $8 = \frac{4 + 13 + 1}{2} - 1$, and the beginning of the next sequence as $9 = \frac{4 + 13 + 1}{2}$. It's easy to forget to add or subtract 1 somewhere.

It's also a bit jarring to specify intervals with (b), because it feels unnatural to skip the first element when you're writing a loop.

As for how to explain the above to your students, I think that they just need to accept that breaking sequences of integers in half is something they'll do later on, and then a few examples will quickly point to [,) intervals and zero indexing as the most natural choice.


You can get at this concept very intuitively in strings before you ever get to arrays.  Take a string like "hello world" and ask them a subtle-sounding point: does the string begin here: "*hello world", or here: "h*ello world".  They'll certainly be able to identify the correct answer.

Then ask, "how far from the start of the string do we have to go to get to the 'h'?  Answer in a number of characters. Do we have to move 5 characters away? 3? 1?"  Again, they should be able to identify 0.

Now, it's time for the big reveal.  (My description here is in Java)

"When I want to get at that first character, h, I do it with myString.charAt(0).  Given what we just discussed, why do you think I would use 0, and not 1?"

At this point, they will naturally move to the idea that it is at the beginning, and that we have moved no steps from the beginning.

"Excellent.  This is an example of an index value.  And, in Java, when we do index values, we don't count from '1', we actually count the DISTANCE from the start.  So, if we want the first character, we move no distance.  And how far do we move to get the 3rd character? ..."

When you later get to arrays, you can remind them of the concept, and just say that it is being used again here.


Is there any value in teaching pseudo code?

Yes, definitely. There is a need, while developing an algorithm, for a language (or diagramming technique) that is less precise and requires less detail than a formal programming language. This is to let the developer expand his/her thoughts from an overall view to one that is more and more refined. This is true even for high-level languages, though the language itself may be useful for that given a test-first design methodology and good tools.

A pseudo-code is also useful for presenting algorithms in a language neutral way so that implementers may build to suit a need in the language of their choice.

I note, especially, that The Science of Programming by David Gries uses such a pseudo code throughout. The code is defined in the book and fairly precise, though leaves out many details needed for implementation. It is the same language, in fact, that Edsger Dijkstra used in his papers. I used several variations on it as the basis of a compiler course for many years. The Gries book should be on the bookshelf (and in the mind) of every serious computer scientist, and most programmers.

Programming involves several tasks at different levels of abstraction. A good pseudocode lets a programmer focus first on the overall, high level, concepts, without having to change focus, or get distracted by, the lower level details needed for implementation. Even if you use "misspelled java" as your pseudocode you have gained this separation of concerns as long as your development environment doesn't complain too visibly or loudly as you go.

Teaching this separation of concerns to students, via some formal or informal pseudocode, is a way to get them to develop algorithms from the outside-in rather from the top-down (i.e. top of page to bottom of page). That is to say, from the general to the specific, rather from the first statement to the last. Some students seem to want to work in that way initially. The sooner they develop better habits, the sooner they can progress.


(FOSS) Application to show/explain compilation?

One crazy suggestion, install Python from source. Configure time about 42 sec. and compile time either around 3 minutes, or 48 sec with make -j.

Your class will be using Python anyway, and seeing how long it takes to build from C vs. how long it takes to run Hello World in Python ought to begin to give them some appreciation of the differences.

Otherwise, two options that I'd considered are one with a relative fast compile and the other with a longer compile.

Fast compile - C source

The option for a fast, but watchable, compile is curl, which is probably already on the system. curl is written in C. It is available on GitHub. curl is released under its own license which is similar to MIT/X, but not identical. If curl is on the system already you can perform the configure and make commands, and then stop. The students will be able to see what goes into the process of compiling it, and you won't have to modify your system with the actual install. The original install of curl can be used to show what it does. Of course, once you demonstrate the speed of the binary it's nice to have a flashy result. As curl does not require the returned file to be rendered in a browser, you could have a simple ASCII-art file to download. Hosted on the same computer, and using the 127.0.0.1 IP would, of course, be the fastest, and best show of the difference between compile and run times. A simple demo of what could be downloaded could be "HELLO CLASS". curl https://www.gypsyspellweaver.work/hello_class or from the Gist,

My expirements, using an AMD FX 8300 8-core CPU, gives configure times in the one minute range and compile times in the one minute range. In both cases there shouldn't be the need to add any switches or options, and while speaking you won't have to think about what options was I supposed to use? for the commands. Timing your delivery around the process should be reasonably simple, and the process is fast enough to not become boring for the students to observe.

Slow compile - FORTRAN source

There is a project for physics (good place to look for FORTRAN programs) called Octopus for doing virtual experiments. Octopus is released under the GPL ver 2 license, and contains external libraries licensed under a variety of other OpenSource license. The current list of licenses can be found in the GitLab repository. The program does have some dependencies, all of which were easily found in my SUSE repositories for simple installation.

Again, using my system, I found the ./configure command to be quite fast, typically under 30 sec. The compile time, however, was much longer, avg. of 8 min. Use of the -j flag on make was significant in this case, avg. of 3 minutes to compile. As in the curl case, there's no need of switches or options (unless you want to use the -j swwitch on make for the time savings.

Octopus dependencies

The non-optional dependencies listed on the installation page are:

cpp (should be there already)
Perl (should be there already)
Libxc
FFTW
LAPACK & BLAS
GSL

Since SUSE had these in their repos, I'm guessing they're likely in the repos of other major repos. Just be sure that the development packages, -devel or -dev, are installed as those include the headers needed to build other programs, such as Octopus.

In the case of Octopus I have no real idea what would make a fast, and simple, output for the maiden launch of the program. Their website gives a simple run to use. It involves creating an input file, always named imp, in the current directory and running octopus. The simple input file is:

CalculationMode = gs

%Coordinates
 'H' | 0 | 0 | 0
%

Using that example, the best I can create for a demo is to trap the output to a log file, then display the convergence result data. octopus >&log; cat static/convergence. Using my system as a reference, the typical run time is between 1.000s and 1.025s. Changing the command to octopus >&log; octopus >&log; cat static/convergence so that the command runs twice, using the results of the first run to fine-tune the results of the second run, adds approx. .650s to each run. The output of the single run is a table of 9 results and the double run produces a table of one result.

As a final resource, if none of these ideas work for your situation, or instructional style, you could look through the list of programs, organized by language, on dmoz. Surely something there will work for your presentation.


What would be your ideal first lecture in a databases course?

Similarities

For a first lesson, what you want to focus on are anchor points, i.e. how databases are something that's closely related to what students already know and understand.

The prime example here is Excel. We've all seen a data table at some point, e.g. your grades/report card from school are a data table, or your bank transaction history.
My SO is currently in the process of a career change in IT, and I suggested her to substitute "table" with "Excel file", and it really helps to understand the big (though certainly massively oversimplified) picture.

Understanding that, a database can easily be described as a folder of Excel files. This is again massively oversimplified, but enough for an introductory understanding of what a database's purpose is.

Note that you could also represent a database as a single Excel file with multiple sheets. However, for display purposes I prefer having my tables in separate windows, which is easier when working with separate Excel files. It's purely a visual decision.

A practical example

My favorite example, probably because it's what I was taught as a first example, is Blockbuster, i.e. a simple video renting service. It's an example that can be adapted to students' growing understanding of a database structure.

In a first version, you have a single table where each record represents a rental, with customer info (e.g. name), DVD info (e.g. movie title), and rental info (e.g. return date)

If a customer rents multiple videos at the same time, it quickly becomes cumbersome to have to repeat their personal information, which leads to version 2: separating the customer information into its own table, and referencing the specific customer (by ID) in the rentals table.

The same logic then also leads you to separating the video tapes into a table of their own, analogous to the customer example.

This three table structure is fairly straightforward, easy to develop from what was initially a single table, and it teaches most core concepts for database modeling: tables, columns, records, primary keys, foreign keys, and the basics of data normalization.

Database design is a theory, not a technology

It's interesting to note that you could, time permitting, demonstrate the above implementation of a video rental database using a literal folder of Excel files. This helps separate the distinct skills of designing a database (i.e. deciding the structure) and implementing a particular database system (e.g. SQL Server, Oracle, ...)

I strongly suggest separating the two, as the complexity of learning a particular system often distracts from students learning about and appreciating the theoretical database design skill.


Is there a word for mathematics/physics/data-analytics/....?

Sciences of the Artificial

There are many ways to categorize the sciences.  Herbert Simon (Nobel Prize winner, pioneer of artificial intelligence as well as economics, organization theory, etc.) wrote a book-length essay called The Sciences of the Artificial to make a case for why the "applied" sciences have a rightful place in academia.

In The Sciences of the Artificial, Simon laid the foundations for a philosophy of the artificial and a science of design. Artificial (i.e. “man-made”) things surround us. They are constrained by physical laws and, if we want, we can study them “objectively” using the natural sciences: for example, a physicist could take an airplane as a given and study the way it is affected by the flow of wind. But this doesn’t really capture the whole truth of the artifact. An artifact such as an airplane also embodies certain goals that we need to grasp if we are to understand it.

  “If science is to encompass these objects and phenomena in which human
  purpose as well as natural law are embodied, it must have means for
  relating these two disparate components.” (Simon, p. 3)

An artifact for Simon could be seen as a meeting point between an “inner environment”, the way the artifact itself worked, and an “outer environment”, the problem it addresses and the context in which it operates. The relationship between the inner and outer environments is where we find human purpose. A problem solver, engineer, or designer is someone who tries to make the inner environment appropriate to the outer environment. For example: for the inventor of an airplane, the outer environment is characterized by the known laws of gravity and air pressure. He makes choices about the inner environment (the materials to use, the type of engine, and so forth) in order to achieve a goal—flight.

"Goals" as subject of study

For a while I did a lot of reviewing papers in the "design science" domain in my academic field.  Somewhere in all of that material (I can't remember the author) I came across a categorization of the sciences that used the relationship between the science and human purpose:

The physical sciences such as mathematics, physics, chemistry, pay no attention to human goals.
The social sciences such as psychology, sociology, economics, study human motivations as natural phenomena, but are indifferent to them.
The design sciences or sciences of the artificial such as architecture, engineering, medicine, business, allow researchers to take sides, to work on important human goals.  They study problems as perceived by humans, and they study solutions, both using scientific methods.


Did the spread of smartphones increase or decrease general computer literacy?

If somebody has some statistics, that would make a great answer, but in the meantime I'll offer some thoughts.

First off, I think it depends on what you mean by "general computer literacy". I can think of a few interpretations:

If you pick a random person, how computer-literate are they?
If you pick a random person who owns a computer, how computer-literate are they?
If you assign a score to "computer literacy" and then calculate that score for every person and then take the average, what would that number be?
If you assign a score to "computer literacy" and then calculate that score for every person who owns a computer and then take the average, what would that number be?

Are we asking about everybody, or are we only asking about the people who own a computer?

According to the US census, ~60% of American households had a computer in 2003, compared to ~80% in 2015. So if we're asking about everybody, then I would guess that general computer literacy has gone up, because more people have access to computers.

In other words: if you don't have access to a computer, you have a computer literacy "score" of 0. If you have access to a computer, even if you aren't an expert in computer science, your "score" is above zero. So if we're asking about everybody, then the literacy increases as more people own computers.

If we're only asking about people who own a computer, then I think it's fairly obvious that "computer literacy" has gone down, but I don't think that's necessarily a bad thing. Until recently, you had to know what you were doing in order to work with a computer, like you've outlined in your question. Since then, hardware and software companies have done a great job of making their products more accessible, i.e. easier to use even if you aren't an expert. The previously-required expertise has not been necessary, so "computer literacy" has gone down.

However, I don't think all of this hinges on smartphone usage. People have been complaining about the new generation of non-tech-savvy users since the internet began. Eternal September happened in 1993.

Anecdotally, I started college in 2004, before smartphones were popular (the iPhone was released during my junior year). Plenty of my classmates chose the Computer Science department because they were "good at computers". Many of these students struggled when they found out that being "good at computers" meant more than playing video games.

This phenomenon is more general than computer science. I don't have any numbers to back this up, but I've often observed that anytime something becomes more accessible to the general public, many of the previous "experts" see the craft as becoming "watered down" rather than celebrating the fact that more people are participating.

To come up with a specific example: thanks to the internet, now anybody can record themselves playing music, and put that out in the world. Compare that to how music was shared in 1980, and it's easy to see that more people are sharing their music now. But because it's so easy, many of these people are not professional musicians. Many of them are not good at music (yet). So because more people are playing music, does that mean music literacy has increased? Or because more novices are playing music, does that mean music literacy has decreased?

More total people are using computers, but of the people using computers, more of them are novices. Does that mean computer literacy has increased or decreased?

You can ask the same question about anything that has been made more accessible or shareable. Has art literacy decreased because more people are posting their doodles online? There are more novices participating, but does that mean "general literacy" is increasing or decreasing?

Another thing to consider is that "computer literacy" is very broad. If I'm an expert in ethics in AI, but I've never touched a command line, am I computer-illiterate? If I'm an expert in Linux but I don't know how to use a web browser, am I computer-literate? I would argue that we're trading some kinds of expertise (like navigating the file system) for other kinds of expertise (like navigating social media). One isn't inherently better or "more computer-y" than the other.

I also think it's easy to forget how it feels to be a novice. Being new to a subject is really hard, and as experts we tend to forget that feeling. So when we work with a novice, we can be dismissive or frustrated- "it's just a for loop, what don't you understand?" But we're forgetting that it took us a year to figure for loops out. A little empathy goes a long way.

I'll end this with a conversation I had a few years ago that stuck with me. I had a coworker, who went to college back when they used punch cards, where they had to walk to the only mainframe on campus (uphill, both ways) at midnight to run their code. I asked him: do you get frustrated by this new generation of coders who don't know how anything works under the hood?

He responded: "No way! The new generation can do things I never dreamed of doing!"


Through what basic programming language can beginners easily get the concept of programming?

Actually, this depends much more on the teaching methodology you use rather than the language. The best answer might just be the language that you, yourself, are most productive in. But if you aren't a programmer yourself, it may be very difficult for you to teach them.

But, if I had to name a language that is (a) fairly modern and (b) fairly forgiving of beginners and (c) widely used and (d) a useful tool for people with other interests, then it would probably be Python. If you give up one or more of my criteria there are many other choices.

But the teacher needs to be proficient in the language and its use. Programming is a way of thinking, not just knowledge of the features of a language. I worry that, just because you are asking this question, that you may not have the required background to do a good job of this.

However, all is not lost. I asked a question of my own here a while ago that might provide some guidance to you if you are, indeed, a novice programmer yourself. See the question and at least my answer to How do you teach something when you don't know it yourself.  The short version is you admit your lack of knowledge and learn it along with the students. But first you need to find good tools and resources.

If you use Python, make sure you use V3 and not the earlier and incompatible V2. It isn't any harder to start with the current version.


Short foundational lessons for 7-8 year olds

If you are merely looking for feedback on this, let me point out, first, that according to Piaget's work, your students seem a bit young for this. They have only just entered the third stage of Piaget's Model. Moreover, since not all people advance in sync, some may still be in the second stage. In particular they are still very concrete thinkers. Anything that depends on abstract thinking won't be very comprehensible to them for a few more years.

For a small exercise, however, the above might not matter too much as you aren't expecting them to do much but think "WOW".

But there has actually been a lot of thought given to "computational thinking", through Jeannette Wing's work. This has mostly been directed at slightly older students, however, say secondary school.

There is a well developed effort to bring computational thinking down to this age level. CS Unplugged, provides a fairly comprehensive set of activities that are targeted at 5-10 year olds.

While there are a lot of things you can do, don't expect the kids to retain a lot of it, and certainly don't expect that they can then (or soon) abstract from it to actual computing. I find that Spiral education, in which ideas are introduced in a simple way early and then returned to (often), works well. So, for a first cycle, you give them a hint of things that might be and later reinforce that more formally.

I find that something as simple as the song There was an old lady that swallowed a fly is interesting and fun. It is also an introduction to recursion, but at that age, don't talk about base cases, etc.

A few more words about logo. While it is a fine language, you need to use it carefully for youngsters, so that what you do matches their cognitive level. Since they can't do much abstraction yet, there are a couple of possibilities. Since it is visual it matches their "concrete view" of the world, of course. One is to use only the language primitives. But another is to build a virtual world in logo with a set of its own "primitives" that they just use instead. These can be of a higher level than the built in commands, but are opaque to the students. Karel J Robot is like that actually. Robots obey five simple commands (move, turnLeft, etc) and students begin with only those. The robot language hides the underlying Java primitives completely.


Here is a short list, of some ideas. You could not teach them all fully in a short time, some you may only introduce, discuss, compare:

What is cloud: Just one or more servers on the internet. The advantage is that you don't have to invest in hardware. Cloud is tech marketing speak for “Somebody else's computer”.
Cloud provider independence: Look at tools that allow easy migration to other cloud providers, such as docker-ce.
Cloud services vs my services on someone else's computer.
Gnu/Linux: This OS runs on 490 of the top 500 super computers, the other 10 run UNIX. It is also used by >60% of the web, and most of the internet infrastructure.
no-sql databases: such as couchdb, mongodb, et al.
no-cloud: The cloud sounds fluffy and distributed, but it is not. Look at fully distributed systems, such as ipfs. ipfs is a bit new, so future looking.
Configuration control: such as pupet, ansible, cf-engine. These can be used to deploy software, and keep servers consistent.
Focus on what service it provides to the user: A place to ask and answer questions vs a web site.


Simple explanation of JPEG working principles

The basics

Let me start with a quick overview of how JPEG (as usually applied) compresses color images.

Colorspace and downscaling. Raw images are usually encoded in the RGB color space. The human eye is more sensitive to the luminosity of images than to their chromatic aspects — as an extreme  example, we can understand black and white photos quite well. Therefore JPEG images store more information about luminosity and less about colors. This is implemented in two steps. First, the RGB color space is transformed into a different color space (in a linear fashion), YCbCr (similar to the TV color space YPbPr) in which Y is luminosity and Cb/Cr encode how much the pixels are blue rather than purple (Cb) and red rather than green (Cr). The Cb and Cr planes are then downscaled or subsampled, that is, their resolution is reduced, usually by a factor of 2 in the horizontal direction (the eye is more sensitive to the vertical direction). From this point on, the three planes are compressed individually.
Division into blocks. Each of the color planes is now divided into 8×8 non-overlapping blocks (in contrast, in MP3 the sections are partially overlapping), which will be compressed more-or-less individually. This division is the reason for the so-called blocking effects, since the superimposed grid cuts through features of the image.
Spectral compression by quantization. The basic insight behind JPEG is that nature is noisy, and this noise is filtered by the human visual system. It follows that we can throw away the noise without substantially affecting the way the image looks. It remains to decompose the image into its "substantial" and "noisy" components, and this is accomplished by a 2D Fourier transform. Recall we are trying to compress 8×8 blocks. The most important feature of a block is the average value of its 64 pixels, known as the DC component (or, zeroth Fourier coefficient); the DC components of all blocks are just a result of scaling down the original image by 8 in both dimensions. The importance of the other components, known as AC components, depends on their frequency — the higher frequencies correspond to noise, whereas the lower frequencies are more informative. However there is no clear cut distinction between features and noise. For this reason, we need to retain all components, albeit with different accuracy. Accordingly, we quantize the different components to various degrees, depending on the frequency: components corresponding to higher frequencies are quanrtized more. The exact quantization matrix depends on the disparity between the horizontal and vertical dimensions, and has been determined experimentally. (It also depends on the quality parameter of the compressor.)
Entropy encoding. It remains to encode the quantized components into bits, which is done using Huffman coding, a standard encoding scheme. Since the DC components of all blocks are a downscaled version of the entire image, we expect them to vary continuously. Therefore instead of encoding their actual values, we encode them differentially, that is, we encode the difference from the preceding DC value. The AC components don't have this behavior, and so are encoded absolutely.

Artifacts

Why does compressing geometric drawings result in artifacts? Geometric drawings are very different from natural images. They don't vary continuously. Spectral compression results in "smearing" effects, since we are only retaining the lower frequencies. The best illustration of this is the Gibbs phenomenon, which is the continuous analog of the same issue. When trying to represent a step function using Fourier series, we need to use all frequencies. If we suppress the high frequencies, we get something really different. Lines in a geometric drawing are the discrete analog of step functions.

Another problem is the blocking effects. Imagine a diagonal line. JPEG partitions the space around these lines into 8×8 blocks, which are compressed individually. No attempt is made for the resulting lines to match exactly, and indeed they probably don't. This is very apparent because lines are very clean and exact, something that cannot be said about real-life images.

Teaching ideas

Using software like Matlab, you can show the effect of quantization on a real-world image, and then compare it to the effect of quantization on clip art. You can vary the quantization steps to show the effect of downplaying the higher frequencies (and also what happens when trying to suppress the lower frequencies).

You can demonstrate the effect of blocking by varying the angle of a line which is compressed block-by-block, or fixing a line and varying the block size. You can use a low quality setting to emphasize the effect, and include the block boundaries to highlight its origins.


Encouraging Critical Thinking On Programs Before Students Write Them

I agree very much with ctrl-alt-delor that the level of "total novice" might be rather early to introduce larger-scale meta-design techniques into coursework.  The work being done at that level simply does not require (at a cognitive level) such deep planning to execute properly.  Since the need is not self-apparent, efforts to bring it into their work will typically feel like extra, needless work.

If you would like to help them understand how to use plans (and how to utilize good, structural thinking), here is a way you might go about it.  Provide a diagram in class, and talk through it as a group.  Next, ask the students to work with a buddy to make a series of modifications for different purposes.  At the end of this exercise, they will have several different diagrams.

Ask them to choose one of their diagrams, and imagine that some other coder will have provided some source code that attempts to follow their specification.  However, it is their job to verify that the code that they receive truly will work as specified.  They should now work with their buddy to design the trickiest test cases that they can think of!

You can encourage this by enthusiastically placing great examples of test cases on the board as students come up with them.  "Look, how wonderful! Testing for the empty string!"  Or "Using a negative number is a great way to try to trip things up!  Great thinking!"

Finally, whichever project they chose for their test code, they should actually program as a lab.  (This could be done as paired programming or as solo work.)  When they submit their lab, they will provide a UML diagram, thoughtful test cases, and their coded solution.

Congratulations! You've now integrated student choice, prior design, unit-testing (well, the core of it anyway), pair programming, and created an assignment that is harder to cheat on than the standard mainstays (like sorting algorithms) in a way that feels natural and un-forced.


Teaching (2,3) and AVL Trees: information in internal nodes or in external nodes?

I think the two situations are entirely different in applications. In the case that the internal nodes are only search keys we find applications in database indices. By associating keys with internal nodes we obtain space efficient dictionary types.
The contrast between the two cases could help learners understand the concepts more easily. By focusing on the differences between the two cases, perhaps without too much reference to the implementation of the tree operations themselves, learners would better understand the utility of the datatype.
Once that is the case you could choose either case to explore the operations in more detail. Or why not be groovy and use red/black trees. As a student I found AVL and 2-3 tree theory deeply boring whereas red/black trees were quite exciting. I think because the rules are so much more interesting, involving colours rather than arithmetic.
As a teacher I have always regarded me being confused as a sure sign that my learners will be. Perhaps more visuals would help out - and that means colours - and those tree rotations are beautiful!
I would also say that such things are not really confusing - its just how they work out - like music, its just that way. Similarly AVL trees and 2-3 trees being the data type analogue of Manhatten Transfer are less inspiring to a modern audience than https://www.youtube.com/watch?v=HZfnmNf5MwA.
What you say about splay trees, and the finer implementation details of B+tree indices is correct, but who really cares - not your students - they are already confused. Give them some colours, give them a taste of the good stuff and ... then start looking at 2-3 trees, I mean, when you are no longer bored, confused and not listening - but instead - curious and inspired, those 2-3 trees ... well are they
Fibonachi? I mean, thats better than dyadic surely ....
Answer - its best if your students are still awake after 10 minutes, ;)


How to integrate CS when learning about DNA/RNA/protein

Create a DNA-like representation for the alphabet

This activity establishes a background experience that can later be used when teaching that DNA and computer data are sequences of discrete values. Each student picks three colors and creates a 27-character table showing all permutations of "codons" of the colors, akin to the 4^3 DNA codons representing amino acids. This activity was implemented in a U.S. grade 7 science classroom. An example of the student work is shown below, although the printed worksheet was revised after the pilot to make more explicit connections to both computer science and genetics.

Sample student work:


Best practices for letters of recommendation in CS

I write a paragraph saying who I am, and where and how long I have taught.  This is standard for all letters.

I write a brief second paragraph stating how long and in what capacities I have known the student.

I then answer these four questions from an old Columbia form.

A.  Please tell us about the candidate's intellectual qualities and
academic work.  We are interested in the nature of his or her motivation for scholarship, breadth, and depth of intellectual interest, originality, and
capacity for growth.  Cite specific examples where appropriate.

B. What are your impressions of the candidate's character and maturity?
How do fellow students, teachers and you regard him as a person compared with
contemporaries?  Does the candidate show open--mindedness toward opinions,
values, and backgrounds different from his own?  Does he have any special
strengths, weaknesses or problems of which we should be aware?  We would
welcome any additional comments you think might be helpful to us.

C. What has been the candidate's most valuable contribution to your
class?

D. Do you have any reason to doubt this student's integrity?

Lastly, I have a closing paragraph that looks like this:

Thank you for taking the time to read this letter.  If you have questions,
please send me e-mail at XXXX@gmail.com; this account is entirely separate
from the school and you may communicate in complete confidence.  You may also call me at home in the evening at 919-XXX-XXXX.

My work phone and address appear in the head of the letter.


Should I share CS jobs stats at a Girls Who Code session?

Expanding my comment and those of others to a full answer seems to make sense now. The short answer is, as Ellen Spertus notes, there is no reason not to, but it isn't enough.

Young people need good, and honest, guidance about what they might expect from their choices. But the future isn't necessarily determined by things we can see at present, so in many ways the best advice to a student is to "be flexible." Their future will be determined both by circumstances and by a series of choices that they make; not just one choice.

Right now, tech salaries are high and job opportunities abound, but a secondary school student's career is years, even decades, away. The world is not likely to look the same over that period of time. In particular, advances in AI may make many software development roles obsolete. At one time, a huge fraction of people in the US were involved in farming. Now it is a tiny fraction. The same is true in manufacturing. While we still have farmers, most farming is managed by giant corporations employing unskilled and low-paid workers. The same could happen in computing. While there will likely always be a need for software development, it might, in the future, be entirely managed by a very small cadre of highly skilled folks.

One of the trends in evolution is specialization. Organisms become more and more specialized to their environment as long as it doesn't change. However, when the environment does change those specialists are normally wiped out and replaced by others better adapted to the new situation. If you know one thing well - better than anyone - you may be well placed in some environment, but if it changes you are lost. However, if, along with specialization, you also foster generalization, you are better prepared for change.

This is why a liberal education which includes some specialization but a lot of generalization is such a good thing. If you can be good at two or more things you are probably better off than if you can only do one thing well. But, even more important is an attitude that your education won't end at some determined age or milestone. If you truly believe that you can and should learn throughout your life, and learn things sufficiently different from what is needed in your profession, you are well placed for most foreseeable futures.

I have an unproven theory, that in the real world, most specialists have a boss (or a boss's boss..) who is a generalist. The one who knows a lot of things and can see the bigger picture is likely better placed to lead than the one who sees the world through a microscope. If you teach, it may well be that the least technical person in your course will end up being the employer of your uber-geeks.

However, those with few resources, have a different problem. While it is great to say Do What You Love, you also need to temper it with Do What You Must, or even Do What You Can. But even if you need to compromise for monetary or familial reasons, the attitude of a lifetime of learning can still benefit the individual. This is, more or less the mantra: Yes I Can.

Also, for those in unfortunate circumstances collective action and mentoring by peers and others is especially needed and especially powerful. If "daddy" is a millionaire you can probably do what you want, but if you come from a more modest background (as I did) you need to gather the resources you can - mostly other people.

On a personal note, I studied Mathematics, but wound up in CS. I might have wound up as an actuary, but it sounded boring. I was meant to do mathematical research, but never really got the chance after I finished my doctorate. Up until about two years before I finished, the job prospects for mathematicians were fantastic. Like CS today, there were lots of jobs and good salaries. But it all fell apart in about a year. When I finished there were no such jobs - none. Several hundred applications resulted in no offers, though I was well respected at the time and wrote a very nice thesis. But I really wanted to teach, and so took a job that I was, in many ways, overqualified for. But it kept me in the profession, even though I had to change fields. I never programmed a computer until after I had a PhD. But I knew how to learn and how to work hard.


Strangely, just after posting a question I found a list of additional link collections:

https://github.com/zamansky/awesome-cs-education
https://github.com/quobit/awesome-python-in-education
https://cseducators.stackexchange.com/a/3947/9632

And one chat:

https://chat.stackexchange.com/rooms/59174

I still think there should be more, but this is a start.


Exercise or example to reinforce idea of functions?

I saw the light at the end of the fiber optic cable as soon as you said that these are students of electronics. There is nothing more modular and encapsulated than that! Software is simply electronics without the hardware part.

If you said to them, "What are the building blocks of a simple AM radio receiver?" they would (hopefully) reply something like: antenna, tuning, rectification, filter, audio output... A crystal radio has all of those. They already know that it is pointless to build the antenna in to the filter, or duplicate the tuning parts more than once. They know that they can work in teams to produce parts that fit together to make a complete radio.

So speak to them in a language they already know: the functional relationship of parts and wholes. Using globals instead of parameters would be like having extra cables going outside the radio to connect different parts of it to the signal path or the power supply. Can you say "Rube Goldberg"? I knew you could.

Man, let me teach them. I have been studying electronics on my own since before anyone I knew even had seen a computer. Electronics students should be the easiest audience in the world to teach programming to. Use examples they already know.


Discrete function is also a math function?

Focus on the idea that the sets can be finite. They don't need to be defined by a formula. Any set of ordered pairs is a relation. If there is a unique second element for any given first element then it is a function.

For example, the set of pairs {(5,2), (5,4)} is not a function, since the value associated with 5 is not unique. This is a relation: a set of ordered pairs.

But {(5,2), (6,2)} IS a function since the value associated with 5 is unique and the same is true of 6. It is a constant function, by the way, since all values map to 2.

Additionally {(5, 2), (6, 3)} is a function and its inverse is {(2, 5), (3, 6)} which is also a function. Thus the original here is called invertible.

You don't need Lambda Calculus or any mathematics to show what a function is. Finite functions can be computed by table lookup or by hash maps. An array is a function from a certain set of integers to some other set (the values).

Actually functions defined by formulas in computing are often problematic since computations of many values (say Real Values) are only approximate.


I'm not a fan of full IDEs for beginners. A few years ago I switched my first year students (Java) from NetBeans to an online tool without any autocomplete or helpers for most assignments and found that they've gotten way stronger at writing code. I think the automatic stuff that helps out while programming becomes a crutch for newbies.

Our intro teacher, who teaches Python, really likes Idle for his first year students because it's so simple.

I've also used PyCharm with second and third year students, and really like it. It's what I personally use when I'm writing Python code. The free community edition is plenty for classroom use, but they've also got free licenses for students, teachers and classroom labs if you wanted to use the pro version.

  a lot of their mistakes are because the tool told them to

So much this. When NetBeans highlights something in yellow, students feel that they have to click on it and follow the programs advice even when they have no clue what it's saying.


Methods for engaging students when teaching unpopular or unfashionable topics

There two important facts here:

  Complexity is in every programming language
  Popularity is due to a marketing monster talking on every opportunity (for example on the Youtube adds about what is trending
  and what not)

For the first point.

We need to translate programming teaching about new fields; for example in many cases teachers spend a lot of time talking about theory, origins and giving more importance to math exercises

For the second one We need to know more about other technologies, for example if an student asks to me, hey teacher why I do need to learn Java, existing Python or Ruby?

Things yo shouldn't do it

dear student Java is ugly but neccesary to get a job

Things you probably should do it

  Java is a complex language
  Java around the world is the key to get a job in a easy way
  (Showing proves) Java has the most high salaries
  I f you get fluent in Java is very secure you can move yourself to many other languages

Many times the key factor is "What I can do if I learn this technology"?

And the answer for this question is not easy for many IT Teachers, for example I know a lot of them whose only make simple math exercises about calculate pows, substracts and stuff like those.

As technology moves, Teacher needs to do in the same way; for example:

PROPOSALS

  We're going to learn Java, for building an app
  We.'re going to learn Java for building a chatbot using the Facebook API
  Maybe we're going to learn Java for building a Instagram clone
  We're going to use Java but combined with Angular for example for building an API

I mean programming languages are cool but is better what can we do if we understand them

At the end We as IT Teachers need to move, re learn and interpretate how this world is changing in every oportunnity

example

Fr this course I need to build an app with my students:

the good

apps are very popular
they are expecting discover something amazing
I choose to use Angular 6

the bad

They have not computer in many cases
They don't know how to use simple tasks: email, word .....

I choose Angular for building an PWA, is a good alternative, I will show them differences and similarities

Advantages

They will discover with me how to program
in spite of not use Java, We're going to understand how to build a product
Students will be free to choose the content of this PWA
PWA is part of some requisites for web development jobs

So I will be give them another option, itself they can change after if they have the ooportunity to learn Java or any other thing


Should assembly language be taught in an introductory course (or soon after)?

I think there is very limited benefit in teaching assembly so early, and it's more likely to just scare away your students.

When I started learning programming, I thought bare-metal OS development was really interesting, and I started to learn about it (mainly through OSDev). But frankly, assembly was far beyond my level at that point, and it was hard to get anywhere beyond the tutorials they give. Consider that:

Beginners often have problems with learning the syntax of the language, and the underlying conceptual problems ("how do I design this?"). Your students may not be ready for that after an introductory class—learning the concepts and thought processes (how to think like a programmer) is far more important than any language, and assembly only clouds that by making you think about memory, registers, jumps, etc.
Your students probably won't ever need assembly, and they almost certainly won't be writing much unless they go into fields like embedded development, OS development, etc. Even then, it's more likely that C (or a similar low-level language) will be used.
Assembly is intimidating. It's not something that it easy to read, understand, and write. Aside from the technical problems of teaching and learning, it's just scary, and when I tried to learn assembly, it just led to frustration and not a lot of progress.

My opinion is that you should develop the higher-level concepts first, and make sure your students have a solid understanding of how to write code logically. Then, you can begin to 'remove the stabilisers', introduce memory management, and then finally lead to assembly, if that's what you want to teach.


When should concurrency and parallel multi-processing concepts be introduced?

If we don't introduce parallel/concurrent thinking early, our students can develop a sequential mindset that makes it hard for them to make the shift later. The rest of this is in the context of a college/university CS curriculum...

Multithreading can be discussed in CS1 if the students build GUIs, since the GUI needs its own thread to maintain responsiveness while the main thread is handling time-consuming GUI events.  But most GUI libraries do this multithreading for you, so the students don't have to do it themselves -- you can talk about what's going on under the surface, but the students don't gain any hands-on experience and it's unclear to me how much they take away if they don't have to do it themselves. But there are schools that take this approach.

We introduce students to multithreading in CS2 (Data Structures), using Just-In-Time pedagogy.  The basic idea is to give the students a problem that requires them to store a lot of data in a data structure (e.g., an organism's genome in a C++ vector or a Java ArrayList, or a really big image to be processed) -- enough data that processing the data sequentially takes 5-15 seconds.  This is an eternity for todays students and they get impatient waiting so long for their program to solve the problem.  We leverage that impatience and use it as motivation for introducing multithreading and parallel execution as a means of speeding up the program. We think the CS2 (Data Structures) course is the first time there is a natural motivation for introducing multithreading, since that's the first time you can store enough data to really motivate it.

Our CS3 course is an Algorithms course, so we continue the exposure there by introducing parallel versions of searching and sorting algorithms, graph algorithms, etc.

Our fourth course is Programming Languages, where we spend 1-2 weeks on languages that provide features for parallel / concurrent execution.  For example, we contrast languages that expect threads to communicate via shared memory (and the different mechanisms to synchronize those accesses: semaphores, locks, condition variables, monitors) with languages that have threads communicate via message passing (e.g., Erlang, Scala).

Our sixth course is OS & Networking, where spend several weeks exploring the implementation of the features needed to do all of this: threads, processes, semaphores, locks, condition variables, message-passing systems, etc.

The upshot is that parallel and concurrency topics are "sprinkled" throughout our curriculum, rather than being confined to a single course.  (We also offer a junior-senior elective course that focuses solely on parallel computing, so that students who want more can dig deeper into the subject.) That's one way to do it.


To what extent should UML be covered in the context of a degree?

From my software engineering experience.

Some of it is useful some is not. It was put together by a committee of organisations that had a product to sell. (state machines got in there because a committee member had a state-machine editor.) A lot of other useful stuff was missed out.

Take what is useful, leave the rest, and use stuff from elsewhere.

There is nothing unified about it. I have used mainly class diagrams, some dataflow (I think it may be called), but as you say not too much formality. We never passed them through a linter. At one time we were drawn in to using them to create code. This was an expensive lesson.

Most of the diagrams (may be all) existed before the UML. I tell my pupils that some of the diagrams are useful, but also look else where. I tell them which ones I have found useful. And I tell them what I have said here: there is nothing special about the UML (or the process of collecting together, arbitrarily, some diagrams notations).


What to consider when choosing version of Python?

A few years ago, the answer to this would have been "stick with Python 2; the libraries aren't ready for Python 3 yet". In many cases, that would have been a deal-breaker, because many of the older libraries were pretty useful, particularly for scientific computation.

However, the story's a bit different now, in 2017. There isn't much of a reason to stick with Python 2; almost all of the top 360 libraries support it now.

A few popular resources, like Learn Python the Hard Way, have remained ardently Python 2-only until recently (early 2017), and I suspect a lot of old tutorials haven't been updated.

If you stay with Python 2, you miss out on all of the really nice features, like async and f-strings, which have only been added to the 3.x series.

Something to consider, though: Python 2 and 3 are very similar, and learning one will mean you can relatively easily switch to the other. Python 3 just removes the major 'gotchas', like 5 / 2 = 2, or bad things happening when you use Unicode. For beginners, I think it's a great advantage for things to work intuitively (until, of course, you fight with the floating point representation issue).

Generally, I don't think you'll experience any problems with Python 3, and it seems logical to me to learn the future of the language, rather than Python 2, which is legacy.


How do you read and write a project beyond a one-page script?

For a language like Java, the way out is to pick a project that isn't just the solution of some equation(s) or a similar mathematical problem. Find a project in which the description of the problem can be analyzed as some "thing" that has discernible "parts". The parts can be modeled as classes and the resulting objects composed into a solution.
One that is simple enough is a calculator. A calculator has a display. It has keys that have actions, which vary depending on the "state". For example, the "5" key behaves differently in the case that the previous key was an operator or another numeric key. The answer of Ben I. mentions design patterns. This is an example of the Strategy Pattern.
Most calculators employ a stack or other hidden register beyond the display. Calculators have an operational strategy of operation that differs for an RPN or an algebraic calculator. The precedence of the operators may be important, or not.
The calculator can print out a tape of recent operations, or not. It can have a GUI or not. If it has a GUI then you can build it with MVC or not.
And if you want a real challenge (the Polymorphism Challenge = writing a program with a limited budget for selection statements), it is possible to build such a thing without a single "if" or "while" statement, provided the user gives the key presses. This will give you very low Cyclomatic Complexity, which is a desirable feature of any program.
But it is the "parts" composed into the whole that is the essence of this.

I've purposely not provided pointers to some of the terms here. You can explore them on wikipedia or elsewhere. But the polymorphism challenge search will lead you astray. Look HERE for guidance.

And using JavaDoc consistently is a good habit. If you are extending an existing project then the JavaDocs already (hopefully) in place should be a good guide to the operation.


How to avoid misconceptions about while loop when using null loop

To add some context from the chat room conversation: This is part of a larger course that introduces technology in an applied fashion. The segment with the robot is 10 days and the students have not necessarily programmed elsewhere.

Empty while loops

I would recommend against beginning with any empty loops for your students.

All the looping constructs are best understood when presented in manner that fulfills the purpose they were created for. An empty loop, using any of the available constructs, is using the loop for a purpose other than what it was designed for. If the loop is being placed so that you can add functionality later, at least replace the comment so that it is clear something is planned for inside the loop later. If you are using the PLTW "Natural Language" module, and start with the function

waitUntilDistanceSensorLessThan(200)

you can expand the lesson by replaceing that with the loop:

while (sensorValue[distanceSensor] >= 200) {
  // Things to do while the robot moves closer
}

That way you are not presenting an "empty" loop, but one that is planned for a purpose, and that purpose just happens to be "to be determined." Don't leave it that way either, but fill it with something real before executing the program. The comment line is showing the development process of changing the first version into a useful version. The next step is to then put something there, even if it just flashes the LED as the robot advances to the target.

while vs until

Some programming languages have an until control statement, others do not. Many of those which have both a while and an until separate their usage by having the while test the condition before the loop executes, and the until tests its condition after the loop executes. In hypothetical syntax they are commonly like this:

set(testCondition);
while (testCondition == TRUE) {
    doThisFunction();
    doSomeOtherFunction();
    update(testCondition);
}

do {
    doThisFunction();
    doSomeOtherFunction();
    update(testCondition);
} until (testCondition == TRUE)

Syntactically, the until loop is guaranteed to execute at least once and the while loop may not execute ever.

Many languages which do not have an until control statement still provide for testing before or after execution of the loop. In the case or RobotC, the language of this question, the syntax is like this:

while(SensorValue(sonarSensor) > 20)  // while the Sonar Sensor reads data greater than '20':
{
    motor[rightMotor] = 50;               // run 'rightMotor' at power level 50
    motor[leftMotor]  = 50;               // run 'leftMotor' at power level 50
}

and

do
{
    motor[rightMotor] = 50;  // run 'rightMotor' at power level 50
    motor[leftMotor]  = 50;  // run 'leftMotor' at power level 50
    bursts = bursts + 1;     // increment 'bursts' by 1
    wait1Msec(3000);         // wait for 3000 milliseconds before continuing
}while(bursts < 3)         // while 'bursts' is less than 3:

Source RobotC Wiki: Control Structures

That still leaves the testCondition as an issue, however. Based on the English usage, from which most programming languages derive their meaning, "while" and "until" are opposites. "While" implies that something is not done unless the test is true. "Until" implies that something is done unless the test is true. The while loop exits when the test condition is false (fails), the until loop exits when the test condition is true (passes). Using that, for a language which lacks the until control statement, the same functionality can be created by using a negative test. Thus until (done) becomes while (notDone), or if the language uses this syntax, while ( ! done). Thus until's usage can be created when needed. In the case of RobotC it's even possible to create the common version of a tail-test by using do {} while (! done)

Note: Perl has taken the while vs until concept and extended it into the realm of the if statement by creating an unless test:

unless (testCondition) {
    say "testCondition is FALSE";
}
else {
    say "testCondition is TRUE";
}

Limited prior programming exposure

All the above, absent the motor and sensor parts, really applies to any programming related course. It can even help prepare students for what they will encounter "in the wild" with other languages not covered by the course. The specifics of this question, however, with its short duration and unknown, but probably limited, prior programming by the students, creates extra concerns.

As made clear in one comment in chat, the students may not even understand the concept of statement block and there is precious little time to explain all the details of programming, let along all the possible variations. With the objectives of awareness/excitement about career paths in mind, planning ahead and having some of the desired variations pre-built might be helpful. For example, the first two code segments could be saved, and quickly "built" with the students. A third variation, which might be attractive to the students, is to have the LED flash faster as the distance closes with the target. Using guessed numbers for examples here, with numbers found to be useful in the lab replacing mine, the original waitUntilDistance.... line could be replaced with something like this:

int totalDistance = 500;
while (sensorValue[distanceSensor] > (totalDistance/25)) {
  sensorValue[LED] = 1;
  delay(300 * sensorValue[distanceSensor] / totalDistance);
  sensorValue[LED] = 0;
  delay(200 * sensorValue[distanceSensor] / totalDistance);
}
sensorValue[LED] = 1;

That will give a duty-cycle of 60% and an initial frequency of 2 flashes per second, and a final frequency of 50Hz. Another chance to reinforce some math and science, increase the engagement with the robot, and not introduce new programming concepts.

In consideration of the limited time and limited programming exposure before this segment, I think that introducing the empty loop

while (waiting-condition) {
  //empty loop
}

will cause more students to stumble, and not necessarily later. The emptiness might make apprehending the statement block concept more difficult than it already is. I'm also not so sure you should even divert into the infinite loop of while (true) {} at all. If you do use the LED-alertButton combination you presented in the question, modify it to respond as a toggle rather than a one-shot that turns on and then appears to ignore all future button presses. The program might loop forever, but it will look to the students like it turns on the LED and then stops responding.


I did what the OP is describing for all of my students during the month following the AP CS exam in the U.S. Students were given a list of potential topics to research and then present. I also gave students some things the presentation needed to include:

At least two original examples (in code)
Well formatted and commented code
References useful for learning more about this topic
Some context to explain how or why this topic is useful

Students shared their presentation with me before delivering it to the class and I didn't need to spend much time outside of class working on this.

Since students had spent a year with Java, but actually covered very little of the language and standard libraries, some of the topics given involved delving deeper:

Using Threads and Runnable to handle concurrency
The Servlet API: creating a basic web application
Pick another language on the JVM and learn enough to demonstrate it
Lower level network code in Java: UDP for a chat app
Lower level network code in Java: Sockets
Parsing XML
Parsing HTML from a web page (e.g. stripping out the barometric pressure from a weather.com)


What should be the difference between a university course and developer training?

I teach and develop curriculum at a training-oriented nonprofit, and have taught in an academic setting as well. Here are some of the ways that I try to approach trainings for professional developers:

Remembering that trainings are for practitioners, and as such, the lessons should be oriented toward objectives that will be immediately useful in their work. So, for example, with entry-level developers we de-emphasize (and sometimes leave out completely) topics such as concurrency and algorithm analysis.
In general, relate the presentation of topics as much as possible to how they will be used on the job. With assignments, this can be essentially a linguistic slight-of-hand: state assignment tasks as user stories, provide a narrative for the assignment that aligns with workplace practices ("The client has asked for feature X, and your team lead has tasked you with this feature"), etc.
Using current, professional-grade tools: Git+GitHub, widely-used IDEs, professional-grade databases (e.g. not DBs like SQLite).
Using as supplemental (and sometimes primary) resources that professional developers use. In particular, we emphasize use of official documentation and references.

These approaches often are employed in an academic setting, but they are essential (in my view) in a training setting, where developers will highly optimize their own learning toward direct, practical application. As the instructor, it's my job to make clear the connection between the material and their day-to-day work.


Scope and Sequence for Raspberry Pi Course

I would teach the command line first. Both units 2 and 3 require use of python, which I wouldn't teach before the command line because it is normally run from the command line. I'd also teach the command line earlier because I find that it makes students more comfortable knowing it. It could also be useful because you could teach some command line utilities to connect to the pi and that we prepare the students to learn about networking further.

Generally, teaching shell scripting opens many doors into computer science that I'm sure a few of your students will happily explore. Once you know the command line you can learn how to write command line utilities, explore networking,  process management, and so much more. I think it'd be more effective to get this vital information to students earlier rather than later.


Looking for a simple, offline, portable, lightweight IDE for C++ with a compiler and debugger

My department uses Dev-C++. It's free, simple, offline, portable, and lightweight. Windows native.
Over the years the maintainer has swapped hands a number of times, it's occasionally gone a number of years without updates, and the size of the install has increased. But I like it quite a bit. As of this edit it got a new maintainer and update to v.6 a few months ago (November 2020):

Dev-C++ v.6 by Embarcadero (72 MB, 1/31/21)
Dev-C++ v.5 by Orwell (49 MB, 4/27/15)
Dev-C++ v.4 by Bloodshed (9 MB, 10/10/05)

Mirrors for the v.6 version that avoid the current maintainer's request for a lot of personal data can be found here and here.


What's the point?

Why does the number of lines in the project matter all that much? Unless the code is extraordinarily long or short (i.e. orders of magnitude away from what is expected), lines of code aren't a good indicator of whether a project is good or bad.

I've heard of one example where some students were set the task of creating a Caesar cipher1 program. If you're aware of it, you'll know that it can be trivially solved by using modular arithmetic2:

def encrypt(ciphertext, shift):
    output = ''
    for character in ciphertext:
        output += (character + shift) % 26
    return character

So, the 'smart' solution uses 5 lines.

One student submitted a solution to that function with 1382 lines.3

Wait, what?

I suppose you'd quickly realise that this student's solution was... sub-optimal... if you asked them how many lines when they presented their project.

And here's why:

def encrypt(ciphertext, shift):
    output = ''
    for character in ciphertext:
        if shift == 1:
            if character == 'A':
                output += 'B'
            elif character == 'B':
                output += 'C'
            ...

So now you can see the merits of using code length to spot solutions that are over 250x longer than necessary.

But when the difference is much smaller, why bother using lines as an indicator of anything? Hopefully, students are writing clear, maintainable code, not playing code golf, so a longer, explicit solution may actually be better.

Equally, treating a higher LoC measurement as a better project is a bad idea. If you do that, you're encouraging unnecessarily verbose solutions, like our student who wrote 1400 lines for a 5 line problem.

Summary

LoC can be useful for spotting really badly wrong solutions, but setting 'targets' with it can be harmful.
Asking for the length directly is probably pointless—instead, just take a look at that when you review the code and mark it.

1You might also know a variant of this as the ROT13 cipher where the shift is 13. This has the convenient property of being self-inverse, so you don't need to subtract to decrypt in a separate function. If our student was really clever and wanted to implement that in Python 2, they could have just written input().encode('rot13'). It's a whole new world up here!

2There's a bit of a lie-to-children here, if you're not paying attention. That code assumes that all the letters you want to encode are encoded from 0 to 25 (e.g. 0 = A, 1 = B). That's not how character encodings work in reality (there's an offset in ASCII before you get to the capital letters), but it's not relevant for the example.

3I cheated and calculated the amount of lines you'd use from that approach, rather than actually writing the whole thing and counting the lines.


While giving an introduction to the Internet, should I talk about the risks?

Yes.  You should absolutely identify the specific risks of each technology or tool that you are going to teach and discuss those risks before you assign students to use those technologies or tools.

The exact form of these warnings depends on what exactly you are introducing and the age of the students.  This is also a decision that should be made in the context of a school-wide policy on information technology.

If you're teaching TCP/IP to college freshmen, there's obviously no reason to go off on a tangent about the dangers of sexting.  If you're teaching sixth graders how to use your school's library databases, it's probably not appropriate for you to bring up many of the dangers of the internet.  So of course keep the warnings relevant and age-appropriate.

But if you're assigning students to create a class blog, you should give them instruction about not putting certain personal details on it, about dealing with spam, about creating and protecting a secure password.  If you're using a social media group (like a facebook group for the class) you should remind students about school policies that apply to the group (about swearing, offensive materials, cyber-bullying, cheating).  If you're teaching php development for a database app, you should warn students about SQL injection attacks and other common security risks.

Keep in mind that it's unlikely that you'll encounter students who haven't already used the internet.  My son is four and he's a big fan of YouTube already.  So remember that you aren't really introducing "the internet" - you're introducing a specific tool or technology.  Your obligation is to teach the risks of that technology.


Want to be good at programming (C++) and then start learning game development, where should I start?

How do you eat an elephant? One bite at a time.

First, learn how to properly code in C++.  This can be done by reading "The C++ Programming Language 4th edition" by Bjarne Stroustrup (The creator of C++) and coding at the same time; that is, while you read the book.  The key word here is "properly", though.  The following is a very accurate quote about C++: "In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg."  Improper use of the "new" keyword in C++ can lead to big problems.
This one actually got me, since I had a Java background prior to learning C++.

Second, learn about game development.  This will involve learning about how to build physics engines and collision detection systems (using spatial data structures).  A little bit of knowledge on vector calculus can go a long way when developing a physics engine.  You will also need to learn computer graphics.  You can buy a book on OpenGL, which is a graphics library that you can use in C++.


How do you teach Theory of Automata / Formal Language Theory / Computation Complexity?

The course is often theoretical, taught like a math course, which it is, actually. In fact, my daughter has a doctorate in Philosophy and this was one of her doctoral courses since it relates to Epistemology.

There is actually more material than can be covered in a single course, I think. Formal language theory could be introduced as part of a Languages and Compilers sequence to separate it out a bit. This is how I taught formal languages so as to motivate scanners and parsers.

Automata and Computability is quite a lot on its own.

There is a third way to teach the course, actually, which is to teach the insights, rather than going through the proofs. What does it all actually mean if you look at it from a bit of a distance. What does it mean for problems to be equivalent?

But if you want to have a course that includes programming, you should at least look at JFlap, which is a system for teaching the course and was developed by Susan Rodger at Duke. The system lets you simulate finite automata and can support either a theoretical or insight driven course.

There are a couple of old books, now somewhat hard to find, that I consider classics and excellent introductions. Both are by V. J. Rayward-Smith:

A First Course in Formal Language Theory

A First Course in Computability

These are both small books but are good for the basics and for generating insight. They are worth having, even if you don't use them as course texts.

There have been a lot of books published since I studied this subject. If I had to teach a complete course, the first book I would consider would be
Introduction to the Theory of Computation by Michael Sipser. I expect it would be clear and deep.


Course for the more practical aspects of software development

What you are trying to do is entirely laudable; helping your students to not only be better engineers, but also better hires, could help them in tremendous ways in the long run. However, since you are in a situation where your rating numbers matter very much to you, be careful that you always attend to your own professional needs as well. You would be in no position to help others if you simply lost your job.

Usually, people are okay with instruction that meets their expectations. Therefore, I agree with G. Ann that telling the students that this will be a part of the course is an important first step.

However, students signing up for a specific technical course might already have fairly fixed expectations before they enter your classroom, and, as what you are doing may differ from these expectations, you may find that your review marks still take a hit.  Thus, I might recommend two alternatives as well:

Develop a course in soft skills for developers. Include a full evaluation in order to address areas of weakness that you cannot reasonably cover in class (such as English), and spend the course time talking about the things that you can do. The advantage here is that students who sign up for the class will clearly want it.
Keep incorporating the material into your regular coursework, but make some of it optional for students who want it. And, as already said, always pay very careful attention to setting the expectations of your students with clear communication.

It sounds like your circumstances may preclude you from doing this sort of work if it causes a hit to your salary, so you may need to carefully monitor the effects of taking these changes, and communicate with your own administration to be sure that any temporary drops in your numbers will be understood correctly (eg. you won't lose your job).

Good luck!


Teaching Revision (Change) Control Systems In High School CS Classes

I agree with the CSTA Standards that revision control is an important skill by upper high school.  My school has a GitHub account and it is good for both revision practice and for using Agile boards for task management, which is an important methodology for students to know as they move to college.  I think there is value in either GUI or Command Line knowledge.

Here are some resources about Agile in Education:
https://www.agileineducation.org/examples.html

I like this resource for revision control:
https://betterexplained.com/articles/a-visual-guide-to-version-control/

The main ideas are backup/restore, synchronize (sharing resources with multiple people), tracking changes, sandboxes, branching, and merging.


Strategies for independent learners to identify gaps in their knowledge

First off, it's worth mentioning that everybody has these "blind spots" or gaps in their knowledge. Nobody can know everything, and some of the smartest people I've met are very open about that fact. I think a big part of being a good programmer is being comfortable with the unknown. What makes a good programmer isn't that they can write code, it's that they can learn how to write code.

In that regard, a self-learner already has a lot going for them. Because it's not really about memorizing stuff: it's more about the ability to do research, consult documentation, try stuff out, and see what happens. So the best thing somebody can learn is the ability to learn, if that makes sense.

I'll also say that for me, the thing that really took my knowledge to the next level was when I started answering questions. So I'd say your recommendation of checking out posts on Stack Overflow is on the right track, but I'd encourage novice and intermediate programmers to go a step further and try to answer questions as well. If Stack Overflow seems overwhelming (it was for me at first), then maybe join a forum and start answering questions there.

If you're only familiar with if statements, then start answering questions about if statements. Eventually you'll see a question that also involves a for loop, so to answer that question you do some research on for loops. Then you start answering for loop questions, and eventually come across a question about functions... That's a contrived example, but the general flow is pretty much exactly what I experienced. Even after a formal education, it really opened my eyes up to how much I didn't know!

Find a community, share your work, talk about programming. This is one way the gaps get filled in with a formal education, so it stands to reason that this would help with a self-learner as well.


Do Python and Java lead students to construct different mental models of memory?

I am not aware that cognitive modeling of memory structures in early programming education has been directly studied, so anything that I say here is entirely speculative.  However, I suspect that the models themselves would somewhat depend on teacher presentation, and would otherwise be relatively stable.

Take negative indexing as an example.  A reasonable initial cognitive model for a list would be some sort of cycle.  If it is later explained as an array with indexing performed with a modular operation, then we have moved our conception to some sort of line.  When we even later explain about memory references and data size, then we can finish the picture as an array (line) of fixed size memory references, each pointing to a different object in the heap.

There are only so many simple physical shapes that we can use to represent these ideas.  Which actual conceptualization a student takes will depend on their maturity in the subject matter and on how the data structure is presented by the instructor.  I don't see any reason to believe that the initial choice of language would have any substantive, lasting impact on these cognitive models as the student matures in their understanding.


The two general approaches to teaching OO that I've seen are "objects first" and "objects last".  Objects first takes the notion that, since we are teaching OO, we should start with instances, APIs, method calls, and inheritance.  (See Greenfoot as an excellent start to an objects-first curriculum if you are interested in exploring this approach.)  Eventually, you start to delve further into the nitty-gritty of the language, adding in arrays, loops, mods, etc, etc, etc.

Objects last follows the historical developments more directly, teaching imperative programming without OO first in order to highlight some of the thought process that went into developing OOP in the first place.

If you are taking an objects-last approach to your course (and it sounds like you are), then methods naturally fall before objects, and need to be included.  Methods were an important development for both code clarity and code reuse.  Though it's true that everything will need to be static at first, you can either leave this in as a temporary magical incantation, or make note of it as something exciting that will come later, and that about two-thirds of the way through the course, you will flip everything on its head, and those static markers will largely go away.


Show then how the loop can be unfolded into a while loop:
int i = 0 // Step 1
while (i< 100) { // Step 2
    // Do something
    i++ // Step 3
}

Explain that the order is derived from that unfolding.
You could start out by only teaching while loops, forcing them to make these while loops with iterators, then showing that for loops are a condensed of those while loops with incrementing variables.


I don't think the concepts behind generators, sequences and iterators are too difficult to grasp if you're clear on what exactly they are.

The 'old' range(n) function of Python 2 just produces a list of numbers:

[0, 1, 2, 3, ... , n - 1]

You ask it to give you a list of numbers from $0$ to $n - 1$, and it gives you a list.

The new range(n) doesn't do that. Instead, it makes an object that knows the start, end and step that you asked for... but it doesn't give you a list! This object will, however, give you the next element of the sequence if you ask for it.

Running list(range(n)) specifically asks for the list of all the integers, but in the vast majority of cases, you don't need the list, so there's no point making it and storing the whole thing in memory.

Imagine you wanted to print the numbers 1 to 1000. Python 2's range() would generate every number up front, before you can begin iterating. Clearly, this is very wasteful and pointless; it's much easier to work out each number at the end of the iteration, and doesn't require nearly as much memory.

However, I suppose that the merits of the feature aren't really relevant or important to absolute beginners; it's better that they gain some understanding of how to use the feature before understanding the merits behind it. Instead, consider explaining like this:

Iterables (such as range and zip) only do work when specifically asked (they're lazy — if your students have had any exposure to functional programming, that might be familiar)
Generally, being lazy makes things faster, because you don't do unnecessary work (e.g. in case you quit the loop early).
If you specifically need the whole list, you can ask for it with list(iterable) — but this is usually not as common as just iterating through with for.

If your students know Python 2's xrange, they'll find range simple to understand.


Pedagogical issues with Stack Implementation

Actually, the code is terrible, but I don't think its purpose is to illustrate a stack so much as to illustrate in a very rudimentary way how heap allocation works. (Worse than "terrible", it isn't "pythonic").

But you are wrong about the efficiency. Only the initialize function is O(n). Push an pop are O(1) as should be obvious.

But no serious code should print as a solution to a failure condition. The program itself should fail in some predictable way. Likewise no general implementation of a stack should hard code the maximum size. As such, this code teaches very bad programming habits.

The reason I don't think it is intended to represent a stack structure is the tuples that are returned from push and pop. Normally push is a mutator returning nothing and pop is an accessor returning only the top value in the stack.

Also, a stack as an abstraction should encapsulate the free list pointer (i.e. next free slot if any) and this reveals it.

The capitalization of variables is also oddly done for a Python program.

I agree that it is hard to follow, but that is a consequence of the above.

One thing positive that I will say about the code and how it might be actually valuable pedagogically, has to do with a philosophical interpretation.

When you modify a stack (or anything, really), one way to think of it is that you have a different stack - a new thing that didn't exist before. This code emphasizes that view of mutation. So to push onto a stack, you supply a stack, etc, and you get back a stack. A stack goes in and a stack comes out, a conceptually new thing.

So, it works if that is your main lesson, but less so as a stack per se.

But it is valuable only if you want to emphasize that view of mutation. But this is at odds with the normal (philosophical) view of an encapsulated data structure - that its identity is maintained in the face of change.

However, it is valuable for students to consider both views as different programming languages stress one over the other. Haskell, for example, has the "new value" idea built in rather than the "modified value" that you normally see in OOP. In Haskell if you push onto a stack, you get back a stack.

I'll also note that there is a Pedagogical Pattern called Toy Box that suggests that one can introduce a complex topic with a trivial implementation that get across key ideas without going into the complexity. While I might prefer simpler code to show how a heap grabs blocks but must know where they are, this code might be considered an example of a Toy.

Another pedagogical pattern is called Spiral and implies that teaching can introduce simple versions of complex topics early before students are ready for the full explanation. Then later, when it is time to learn it in detail (another loop in the spiral) they have been primed to integrate it into their thinking.


Distance or Part-Time Graduate/Doctoral Study

Georgia Tech announced an Online Master of Science in Computer Science degree in 2013, which has received very positive press. You said you don't want MOOCs because they don't "provide a solid, recognized degree." Georgia Tech's degree is solid and reputable.
According to a 1996 New York Times article:

With one of the top 10 computer science departments in the nation, according to U.S. News & World Report, Georgia Tech had a reputation to uphold. So it made the online program as much like the residential program as possible.
Charles Isbell, a senior associate dean at the College of Computing, helped lead the effort. Mr. Isbell has a Ph.D. in artificial intelligence and machine learning from M.I.T., and he teaches those subjects at Georgia Tech.....
In theory, on-campus programs offer direct access to professors and peers. Mr. Isbell began noticing differences in that respect between his residential and online students. He was interacting much more with students who had never set foot on the Atlanta campus.
“I never see students at my office hours,” he said. A few linger after class to ask scheduling questions, but that’s about it.
Many of the thousands of online students, by contrast, are constantly interacting on a website set up for that purpose, where Isbell can log on and help. “I can jump in and say: ‘No, you should be thinking about this,’ ” he said. “I spend more time helping them with assignments online than I ever do on campus. The experience for the students and for me is much richer online.”

This seems to provide the desired interaction with professors, albeit online.
While it is not a research master's, it should put someone in a good position to apply to PhD programs.
Update
Commenters have correctly pointed out that this is not a research Master's, and a Master's degree is not needed to apply to PhD programs. Thus, it is not a perfect fit. It is, however, the only highly reputable distance CS grad program of which I am aware.


Testing students on recursion - tracing by hand

No

This may be a good way to test understanding of function calls, and the stack. However I don't think it helps much with recursion. As when we design we need to abstract. To do this we need to be able to think without having to keep all of the detail in our heads. We need to focus only on externally visible behaviour, not internal details.

Yes

Having said that. I think it could be useful to look at the stack, if we are considering the consequences of different algorithms, and recursion patterns.

For example both of your examples, the recursion only reduces by one. Therefore the recursion depth is O(n). If you do not have tail-call optimisation then this could lead to a stack-overflow.

Nether of you examples would allow for tail-call optimisation:

The first is not linearly-recursive, but as long as the input data is small, would not be a problem.
The 2nd, has all of the complexity in the return path, and in practice n could be very high. This would be a problem. This example could be rewritten to allow for tail-call optimisation.

Note: Java, C#, Python … do not have tail call optimisation (I heard Java may now have it for direct recursion). C, and C++ may have it (gcc does). Scheme and all functional languages do have it. If your language does not have it. Then a tail-call recursive function can be re-written using the trampoline pattern.


How to phrase questions about spotting design issues in programs

It is true that these issues can be problematic in some cases, however, this depends on the context and the usage of the class.

The "design problem" that you were hoping they would find also depends on the context and usage of the class. We have no idea whether the users of this class are obeying your JavaDoc. In fact, I could see an argument that your "design problem" is invalid because anybody who violates the JavaDoc is going outside the bounds of your design in the first place! Compare that to the functions with no JavaDoc, and honestly I'm more convinced by your students' answers than I am of your intended answer.

Asking "what is wrong with the design of this class" is too broad. You need to provide more context: perhaps provide the UserSystem class and then another class that uses it incorrectly (by creating a new UserSystem instance for every user, for example), and then ask what the design problem is in that code and how it could be prevented in the future.

If you want a specific answer, you need to ask a specific question. All of the answers your students provided sound perfectly reasonable to me.


Is it necessary or advisable to teach text-based input and output in a non-CS intro programming course?

I've been coding for 20 years in non-cs fields. I've worked on several >100k line code bases.

Almost every program I write comunicates with the outside world via text, usually a file hand or file-handle-like connection to stdin and stdout.

In addition, I also almost exclusively  do my debugging via print statements (or output to debugging logs).

IDEs and graphical debuggers can be very useful tools, but they can become a crutch that excuses the student from thinking. Print statements encorage the student to really reason about the logical and flow of their program - they must be able to hold the program in their mind and understand where it is going to be important to output a variable state, or just ping "here" to the terminal.

Now obviously I wouldn't insist that students must do this when working on large, complex code bases, but while they are making simpler things, things where holding the whole structure in your head is possible, then I think it is good for them.


The Wirth formula, Algorithms + Data Structures = Programs is still valid. It is also complete. A program is nothing more than algorithms acting on data structures. That formula does not make explicit the difference between a bad, error-riddled program and a good, error-free efficient program. Looking at the formula, however, can show how to improve the first and make it into the second.

Stating that programs are built of exactly two components, data structures and algorithms, means that the only way to improve a program is to improve one, or both, of its components.

  Algorithms + Data Structures = Programs
  Sloppy Algorithms + Mediocre Data Structures = Buggy Programs
  Better Algorithms + Data Structures = Better Programs
  Excellent Algorithms + Efficient Data Structures = Superior Programs.

The Science part of Computer Science in programming is finding the way to create the better, or excellent, algorithms and develop the efficient data structures. That's where the skills, whatever the instructor wants to focus on, come in to effect. Design patterns help to sort out the options, and provide an established pattern to follow when creating a new algorithm or data structure. Unit testing helps to validate the operational correctness of the written code. Low level knowledge of the target system may allow the coder to increase efficiency, and low level knowledge of the chosen language might allow the coder to utilize "tricks" or "quirks" built in to the language (be they bugs or features is unimportant).

Bottom line is that the only way to make a program better is to make its components better. There are only two components to work with; data structures and algorithms.

  Will you tell students that Algorithms + Data Structures = Programs now(21st century)?

Not only will we tell students that, we should have that on the door lintel
of every classroom and lecture hall where programming is taught.