<p>Challenge them with something they'll have to do once they're working -- give them some code that uses the technique you want to teach them, and have them make a change of some sort. Or show them code that DOESN'T use the technique, require some change to be made to it, with requirements (complexity, line count, whatever) that drive them towards the technique you want them to use.</p>

CC BY-SA 3.0
2018-04-12T14:55:10.933Z
2018-04-12T14:55:10.933Z
Rob Crawford
<p>When I used to be a student learning C++, my teacher gave us a very open subject with only a subject : Star Wars (it was for the year of the release of the new series). The only consign was to use at least several C++ functions. We had a minimal list of the functions and structure we had to use, and could add any specific function we would have liked. </p>

<p>We had two different delivery of the project, first one was for the teacher to point out some place where we could have coded better (using more C++ built in function) and the second was for the final delivery with proper coding. </p>

<p>Honestly this was a very challenging way of giving us a project, every body get deeply into it and we ended up with very pretty and satisfactory programs. </p>

<p>I guess this kind of approach is very appreciated but the teacher has to give a huge amount of time in order for that approach to succeed.</p>

CC BY-SA 3.0
2018-04-12T10:16:31.727Z
2018-04-12T10:16:31.727Z
YCN-
<p>The persons who could answer your question best are the students themselves. Why don't you ask them?
Seriously though, there might be a host of reasons why a given person is novelty-shy. </p>

<p>First of all, however pleasant knowledge might be, any learning process is intrinsically painful, so some reluctance is only to be expected from any pupil or student at some point.
Besides, computing is extremely abstract. Maybe not as much as maths, but still it takes a bit of time before you can really create something beyond learning basic vocabulary. For those who are passionate about the subject it's a breeze. For others, that initial period requires a leap of faith.</p>

<p>Maybe some of your students are simply not interested in programming, in which case they will likely try and avoid the chore of learning more unpleasant stuff.<br>
Or maybe they are struggling to keep up and feel too insecure to tackle new concepts.<br>
Or maybe they are having it too easy and don't see the point in learning new tricks if the problems they are given can be solved without.</p>

<p>Depending on the cause of their reluctance, you might for instance:</p>

<ul>
<li>openly discuss their lack of interest and make a deal with them: do the bare minimum honestly and I'll try to make it as painless as possible</li>
<li>work on the student's self confidence. Try to find a couple of relays among the most advanced students that can spend some time helping others in group projects.</li>
<li>give them something worth tackling the new concepts. Ideally a project where old tricks either don't work or are too impractical.</li>
</ul>

<p>As a student, my best memories are from classes where I felt I belonged. Not necessarily as a successful student, sometimes quite the contrary. By "belong" I mean I knew what to expect and felt in agreement with the teacher - even if that was sometimes limited to agreeing to disagree :)<br>
I loathed electronics and had disastrous grades, but I managed to strike a deal with a few teachers who would clearly state what they expected of me and respect my lack of interest.
I also had a couple of teachers who took the time to devise problems for advanced students and kept us interested while the rest of the class struggled with system programming basics.
Plus a couple of teachers who helped me overcome an initial reluctance to dive into some domains.
Lastly, I remember one college teacher to whom I am still grateful today for opening a window to all that marvellous literature. Decades later, I met again with a college friend, and to my consternation she told me these French courses had bored her silly :). It took me a real effort to accept the idea that these lectures I had found so captivating could have been perceived as plain chores by some!
So any teacher's trick is likely to work magnificently with one student and fail spectacularly with another.</p>

<p>I tried to emulate that behaviour in my few teaching experiments, with mixed success to be honest, but at least I always avoided the pitfall of being a one trick pony.</p>

<p>Always try and listen to what the students have to say (if anything), that would be my first and last advice.<br>
If they know you sincerely try to take their needs into account and expect reasonable things of them - within the limits of what you are expected to teach them, of course, they will usually go to great lengths to be worthy of your respect and fulfil your expectations. At which point problems like the one you evoke in your question cease to be major issues, in my limited experience.</p>

CC BY-SA 4.0
2020-01-12T00:34:37.240Z
2020-01-12T00:34:37.240Z
kuroi neko
<p>I have spent a lot of time on chatrooms/forums helping people with their programs, and over time what I've found is:</p>
<ul>
<li><p>Provide partially written code to help them feel comfortable with it. Be sure the code you give is clear <strong>and concise</strong>. It needs to focus on the point and avoid being more confusing than it must be. (I find this helpful for people asking for help.)</p>
</li>
<li><p>Give solid reasons for <strong>why</strong> they should use something. If you just tell them &quot;this does X&quot; without explaining why they would want something like &quot;X&quot;, then they'll never know when they should use it over something else. If you're teaching these advanced concepts, there should be a reason you're teaching them.</p>
</li>
<li><p>Make sure they try it. For many, code snippets during lectures are nothing more than code snippets. People tend to have more attachment to their own code because they understand their own code more than a stranger's. This means they aren't really understanding why the code you're showing them actually matters to them.</p>
</li>
</ul>
<p>Now, that's cool and all, but how should you actually integrate this advice into a classroom setting? I'm not a teacher, but here's some ideas:</p>
<ul>
<li><p>Provide partially written code alongside assignments as <strong>hints</strong>. Whether or not a student uses it is up to them, but it'll encourage them to think about stuff like &quot;where should I use this?&quot; and &quot;how should I fill this in?&quot;.</p>
</li>
<li><p>Make it obvious how the given reasons for using something over something else would apply. If you're going over lists vs sets, then even have them implement something simple using both ways so that they can see the difference first-hand.</p>
</li>
<li><p>Give them a reason to look back on their own code. For example, have them do peer reviews after they finish the assignment. Most students won't look at their code after they've turned it in, so they don't learn from their own mistakes.</p>
</li>
</ul>

