1. Tell them what to do but do not tell them how to do it. (Just give a few pointers otherwise they'll be lost.)
2. Give them a playground to fail - Offload any non-business critical tasks and let them make mistakes. No one I know ever learnt programming without making any mistakes. Immediately tell them about best practices and how to avoid such mistakes in future.
3. Show them the impact of their work - There's nothing more motivating than seeing the impact of one's work.
4. Build curiosity - Answer as many questions as you can answer. Admit when you don't know any answers and start looking it up on the web right in front of them. People pick habits by looking at their superiors.
If it's absolute beginning to programming, this video is a great way to show how difficult it is to teach a machine to do something and how clear instructions can help get things done: https://www.youtube.com/watch?v=cDA3_5982h8
I have never liked the “make a sandwich” task. It sets people up for failure, because the teacher can always take things literally enough to make the student wrong. (For example, when given the instructions: "Take out two slices of bread", the teacher can rip open the side of the plastic bag rather than use the opening.) Some students end up with the feeling of “If I can’t even explain how to make a sandwich, how will I ever be able to tell a computer to do anything?”
Here’s an exercise (not sure where I discovered it) that I use at the community college level: https://www.youtube.com/watch?v=meSK1rn2VbA It has the same elements of analyzing a problem, breaking it into steps, and making sure they’re in the right order; but it’s set up for students to succeed.
This exercise is very effective when you put the students in groups of two or three to work on it.
Sounds like this make a sandwich exercise is rather good for understanding the issues with gathering software requirements; it confronts the students with creeping requirements, before they even know how to code.
Coding should probably be taught with a background of requirements that are precisely given in terms of the abstractions that are being used in the code. So that is to say, the problem itself doesn't have to be something abstract (like a number-theoretic computation); it can be connected to something in the real world. But the representational mapping from that domain to the computer should be established by the teacher, so there is no irrelevant fumbling about the requirements.
In the case of the sandwich, we should provide a procedure which somehow takes the slices of bread out of the bag. Similarly, we provide all other necessary procedures, and only those procedures are to be used. Then we eliminate questions about the detailed requirements about what those procedures themselves do, like can the bag be ripped, or does the removal have to be tidy.
A good domain for teaching coding might be game playing (cards, etc). People understand that the objects used in games are abstract, and that certain details do not matter to the game, like the exact shape of a rook in chess or its precise placement within a square. It could just be the letter "R" in an 8x8 grid of characters (with "r" being the opposite color).
Symbolic games are basically a form of mathematics that is instantiated in the real world whose abstractions people readily understand. Moreover, they have a point (to have fun), so the "why are we doing this" question is settled.
That video was super-helpful. I believe he is a CS instructor, and his methods are easy to explain and understand, unlike a lot of class that just rush the students into learning bunch of technology before really learning how to think like a programmer.
The whole point of the exercise is for the teacher to do it in an unexpected manner. The exercise is about established structures and constraints, isn't it?
The point being "I can't even tell someone how to make a sandwich without establishing the platform we're building on". If you start a python app writing in assembly or Fortran then (in general, you pedants!) it's not going to work.
If you do the same exercise with cooperative people then you don't normally emphasise the point because they do a lot that's not clearly defined, and that hides the point about defining the parameters and metrics you're working with.
Thank you for sharing this video. It can be more helpful for novices than the flat-out adversarial approach of "I'm going to mess this sandwich at every possible step to show you that you need to be precise".
I've found that learners will succeed when they are able to answer affirmatively these two questions: "can I do this?" (self-efficacy), and "do I want to?" (motivation).
The robot scenario with a handful of commands is preferable compared to the "make me a sandwich" task in both respects, because failing badly at even getting bread out of the bag (say) can destroy both self-efficacy and motivation.
I actually think step (1) isn't a good way to start unless the pupil has some prior knowledge.
Many (most?) people don't have know how to take a big problem and turn it into something they can make progress on.
You give them the lego bricks and say 'make me a windmill' and they don't have the first clue where to start. They may not even understand that programming is lego.
So, you either have to teach that first. Or, if you want to teach it later, start with a sequence of problems that have one obvious step each.
Some good approaches to attacking a problem too big to be obvious:
1. Break it into smaller and smaller pieces, then implement those pieces.
2. Bite off a small piece that you think you can do, then grow that.
3. Write down everything about it then think very hard about what are the essential characteristics of a solution.
I was going to respond with a similar list. This is close and augments my philosophy well. Thanks!
I personally teach people to code with Python. Because it's easy to get into but can grow with someone where ever they want to go. It has a strong culture of clean code and DRY, and it is fully formed with a great community.
1. Start with Learn Python the Hard Way and do it until you are frustrated.
2. When frustrated with LPTHW, move to setting up a Django website. Do the Hello World of Django.
3. I work with the person to figure out something in their life that they'd like to make a web app of and help them do a simple website with basic Django models and bootstrap (so it looks good and like the familiar face of a finished product).
4. Work with them on simple deployment patterns and looping back into LPTHW to continue rudiments.
What I'm trying to teach here is that when you're staring at a wall of infinite unknown; set yourself up for success. Taking bites out of the elephant and learning to tolerate frustration / lack of knowledge by balancing with feeding yourself success. Always try to back learning of complicated things with a process of exploring something personally relevant to you and keep a sense of play.
I try to emphasize that the feeling of unknown that they are experiencing IS the state of being a programmer, the problems just change. The scale of what you can leverage grows. But at the end of the day, the unknown is what you're exploring and if you take to the process you'll learn to be excited about that. It will still always be scary, annoying, and sometimes really fun.
> 2. Give them a playground to fail - Offload any non-business critical tasks and let them make mistakes. No one I know ever learnt programming without making any mistakes. Immediately tell them about best practices and how to avoid such mistakes in future.
I think even more importantly is to encourage failure, or at least reporting it. How many times have you been ecstatic that you managed to get a program to crash differently? A lot of people are terrified of failure, but people probably learn better from their mistakes. And showing them that it's ok (even encouraged) to report what their stuck on to you means that they can potentially get a quicker solution, learn from you.
I have to second this comment. I think it is also important to stress the activities after the failure is also important. ie reporting it at earliest, proactive in helping to contain its impact, conducting a lesson learn etc.
Of course that's programming, it's Telepathic Declarative Programming. And I suspect that with the rapid improvements in neural interfaces[0], we'll all be utilizing this before long.
Reminds me of a blog post I wrote a few years ago on how breaking down problems is the most important skill you can ever learn as a developer.
I had a similar example where I talked about tying your shoes. What seems so trivial can easily end up being hundreds of steps without even delving into really low level details like controlling individual muscles of a specific part of your body.
2. Give them a playground to fail - Offload any non-business critical tasks and let them make mistakes. No one I know ever learnt programming without making any mistakes. Immediately tell them about best practices and how to avoid such mistakes in future.
3. Show them the impact of their work - There's nothing more motivating than seeing the impact of one's work.
4. Build curiosity - Answer as many questions as you can answer. Admit when you don't know any answers and start looking it up on the web right in front of them. People pick habits by looking at their superiors.
If it's absolute beginning to programming, this video is a great way to show how difficult it is to teach a machine to do something and how clear instructions can help get things done: https://www.youtube.com/watch?v=cDA3_5982h8