Encouraging Critical Thinking On Programs Before Students Write Them

I frequently teach our CS1 class (taught in Java), and have noticed a problem with critical thinking/planning skills on programs of any substantial size. This seems to be related to two problems: (1) not fully internalizing what tools are available to them (e.g., String methods like charAt, length), and (2) not thinking through/planning ahead/leaving enough time when writing their program. I would like to foster these skills, but I am at a loss. This is a class of complete programming novices. Most students have no prior experience. Some students have a little prior experience in some OOP language, but it is usually self-taught with little regard to breaking down larger problems.

The first problem seems easy enough (encourage students to write a glossary of tools we learn with examples - we only require knowledge of a handful of methods), but students rarely do it. The second problem has been a white whale of mine for the past year and a half. I teach activity diagrams and model problem solving in class, but when I try to require activity diagrams as part of program submission, I mostly get students who solve the program first, then reverse engineer their diagram. I would love to require their diagrams to be submitted ahead of time for feedback, but I do not have the time to grade it before the program is due. I do have some students who show up to office hours and never pull out their computer - they just draw diagrams with me, and they are fantastic students. But, they are the minority.

I fully believe these skills are just as important, and perhaps more important, than eventually writing that correct program, but the program of course is what they need to be able to do. How do I teach/evaluate these skills effectively in class in light of all the other material that needs to be covered?

• @Buffy Yes, true novices. I've updated my question. – cryptic_star Oct 19 '17 at 14:35
• I would say one reason I never did pre-planning for programs in college, was that we were never given programs hard enough to require it. Most were small programs to teach a principle or algorithm. – Confuzing Oct 19 '17 at 22:30

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.

• This is fantastic! I appreciate this approach, particularly the in-class guidance and pair programming that then leads to a lab. I feel like this is what I have been missing, this integration - we do one example in class, another in lab, another for an assignment. In response to your comment about when to teach this, I might ask a different question about that. – cryptic_star Oct 20 '17 at 16:24

(1) not fully internalizing what tools are available to them (e.g., String methods like charAt, length)

[...]

The first problem seems easy enough (encourage students to write a glossary of tools we learn with examples - we only require knowledge of a handful of methods), but students rarely do it.

I don't blame them. It can be very hard for novices to know what's important. You're throwing a ton of information at them (even if it doesn't seem like a lot to you), and it's hard to know what's going to be useful ahead of time. Even if I do know what's important, coming up with a glossary seems pretty tedious and honestly seems like one of those things that you only have to do in school and would never have to do in the real world. (Not trying to criticize, just trying to understand your students' perspectives.) So, my suggestion is:

Instead of having students come up with a glossary, give it to them.

This can be as simple as a list of classes and functions that might be useful for the current assignment. Don't just send them to the Java API, as that can be very overwhelming to novices.

(2) not thinking through/planning ahead/leaving enough time when writing their program.

I teach activity diagrams and model problem solving in class, but when I try to require activity diagrams as part of program submission, I mostly get students who solve the program first, then reverse engineer their diagram.

Diagrams are useful for very high-level system engineering (frontend X calls server Y which fetches from database Z), but aren't very useful for the kind of code that novices will be writing. See also:

Instead of using diagrams, you might have the students break the problem down into smaller steps and write those steps out in English, or pseudocode. The real goal is to get them to break the problem down into smaller steps though.

You might go a step further and break the problem down for them, at least for the first few assignments. Break the assignments into steps, or split the project up into multiple assignments. Tell them what you're doing, so they see the process and eventually do it themselves.

I'd also recommend checking out Processing. Processing provides a simplified reference which helps with the first problem, and it's visual which can help with the second problem. (It's much easier to reason about stuff you can see instead of abstract concepts.) There are quite a few questions and answers on this site about using Processing in the classroom, so I'd start by searching here.

True novices

If the they are novices, then you may be asking to much, to get them to write large programs from scratch.

More useful exercises may be:

• Parsons problems: Give them «all the right code, but non in the right order» Works well with about 4 lines of code.
• Contribute to a bigger project: Have them work on something that is already written, and add new features to it. This way they «learn to write, by reading».

The value of planning

If you want them to plan, then they have to see the value of planning. I think that we often do too much up front planning (I have worked on projects, where we did months of planning, then on the first day of coding, we learnt so much, that our plans were obsolete). We need to plan, but we need to do it «just in time», and planning has to be useful. If it is not, then we should plan a different way.

Therefore show your students a variate of planning techniques, that they can choose from. Tell them that the technique that they use, will depend on the situation, and on their preference.

Techniques should include:

• linguistic: e.g. pseudo code / descriptions / rewrite the problem statement, in your own words
• visual: diagrams / colour
• physical: acting, role play of the software / real world objects
• collaborative: talking/acting/whiteboard
• chaotic: brain storming / simultaneous writing