CC BY-SA 4.0
2022-05-12T13:30:58.383Z
I like your opening point. Clear and Concise. I encounter a lot of examples where the point is buried is huge examples, or hidden behind obfuscated code. Python is particularly horrendous when it comes to hunting down examples as everyone goes off in their own confusing direction.
codingCat
CC BY-SA 4.0
2022-05-06T06:37:40.340Z
2022-05-06T06:37:40.340Z
Simply Beautiful Art
<ol>
<li>As mentioned in a comment: start with high level constructs when possible.</li>
<li>In some assignments I give students the main program, and then tell them, write the data structures and functions that make this work. That way you're forcing them to use the high level constructs, and maybe they'll see that the shorter/more elegant expression is preferable.</li>
</ol>

CC BY-SA 4.0
2022-04-26T17:28:18.577Z
2022-04-26T17:28:18.577Z
Victor Eijkhout
<p>I'm afraid that there is no single silver bullet.  The problem you've pointed to is very real, and isn't limited to students.  All of us tend to stick to our own familiar toolsets because, well, it's easier.  We know how to use them already.  </p>

<p>Enter the Motivating Example.  This mythical thing makes a new topic so useful that the new topic is practically a requirement.  Want to motivate recursion?  Try having kids determine the file-size of a folder (including its sub-folders).  Want to motivate methods?  Try giving a main method that calls them, and ask the kids to create the code that will make everything work.</p>

<p>Finding a great, motivating example feels like a search for hidden treasure; it is painful and slow.  You're seeking something of great value, and it's hard to know where to look.  To make matters worse, a good motivator for one teacher may not work for another, because what makes a motivating example work is intricately tied into both the broader curriculum and what sorts of things the teacher emphasizes within the classroom.</p>

<p>And once found, they are indeed treasures!  Clean, motivating examples make the value of a topic immediately apparent to students.  Resistance melts away, and is replaced by enthusiasm for the new tool that is now making their life easy.</p>

<p>Sometimes I spend weeks trying to find a good motivator.  I've found that teacher communities (such as this very one!) can be great sources of inspiration for them, as can algorithms books.  Or, as <a href="https://cseducators.stackexchange.com/users/1896/kevin">Kevin</a> pointed out in a comment (before it was deleted):</p>

<blockquote>
  <p>As far as finding motivation is concerned, it may be helpful to look into the history of the construct. For example, foreach used to be called "the iterator pattern," and even appears in the GoF book under that name, before there even was a foreach loop. So foreach isn't about simplifying the code so much as it is about abstracting away the implementation details of "get the size of the container" and "get the nth element" into a single opaque accessor. That suggests that a motivating example might begin by introducing trees, showing traversal code, and then contrasting it with an array.</p>
</blockquote>

<p>Even with all of these tools, there are no easy guarantees. I sometimes have to simply wait for my <em>"Eureka!"</em> moment, and teach the best I can in the meantime.</p>

CC BY-SA 3.0
2018-04-10T15:40:11.577Z
2018-04-11T02:18:56.540Z
2018-04-11T02:18:56.540Z
Ben I.
<blockquote>
  <p>What are healthy, productive ways to encourage students to progress to more advanced constructs as opposed to staying with the familiar?</p>
</blockquote>

<p>I would say that it's the educator's main goal to showcase the necessity of using these constructs.</p>

<p>In general (even beyond CS), you should only take the more complex option when you <strong>need</strong> to. This is the core essence of KISS.</p>

<p>Therefore, if you want your students to use a more complex alternative, you need to present them with use cases where the simpler option simply doesn't work (well).</p>

<blockquote>
  <p>For example, when they are taught arrays, they continue to use individual variables when they are able.</p>
</blockquote>

<p>You've indirectly answered your own question: <em>"when they are able"</em>. Give them an assignment where they are unable to use individual variables.</p>

<p><em>A very simple example is an application that builds an array of 20 names (supplied by the user, one at a time), after which the program generates a sorted comma-separated list of names.</em></p>

<p>I don't see a way to sort these names by using individual variables. Even if some (hugely contrived) approach exists, it will take <strong>more time and effort</strong> to develop compared to a simple array sort.<br>
If <em>some</em> students use the arrays; the hardheaded others will see that their peers find the task much easier than they do, which will naturally incentivize to do the same.</p>

<blockquote>
  <p>After working extensively with arrays, they don’t want to move to using built-in collection types that offer more flexibility and behavior.</p>
</blockquote>

<p><em>A very simple example is an application that builds a list of names (supplied by the user, one at a time) until the user says "stop", at which point the program generates a sorted comma-separated list of names.</em></p>

<p>I don't see a way to do easily solve this with an array. Since you can't know how many names will be supplied, you can't definitively declare your array (you'd have to constantly recast your array to a bigger size).<br>
If they use a massive array to begin with, then they should be docked points for irresponsible memory management (for the same reason that you'd dock points for memory leaks).</p>

<p>While continually recasting the array is not impossible to do, it is contrived and it will take <strong>more time and effort</strong> to develop compared to using a list.<br>
If <em>some</em> students use the lists; the hardheaded others will see that their peers find the task much easier than they do, which will naturally incentivize to do the same.</p>

<blockquote>
  <p>When introduced to the foreach loop, they continue to use bounded for loops.</p>
</blockquote>

<p>The problem here is that every <code>foreach</code> loop can be written as a <code>for</code> loop. There is no real benefit to using a <code>foreach</code> over a <code>for</code>, the only benefit is the ease of reading/typing.<br>
A similar example would be LINQ, which is mostly used as shorthand for a foreach loop. In essence, every (in-memory) LINQ query can be written as a manually developed <code>for</code> loop. That's technically not wrong (it only affects readability and increases effort required; it doesn't functionally matter).</p>

<p><strong>Currently</strong>, your students prefer to use a <code>for</code> loop because it takes them less time to use something they know, compared to something they don't yet know (<code>foreach</code>).<br>
I would temporarily ban the use of the <code>for</code> loop (or force them to use <code>foreach</code>, same thing), to force your students to familiarize themselves with the <code>foreach</code>. After a few (iteration heavy) assignments, they should be familiar with how to use a <code>foreach</code>.</p>

<p><strong>In the future</strong>, when they are familiar with both the <code>for</code> and <code>foreach</code>, it's up to them to decide what to use. Most likely, most will pick <code>foreach</code> because it's easier and less prone to developer error.<br>
But the traditionalists who revert to using <code>for</code> loops are not really wrong (though they may be docked some points for readability, if you grade readability too).</p>

<blockquote>
  <p>It is sometimes difficult to impress upon beginning programmers the usefulness of “new” constructs, because the exercises and programs they are capable of undertaking do not sufficiently demonstrate the power and usefulness of those constructs.</p>
</blockquote>

<p><strong>This is a contradiction</strong>. If you don't think the students are capable of handling a problem of this complexity, then you shouldn't be trying to teach them the solution (to a problem that they can't grasp).</p>

<p>In other words, if you want to teach them something, <em>of course</em> you're going to have to show them a situation where it is relevant to use the solution!</p>

CC BY-SA 3.0
2018-04-15T00:32:07.823Z
*I don't see a way to sort these names by using individual variables.*  Hard-coded sorting network where every compare-and-swap is specified separately (hopefully with the compare+swap wrapping in a function call).  A sorting network for 17 elements can be only 71 comparators according to https://en.wikipedia.org/wiki/Sorting_network, so 20 elements is at least plausible to write out in the source code, and I think there are sites online that can generate them.  Anyway, totally implausible for beginners to actually come up with, but in other contexts it's not totally unreasonable.
Peter Cordes
CC BY-SA 3.0
2018-04-11T13:35:01.510Z
2018-04-12T07:31:20.770Z
2018-04-12T07:31:20.770Z
Flater
<p>As a student, I can say the appeal to my free time is pretty powerful motivation.  I have spent hours implementing features already present in a language only to feel foolish when I realized my folly. </p>

<p>For example I had an assignment where I spent a good chunk of time implementing my own (very flawed) version of a HashMap.  I have some the same thing for a TreeSet as well. </p>

<p>Many of my peers will cling to an ArrayList no matter what the problem presents.  They are just comfortable with using it and prefer it over any other structure, even when that means a lot of extra code they have to write.</p>

<p>Elegant solutions are appealing to some students due to their brevity, which can be seen as clever or almost getting away with something.  That may motivate some, especially the lazy ones.  Others may just appreciate how elegant the solution is for it's open merit.</p>

<p>I think some students will stick with Array and ArrayList until they are basically forced to not use them.  No matter how clever or elegant they could potentially be.  Fostering a culture that embraces failure may help overcome that.</p>

<p>I have found online interview prep sites have done the best at nudging me to use constructs I would have otherwise ignored.  Maybe sell them on the idea of interview prep? Can't use an Array for all of those, just flat won't work and that is a time you definitely want something to work!</p>

CC BY-SA 3.0
2018-04-10T18:41:13.307Z
2018-04-10T18:41:13.307Z
red_squiggly_line
<p>I'm not sure the following will work for all students, but I remember this being a transformative "aha" moment in my own education:</p>

<blockquote>
  <p>Show them <em>your</em> code.</p>
</blockquote>

<p>Preferably contrasted against a functioning but god-awful student submission from the previous term. Show them how its an order of magnitude simpler than their shotgun-formatted needlessly complex mess. Show them what compactness and elegance look like. In freshman?sophmore? CS prof assigned us to write a CLI memory card game. I like many of my peers did this big elaborate class hierarchy and/or held the "cards" in nested data structures with nested loops. The prof's code was IIRC &lt; 20 LoC: he used a flat array of structs with the modulus operator to determine the "row". I learned that day what Torvalds meant by "taste", namely the ability to know when to use "industry best practices" and when to just write simple code even if it's less flexible.</p>

<p>I realize that's almost the opposite point than the one you're driving at (i.e. getting them to use the more advanced constructs) but <em>show in your code that they exist for a reason</em>. If you can replace 50 lines of tedious, error-prone buffer manipulation with a built-in collection and an iterator/forEach that takes less than 10, <em>believe me</em> the smarter ones will notice. And when they collaborate with their peers on group projects peer pressure will help with the slower ones.</p>

CC BY-SA 3.0
2018-04-11T23:32:42.093Z
Time pressure probably helps even more than peer pressure. ;)
jpmc26
CC BY-SA 4.0
2018-04-10T19:46:30.020Z
2020-01-08T23:53:07.483Z
2020-01-08T23:53:07.483Z
Jared Smith
<p>There are a number of facets to this question. But the first thing you need to remember is that students (like anyone) will tend to apply solutions that they are most familiar with. In the student context that means, often enough, the things they learned earliest and have been practicing with the most. This effect is most pronounced on hard problems that may not have an obvious (to the beginner) answer with the new techniques.</p>

<p>For the above reason, I prefer to teach a thoroughly object-oriented course to students, having them build classes and write and use methods (some of mine, some of theirs) before they seen things like primitive data (int, double...) or low-level program structure (if-while...)</p>

<p>More generally, I advice against a strictly bottom up approach to teaching programming, in which low level constructs are taught first with a lot of emphasis on language primitives. It takes quite a lot of scaffolding, however, but my students start their programming learning in a world that I construct, not a "naked" language. So, when they come up with a hard problem and need to "fall back" on what they know best, it will be something like writing a test for something or an interface for structure, rather than just trying ad-hoc methods. </p>

<p>The reason for this is that ultimately I want to teach them to be OO programmers and when they get a new problem, I want them to think in a thoroughly OO way. So they will naturally write 3 line methods rather than 30 (or 300) liners. If I try to teach them procedural programming first, that will be their fall-back and I want to spare them that pain.</p>

<p>However, if you don't want to employ such an "extreme" change in the course, there are other things you can do. </p>

<p>One method is to employ a Spiral approach in which a lot of topics are introduced early with only relatively shallow usage in the first loop of the spiral and then repeatedly going deeper on each while you introduce new topics also. This, rather than <em>completely</em> explaining all the nuances of any given topic. (<em>Spiral</em> Pedagogical Pattern)</p>

<p>Another trick you can use, whatever your overall syllabus, is to introduce a rather large program early on that shows a fair number of important topics. One way to do this is to give them a program that is essentially correct, but which you have "broken" in a few ways. Their assignment is to understand it enough to fix it up (<em>Fixer Upper</em> Pedagogical Pattern)</p>

<p>Ultimately, then, the answer isn't really to "encourage" them, but to structure the course itself so that the "higher level" topics come before the lower level ones. </p>

<p>There is really no reason why arrays need to be discussed before (Java) collections/lists/maps... Then the foreach construct becomes their fallback and you can later teach them the c-like $for$  loop as a possible way that foreach can be implemented. I'd rather they used the libraries in their code in any case, just as I want them to program within my original framework rather than riding bareback on the language. </p>

<p>If you introduce "deep" and "important" topics only late in the course then it is with <em>those</em> that they will have the least practice and experience. </p>

<p><strong>tl;dr: rearrange the course so that they get the most practice on the most important topics.</strong> </p>

CC BY-SA 3.0
2018-04-10T23:40:42.080Z
"The reason for this is that ultimately I want to teach them to be OO programmers and when they get a new problem, I want them to think in a thoroughly OO way" - isn't FRP the hot new paradigm nowadays?
Criticize SE actions means ban
CC BY-SA 3.0
2018-04-11T13:43:29.347Z
**This!**  Why is the OP teaching bounded *for* before *foreach*?
Martin Bonner supports Monica
CC BY-SA 3.0
2018-04-12T10:06:46.503Z
What you said is true if you want to build software devs or web dev that knows just enough for what their aim is to, but that doesn't include embedded dev for instance. If you don't understand the low level approach, I don't feel like people should use more advanced features. Or if they do use those collection they have to code them in the first place to understand how they work.
YCN-
CC BY-SA 3.0
2018-04-15T00:22:23.233Z
@YCN-: I personally love the low level stuff, but I think this advice sounds reasonable.  Getting to the point of understand how different collections work (like sorted maps vs. plain hashes vs. simple `std::vector`) requires some algorithm knowledge, and understanding efficiency is only truly possible with some computer architecture (caches) and assembly language (and how source compiles to asm).  Leaving these topics for later in the spiral makes sense: by the time you get to the implementation details and low level stuff, students will be ready to understand it better.
Peter Cordes
CC BY-SA 3.0
2018-04-10T14:52:32.037Z
2018-04-10T15:43:02.500Z
2018-04-10T15:43:02.500Z
Buffy
<p>Rather than trying to motivate the students, or the reluctant ones, to progress into using your new tool (<code>foreach</code> after <code>for</code>), and finding a new motivating example every time, try to motivate them to be self-interested, lazy coders.</p>

<p>Now that I'm under the <em>tar and feathers</em>, I'll explain. People like to find the <em>easiest</em> way, not the <em>best</em> way. Earlier postings reveal that you're in the teen-age world with your students, and they are no exception, if not the rule, to that thinking. Knowing that your students will have that natural preference for easy, use it as the motivation. "Quality is job one" makes a good slogan for a company, but isn't so good for motivation of students.</p>

<p>Borrowing from the world of sales, show the problem first, and the solution second. To progress from a bounded <code>for</code> towards a <code>foreach</code>, as an example, use the bounded version in a manner already natural to them that is possible, but problematic, against a collection that can be <code>foreach</code>-ed. Legitimately work out the checks and error traps and actually make it work. Once they've experience doing it that way, then you can present the "package" where someone did all that work, and more, when they created the <code>foreach</code>. All the traps, special conditions, etc., are handled, and all the work has been done, and debugged, for them.</p>

<p>The same approach can be used to <em>step-up</em> to any progression you choose. Under the hood in any chosen language the new tool might not be implemented using the old one. At least not now. Still, that's how they came to be created in the first place - refinement on a common problem and its solution creates the shiny new practice which becomes a tool. That's how we got structured programming to begin with.</p>

<p>The key is that the new concept is not presented as <em>better</em> programming, <em>better</em> presentation, or even easier to maintain, update, or fix later. Rather it's presented as a real solution, to a real problem, <em>right now</em> that makes less work <em>right now</em> for them. Less time on coding, now, means more time, now, to be with their friends, or do other <em>fun</em> stuff. After a couple rounds of that, once the light bulb goes on, they'll start actively looking for pre-baked solutions, and libraries will be their next target. That outlook will carry them well into the future, and could even encourage them to look at new languages, either new to them, or new to the world, for an <em>easy</em> solution to a problem.</p>

<p>Hence, they become self-interested, lazy coders. </p>

CC BY-SA 3.0
2018-04-12T22:50:53.420Z
I volunteer teaching 12-14 y/os and this a running theme: Yes, you can make a giant if/elif/elif/.../else block... but *I'm lazy,* so here is a much faster way to do it. By casting it in that way (and ensuring they are comfortable with using it), they tend to move over pretty quick.
TemporalWolf
CC BY-SA 3.0
2018-04-10T19:01:51.817Z
2018-04-10T19:01:51.817Z
Gypsy Spellweaver
<p>If you start with the most absolutely bone-simple programming concepts at the start, then as you introduce each more complex concept, it is obvious why it solves a problem that just could not be solved using the simpler stuff they already know: No number of separate variables will solve a problem that calls for arrays. No fixed size array will solve a problem that calls for expandable arrays, and so on.</p>

<p>Begin at the beginning, with things that could not be simpler or more obvious. Add one thing at a time, and show how it solves problems. Steam engine, gasoline engine, gas turbine, rocket. You just will never get to space with Jules Verne's coal-powered "rocket train".</p>

<p>If someone wants to stick to older concepts that won't solve a new problem, they plain old won't solve the new problem. They can't stick, they either go forward with either new concept, or they fail out. This is why we reproduce the development of programming as it occurred: no one ever gets lost trudging along in the well-worn path. They never ask why something is better than something else: they <em>know</em>. </p>

CC BY-SA 3.0
2018-04-11T14:08:43.330Z
2018-04-11T14:08:43.330Z
user4897
<p>In my experience, there are always students who are resistant to moving to more advanced constructs. They want to stay with what they already know. For example, when they are taught arrays, they continue to use individual variables when they are able. When introduced to the foreach loop, they continue to use bounded for loops. When they learn about functions, they resist modularizing their code. After working extensively with arrays, they don’t want to move to using built-in collection types that offer more flexibility and behavior.</p>

<p>It is sometimes difficult to impress upon beginning programmers the usefulness of “new” constructs, because the exercises and programs they are capable of undertaking do not sufficiently demonstrate the power and usefulness of those constructs.</p>

<p>What are ways to encourage beginning programmers to embrace more advanced constructs without penalizing them? I am looking for more "carrot-y" answers than "stick-y".</p>

CC BY-SA 3.0
2018-04-11T08:11:30.053Z
Some of it is teaching order: Do `foreach` before generalised `for`. Foreach is easier, and will be used 80% of the time in there future programs, so teach it first. Same for container classes. This is related to should I start high or low. Well start as you mean to go on. Students will value and use what they learn first.
ctrl-alt-delor
CC BY-SA 3.0
2018-04-12T08:56:08.323Z
Have something with a good reason to use more advanced constructs. With respect to premature optimization it may actually be a reasonable idea to use a few variables instead of an array, so your current premise may be wrong. Not every neat data structure must be used and people have different programming styles. To teach them to use an array show them a task which cannot be (reasonably) solved by introducing more and more variables.
allo
CC BY-SA 3.0
2018-04-14T21:23:57.950Z
People that progress from simple things at a slower pace, tend to practice the simple things more and better...
rackandboneman
CC BY-SA 3.0
2018-04-24T00:44:06.830Z
Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackexchange.com/rooms/76480/discussion-on-question-by-java-jive-what-are-healthy-productive-ways-to-encoura).
thesecretmaster
CC BY-SA 4.0
2022-04-29T06:48:36.200Z
Two things. 1, you can't teach curiosity. 2, if the students aren't capable of grasping programs where the constructs you're trying to show them are actually useful, then perhaps you are teaching them to run before they can walk?
Steve
<curriculum-design><student-motivation>
What are healthy, productive ways to encourage students to progress to more advanced constructs as opposed to staying with the familiar?
# What are healthy, productive ways to encourage students to progress to more advanced constructs as opposed to staying with the familiar?

(Asked by: username_0 on 2018-04-10)

In my experience, there are always students who are resistant to moving to more advanced constructs. They want to stay with what they already know. For example, when they are taught arrays, they continue to use individual variables when they are able. When introduced to the foreach loop, they continue to use bounded for loops. When they learn about functions, they resist modularizing their code. After working extensively with arrays, they don’t want to move to using built-in collection types that offer more flexibility and behavior.

It is sometimes difficult to impress upon beginning programmers the usefulness of “new” constructs, because the exercises and programs they are capable of undertaking do not sufficiently demonstrate the power and usefulness of those constructs.

What are ways to encourage beginning programmers to embrace more advanced constructs without penalizing them? I am looking for more "carrot-y" answers than "stick-y".

**Tags:** curriculum-design, student-motivation

> **Comments:**
> **username_1**: Some of it is teaching order: Do `foreach` before generalised `for`. Foreach is easier, and will be used 80% of the time in there future programs, so teach it first. Same for container classes. This is related to should I start high or low. Well start as you mean to go on. Students will value and use what they learn first.  
> **username_2**: Have something with a good reason to use more advanced constructs. With respect to premature optimization it may actually be a reasonable idea to use a few variables instead of an array, so your current premise may be wrong. Not every neat data structure must be used and people have different programming styles. To teach them to use an array show them a task which cannot be (reasonably) solved by introducing more and more variables.  
> **username_3**: People that progress from simple things at a slower pace, tend to practice the simple things more and better...  
> **username_4**: Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackexchange.com/rooms/76480/discussion-on-question-by-java-jive-what-are-healthy-productive-ways-to-encoura).  
> **username_5**: Two things. 1, you can't teach curiosity. 2, if the students aren't capable of grasping programs where the constructs you're trying to show them are actually useful, then perhaps you are teaching them to run before they can walk?  

---

## 12 answers

### Answer by username_12 on 2018-04-10. Score: 55

I'm afraid that there is no single silver bullet. The problem you've pointed to is very real, and isn't limited to students. All of us tend to stick to our own familiar toolsets because, well, it's easier. We know how to use them already.

Enter the Motivating Example. This mythical thing makes a new topic so useful that the new topic is practically a requirement. Want to motivate recursion? Try having kids determine the file-size of a folder (including its sub-folders). Want to motivate methods? Try giving a main method that calls them, and ask the kids to create the code that will make everything work.

Finding a great, motivating example feels like a search for hidden treasure; it is painful and slow. You're seeking something of great value, and it's hard to know where to look. To make matters worse, a good motivator for one teacher may not work for another, because what makes a motivating example work is intricately tied into both the broader curriculum and what sorts of things the teacher emphasizes within the classroom.

And once found, they are indeed treasures! Clean, motivating examples make the value of a topic immediately apparent to students. Resistance melts away, and is replaced by enthusiasm for the new tool that is now making their life easy.

Sometimes I spend weeks trying to find a good motivator. I've found that teacher communities (such as this very one!) can be great sources of inspiration for them, as can algorithms books. Or, as [Kevin](https://cseducators.stackexchange.com/users/1896/kevin) pointed out in a comment (before it was deleted):

> As far as finding motivation is concerned, it may be helpful to look into the history of the construct. For example, foreach used to be called "the iterator pattern," and even appears in the GoF book under that name, before there even was a foreach loop. So foreach isn't about simplifying the code so much as it is about abstracting away the implementation details of "get the size of the container" and "get the nth element" into a single opaque accessor. That suggests that a motivating example might begin by introducing trees, showing traversal code, and then contrasting it with an array.

Even with all of these tools, there are no easy guarantees. I sometimes have to simply wait for my *"Eureka!"* moment, and teach the best I can in the meantime.


---

### Answer by username_16 on 2018-04-10. Score: 27

I'm not sure the following will work for all students, but I remember this being a transformative "aha" moment in my own education:

> Show them *your* code.

Preferably contrasted against a functioning but god-awful student submission from the previous term. Show them how its an order of magnitude simpler than their shotgun-formatted needlessly complex mess. Show them what compactness and elegance look like. In freshman?sophmore? CS prof assigned us to write a CLI memory card game. I like many of my peers did this big elaborate class hierarchy and/or held the "cards" in nested data structures with nested loops. The prof's code was IIRC < 20 LoC: he used a flat array of structs with the modulus operator to determine the "row". I learned that day what Torvalds meant by "taste", namely the ability to know when to use "industry best practices" and when to just write simple code even if it's less flexible.

I realize that's almost the opposite point than the one you're driving at (i.e. getting them to use the more advanced constructs) but *show in your code that they exist for a reason*. If you can replace 50 lines of tedious, error-prone buffer manipulation with a built-in collection and an iterator/forEach that takes less than 10, *believe me* the smarter ones will notice. And when they collaborate with their peers on group projects peer pressure will help with the slower ones.

> **Comments:**
> **username_17**: Time pressure probably helps even more than peer pressure. ;)  

---

### Answer by username_18 on 2018-04-10. Score: 16

There are a number of facets to this question. But the first thing you need to remember is that students (like anyone) will tend to apply solutions that they are most familiar with. In the student context that means, often enough, the things they learned earliest and have been practicing with the most. This effect is most pronounced on hard problems that may not have an obvious (to the beginner) answer with the new techniques.

For the above reason, I prefer to teach a thoroughly object-oriented course to students, having them build classes and write and use methods (some of mine, some of theirs) before they seen things like primitive data (int, double...) or low-level program structure (if-while...)

More generally, I advice against a strictly bottom up approach to teaching programming, in which low level constructs are taught first with a lot of emphasis on language primitives. It takes quite a lot of scaffolding, however, but my students start their programming learning in a world that I construct, not a "naked" language. So, when they come up with a hard problem and need to "fall back" on what they know best, it will be something like writing a test for something or an interface for structure, rather than just trying ad-hoc methods.

The reason for this is that ultimately I want to teach them to be OO programmers and when they get a new problem, I want them to think in a thoroughly OO way. So they will naturally write 3 line methods rather than 30 (or 300) liners. If I try to teach them procedural programming first, that will be their fall-back and I want to spare them that pain.

However, if you don't want to employ such an "extreme" change in the course, there are other things you can do.

One method is to employ a Spiral approach in which a lot of topics are introduced early with only relatively shusername_2w usage in the first loop of the spiral and then repeatedly going deeper on each while you introduce new topics also. This, rather than *completely* explaining all the nuances of any given topic. (*Spiral* Pedagogical Pattern)

Another trick you can use, whatever your overall syllabus, is to introduce a rather large program early on that shows a fair number of important topics. One way to do this is to give them a program that is essentially correct, but which you have "broken" in a few ways. Their assignment is to understand it enough to fix it up (*Fixer Upper* Pedagogical Pattern)

Ultimately, then, the answer isn't really to "encourage" them, but to structure the course itself so that the "higher level" topics come before the lower level ones.

There is really no reason why arrays need to be discussed before (Java) collections/lists/maps... Then the foreach construct becomes their fallback and you can later teach them the c-like $for$ loop as a possible way that foreach can be implemented. I'd rather they used the libraries in their code in any case, just as I want them to program within my original framework rather than riding bareback on the language.

If you introduce "deep" and "important" topics only late in the course then it is with *those* that they will have the least practice and experience.

**tl;dr: rearrange the course so that they get the most practice on the most important topics.**

> **Comments:**
> **username_19**: "The reason for this is that ultimately I want to teach them to be OO programmers and when they get a new problem, I want them to think in a thoroughly OO way" - isn't FRP the hot new paradigm nowadays?  
> **username_20**: **This!**  Why is the OP teaching bounded *for* before *foreach*?  
> **username_7**: What you said is true if you want to build software devs or web dev that knows just enough for what their aim is to, but that doesn't include embedded dev for instance. If you don't understand the low level approach, I don't feel like people should use more advanced features. Or if they do use those collection they have to code them in the first place to understand how they work.  
> **username_14**: @username_7: I personally love the low level stuff, but I think this advice sounds reasonable.  Getting to the point of understand how different collections work (like sorted maps vs. plain hashes vs. simple `std::vector`) requires some algorithm knowledge, and understanding efficiency is only truly possible with some computer architecture (caches) and assembly language (and how source compiles to asm).  Leaving these topics for later in the spiral makes sense: by the time you get to the implementation details and low level stuff, students will be ready to understand it better.  

---

### Answer by username_21 on 2018-04-10. Score: 14

Rather than trying to motivate the students, or the reluctant ones, to progress into using your new tool (`foreach` after `for`), and finding a new motivating example every time, try to motivate them to be self-interested, lazy coders.

Now that I'm under the *tar and feathers*, I'll explain. People like to find the *easiest* way, not the *best* way. Earlier postings reveal that you're in the teen-age world with your students, and they are no exception, if not the rule, to that thinking. Knowing that your students will have that natural preference for easy, use it as the motivation. "Quality is job one" makes a good slogan for a company, but isn't so good for motivation of students.

Borrowing from the world of sales, show the problem first, and the solution second. To progress from a bounded `for` towards a `foreach`, as an example, use the bounded version in a manner already natural to them that is possible, but problematic, against a collection that can be `foreach`-ed. Legitimately work out the checks and error traps and actually make it work. Once they've experience doing it that way, then you can present the "package" where someone did all that work, and more, when they created the `foreach`. All the traps, special conditions, etc., are handled, and all the work has been done, and debugged, for them.

The same approach can be used to *step-up* to any progression you choose. Under the hood in any chosen language the new tool might not be implemented using the old one. At least not now. Still, that's how they came to be created in the first place - refinement on a common problem and its solution creates the shiny new practice which becomes a tool. That's how we got structured programming to begin with.

The key is that the new concept is not presented as *better* programming, *better* presentation, or even easier to maintain, update, or fix later. Rather it's presented as a real solution, to a real problem, *right now* that makes less work *right now* for them. Less time on coding, now, means more time, now, to be with their friends, or do other *fun* stuff. After a couple rounds of that, once the light bulb goes on, they'll start actively looking for pre-baked solutions, and libraries will be their next target. That outlook will carry them well into the future, and could even encourage them to look at new languages, either new to them, or new to the world, for an *easy* solution to a problem.

Hence, they become self-interested, lazy coders.

> **Comments:**
> **username_22**: I volunteer teaching 12-14 y/os and this a running theme: Yes, you can make a giant if/elif/elif/.../else block... but *I'm lazy,* so here is a much faster way to do it. By casting it in that way (and ensuring they are comfortable with using it), they tend to move over pretty quick.  

---

### Answer by username_13 on 2018-04-11. Score: 11

> What are healthy, productive ways to encourage students to progress to more advanced constructs as opposed to staying with the familiar?

I would say that it's the educator's main goal to showcase the necessity of using these constructs.

In general (even beyond CS), you should only take the more complex option when you **need** to. This is the core essence of KISS.

Therefore, if you want your students to use a more complex alternative, you need to present them with use cases where the simpler option simply doesn't work (well).

> For example, when they are taught arrays, they continue to use individual variables when they are able.

You've indirectly answered your own question: *"when they are able"*. Give them an assignment where they are unable to use individual variables.

*A very simple example is an application that builds an array of 20 names (supplied by the user, one at a time), after which the program generates a sorted comma-separated list of names.*

I don't see a way to sort these names by using individual variables. Even if some (hugely contrived) approach exists, it will take **more time and effort** to develop compared to a simple array sort.  
If *some* students use the arrays; the hardheaded others will see that their peers find the task much easier than they do, which will naturally incentivize to do the same.

> After working extensively with arrays, they don’t want to move to using built-in collection types that offer more flexibility and behavior.

*A very simple example is an application that builds a list of names (supplied by the user, one at a time) until the user says "stop", at which point the program generates a sorted comma-separated list of names.*

I don't see a way to do easily solve this with an array. Since you can't know how many names will be supplied, you can't definitively declare your array (you'd have to constantly recast your array to a bigger size).  
If they use a massive array to begin with, then they should be docked points for irresponsible memory management (for the same reason that you'd dock points for memory leaks).

While continually recasting the array is not impossible to do, it is contrived and it will take **more time and effort** to develop compared to using a list.  
If *some* students use the lists; the hardheaded others will see that their peers find the task much easier than they do, which will naturally incentivize to do the same.

> When introduced to the foreach loop, they continue to use bounded for loops.

The problem here is that every `foreach` loop can be written as a `for` loop. There is no real benefit to using a `foreach` over a `for`, the only benefit is the ease of reading/typing.  
A similar example would be LINQ, which is mostly used as shorthand for a foreach loop. In essence, every (in-memory) LINQ query can be written as a manually developed `for` loop. That's technically not wrong (it only affects readability and increases effort required; it doesn't functionally matter).

**Currently**, your students prefer to use a `for` loop because it takes them less time to use something they know, compared to something they don't yet know (`foreach`).  
I would temporarily ban the use of the `for` loop (or force them to use `foreach`, same thing), to force your students to familiarize themselves with the `foreach`. After a few (iteration heavy) assignments, they should be familiar with how to use a `foreach`.

**In the future**, when they are familiar with both the `for` and `foreach`, it's up to them to decide what to use. Most likely, most will pick `foreach` because it's easier and less prone to developer error.  
But the traditionalists who revert to using `for` loops are not really wrong (though they may be docked some points for readability, if you grade readability too).

> It is sometimes difficult to impress upon beginning programmers the usefulness of “new” constructs, because the exercises and programs they are capable of undertaking do not sufficiently demonstrate the power and usefulness of those constructs.

**This is a contradiction**. If you don't think the students are capable of handling a problem of this complexity, then you shouldn't be trying to teach them the solution (to a problem that they can't grasp).

In other words, if you want to teach them something, *of course* you're going to have to show them a situation where it is relevant to use the solution!

> **Comments:**
> **username_14**: *I don't see a way to sort these names by using individual variables.*  Hard-coded sorting network where every compare-and-swap is specified separately (hopefully with the compare+swap wrapping in a function call).  A sorting network for 17 elements can be only 71 comparators according to https://en.wikipedia.org/wiki/Sorting_network, so 20 elements is at least plausible to write out in the source code, and I think there are sites online that can generate them.  Anyway, totally implausible for beginners to actually come up with, but in other contexts it's not totally unreasonable.  

---

### Answer by username_15 on 2018-04-10. Score: 9

As a student, I can say the appeal to my free time is pretty powerful motivation. I have spent hours implementing features already present in a language only to feel foolish when I realized my folly.

For example I had an assignment where I spent a good chunk of time implementing my own (very flawed) version of a HashMap. I have some the same thing for a TreeSet as well.

Many of my peers will cling to an ArrayList no matter what the problem presents. They are just comfortable with using it and prefer it over any other structure, even when that means a lot of extra code they have to write.

Elegant solutions are appealing to some students due to their brevity, which can be seen as clever or almost getting away with something. That may motivate some, especially the lazy ones. Others may just appreciate how elegant the solution is for it's open merit.

I think some students will stick with Array and ArrayList until they are basically forced to not use them. No matter how clever or elegant they could potentially be. Fostering a culture that embraces failure may help overcome that.

I have found online interview prep sites have done the best at nudging me to use constructs I would have otherwise ignored. Maybe sell them on the idea of interview prep? Can't use an Array for all of those, just flat won't work and that is a time you definitely want something to work!


---

### Answer by username_23 on 2018-04-11. Score: 4

If you start with the most absolutely bone-simple programming concepts at the start, then as you introduce each more complex concept, it is obvious why it solves a problem that just could not be solved using the simpler stuff they already know: No number of separate variables will solve a problem that calls for arrays. No fixed size array will solve a problem that calls for expandable arrays, and so on.

Begin at the beginning, with things that could not be simpler or more obvious. Add one thing at a time, and show how it solves problems. Steam engine, gasoline engine, gas turbine, rocket. You just will never get to space with Jules Verne's coal-powered "rocket train".

If someone wants to stick to older concepts that won't solve a new problem, they plain old won't solve the new problem. They can't stick, they either go forward with either new concept, or they fail out. This is why we reproduce the development of programming as it occurred: no one ever gets lost trudging along in the well-worn path. They never ask why something is better than something else: they *know*.


---

### Answer by username_6 on 2018-04-12. Score: 2

Challenge them with something they'll have to do once they're working -- give them some code that uses the technique you want to teach them, and have them make a change of some sort. Or show them code that DOESN'T use the technique, require some change to be made to it, with requirements (complexity, line count, whatever) that drive them towards the technique you want them to use.


---

### Answer by username_7 on 2018-04-12. Score: 1

When I used to be a student learning C++, my teacher gave us a very open subject with only a subject : Star Wars (it was for the year of the release of the new series). The only consign was to use at least several C++ functions. We had a minimal list of the functions and structure we had to use, and could add any specific function we would have liked.

We had two different delivery of the project, first one was for the teacher to point out some place where we could have coded better (using more C++ built in function) and the second was for the final delivery with proper coding.

Honestly this was a very challenging way of giving us a project, every body get deeply into it and we ended up with very pretty and satisfactory programs.

I guess this kind of approach is very appreciated but the teacher has to give a huge amount of time in order for that approach to succeed.


---

### Answer by username_8 on 2020-01-12. Score: 1

The persons who could answer your question best are the students themselves. Why don't you ask them?
Seriously though, there might be a host of reasons why a given person is novelty-shy.

First of all, however pleasant knowledge might be, any learning process is intrinsically painful, so some reluctance is only to be expected from any pupil or student at some point.
Besides, computing is extremely abstract. Maybe not as much as maths, but still it takes a bit of time before you can really create something beyond learning basic vocabulary. For those who are passionate about the subject it's a breeze. For others, that initial period requires a leap of faith.

Maybe some of your students are simply not interested in programming, in which case they will likely try and avoid the chore of learning more unpleasant stuff.  
Or maybe they are struggling to keep up and feel too insecure to tackle new concepts.  
Or maybe they are having it too easy and don't see the point in learning new tricks if the problems they are given can be solved without.

Depending on the cause of their reluctance, you might for instance:

* openly discuss their lack of interest and make a deal with them: do the bare minimum honestly and I'll try to make it as painless as possible
* work on the student's self confidence. Try to find a couple of relays among the most advanced students that can spend some time helping others in group projects.
* give them something worth tackling the new concepts. Ideally a project where old tricks either don't work or are too impractical.

As a student, my best memories are from classes where I felt I belonged. Not necessarily as a successful student, sometimes quite the contrary. By "belong" I mean I knew what to expect and felt in agreement with the teacher - even if that was sometimes limited to agreeing to disagree :)  
I loathed electronics and had disastrous grades, but I managed to strike a deal with a few teachers who would clearly state what they expected of me and respect my lack of interest.
I also had a couple of teachers who took the time to devise problems for advanced students and kept us interested while the rest of the class struggled with system programming basics.
Plus a couple of teachers who helped me overcome an initial reluctance to dive into some domains.
Lastly, I remember one college teacher to whom I am still grateful today for opening a window to all that marvellous literature. Decades later, I met again with a college friend, and to my consternation she told me these French courses had bored her silly :). It took me a real effort to accept the idea that these lectures I had found so captivating could have been perceived as plain chores by some!
So any teacher's trick is likely to work magnificently with one student and fail spectacularly with another.

I tried to emulate that behaviour in my few teaching experiments, with mixed success to be honest, but at least I always avoided the pitfall of being a one trick pony.

Always try and listen to what the students have to say (if anything), that would be my first and last advice.  
If they know you sincerely try to take their needs into account and expect reasonable things of them - within the limits of what you are expected to teach them, of course, they will usually go to great lengths to be worthy of your respect and fulfil your expectations. At which point problems like the one you evoke in your question cease to be major issues, in my limited experience.


---

### Answer by username_9 on 2022-05-06. Score: 1

I have spent a lot of time on chatrooms/forums helping people with their programs, and over time what I've found is:

* Provide partially written code to help them feel comfortable with it. Be sure the code you give is clear **and concise**. It needs to focus on the point and avoid being more confusing than it must be. (I find this helpful for people asking for help.)
* Give solid reasons for **why** they should use something. If you just tell them "this does X" without explaining why they would want something like "X", then they'll never know when they should use it over something else. If you're teaching these advanced concepts, there should be a reason you're teaching them.
* Make sure they try it. For many, code snippets during lectures are nothing more than code snippets. People tend to have more attachment to their own code because they understand their own code more than a stranger's. This means they aren't really understanding why the code you're showing them actually matters to them.

Now, that's cool and all, but how should you actually integrate this advice into a classroom setting? I'm not a teacher, but here's some ideas:

* Provide partially written code alongside assignments as **hints**. Whether or not a student uses it is up to them, but it'll encourage them to think about stuff like "where should I use this?" and "how should I fill this in?".
* Make it obvious how the given reasons for using something over something else would apply. If you're going over lists vs sets, then even have them implement something simple using both ways so that they can see the difference first-hand.
* Give them a reason to look back on their own code. For example, have them do peer reviews after they finish the assignment. Most students won't look at their code after they've turned it in, so they don't learn from their own mistakes.

> **Comments:**
> **username_10**: I like your opening point. Clear and Concise. I encounter a lot of examples where the point is buried is huge examples, or hidden behind obfuscated code. Python is particularly horrendous when it comes to hunting down examples as everyone goes off in their own confusing direction.  

---

### Answer by username_11 on 2022-04-26. Score: 1

1. As mentioned in a comment: start with high level constructs when possible.
2. In some assignments I give students the main program, and then tell them, write the data structures and functions that make this work. That way you're forcing them to use the high level constructs, and maybe they'll see that the shorter/more elegant expression is preferable.


---

