The following can also be found with better formatting here: Teaching Staff Training: Sample Dialogs
Student-Driven Teaching
Learning should be student-driven, which means that your teaching should be, too!
If a student says "I don't know how to solve this problem," what would you say?
Often, a TA/tutor’s first answer to this is something along the lines of, "Here's what's going on in the problem, and the first step is...". Think about this approach…why might this not be a good strategy?
Instead, if a student tells us they don't know how to solve a problem, we tend toward responses like "Can you tell me what's going on in this question?" We then continue to ask questions that probe at a student's understanding and guide them toward improving this understanding rather than explicitly telling them how to do the problem. This is often referred to as the Socratic method.
Some questions we might ask them along the way are:
"What have you been learning in class that might relate to this?"
"Have you seen any example problems similar to this in class? Can you show them to me, and we can see how they might help?"
"Which part is confusing?"
"What have you tried so far?"
As you start to see where the student's confusions or misunderstandings arise, offer partial explanations of the concepts that are confusing to them and ask many questions along the way to check that they are following along. It is very common for students to just sit and nod during an explanation even if they are not comprehending it at all. This is why we emphasize partial explanations. You should give the student just the beginning of an explanation--the building blocks they need to get started--and then ask them what happens next. The vast majority of what you're doing during a session is asking questions that lead students to answers on their own.
Once you've gotten into the meat of the problem, you can ask more specific questions. Let’s take a look at some sample dialogs that emphasize student-driven teaching.
It may also be beneficial to set expectations for students at the beginning and let them know that you’ll be teaching in this way. This may help to reduce frustration when you’re not immediately giving them an answer.
Aim to have your interactions structured in the following way. Students should know to expect this–they should not expect us to simply provide answers for the most part. Sometimes, especially at the very beginning of the class, you might find that there is factual knowledge that they are missing and you’ll need to simply provide the information. It is definitely a judgement call, but when possible, err on the side of helping the student figure it out themselves rather than providing them answers. You can also always help by encouraging them to look at certain material (e.g. a particular lecture, example problem, video, etc.).
Expectation setting: Let the student know that we’re going to help them learn together and understand what they need help with. This means you won’t be giving them answers, and it might take longer than expected and have parts that are frustrating. Ask them to let you know if you’re going too fast or slow.
Pre-reflection: What have you done so far? What is your program doing, and what do you want it to be doing?
Troubleshooting: Various teaching strategies. Elaborated in sample dialogs.
Post-reflection: What did we do? What helped? What will you do next time a problem like this arises?
Double check on all students: Sometimes during busy office hours, we may forget where each student is in their progress. You may tell a student to read a particular resource and come back to you when they’ve read it, or look at a particular practice problem–which is a great strategy, since teaching staff shouldn’t have to re-teach the class. However, we do want to make sure that your last interaction with a student wasn’t “Go do _____” with no follow up. Check in on them, and see if they’re able to follow your suggestion. Are they stuck? Confused? Could they benefit from more 1 on 1 attention?
During the pre-reflection and troubleshooting phases, if it sounds like a student is bringing you LLM generated code that they don’t understand, you’re welcome to ask them (kindly!) where they got the code. Remind them that it’s perfectly fine if they used online resources and/or LLMs.
The steps of asking “What is your program doing, and what do you want it to be doing?” actually don’t change much! No matter where their code is from, we want them to understand what it should be doing and what it is doing.
What may change, though, is:
You’ll need to remind them of the importance that even if they use LLMs, they should understand their code.
(If you want, and if the student is already comfortable using GenAI–many have personal qualms about it and that should be respected) You can suggest that they ask a GenAI agent to explain what’s wrong with the code. You can even suggest helpful learning prompts like “You are a tutor, and I am a novice programming student. Help me understand what’s wrong with my code…”
Extra attention to “Double check on all students”--the last thing you say to a student should not be “Try asking GenAI”. Make sure that you’re encouraging the student to learn from GenAI rather than copy pasting, and you’re actively collaborating with the student on their understanding.
The dialogs below are annotated with various teaching strategies and tools that might help to think about. Each “tool” is bolded and in brackets. The dialogs are not annotated comprehensively; after a teaching tool has been tagged once, it is (usually) not tagged again. The annotations are meant for you to get an idea of how the tools are used.
The problem discussed in this dialog is from the following Stack Overflow question (code is pasted below for convenience):
Always Returning in Loop Error in my code, wondering what I need to do to fix it? - Stack Overflow
def divisible_by_7(lst: List[int]) -> bool:
"""
Return True if and only if lst contains an element divisible by 7. Otherwise, return False.
>>> divisible_by_7([4,8,21,6])
True
>>> divisible_by_7([1,2,8,9])
False
"""
for num in lst:
if num % 7 == 0:
return True
return False
<First, make sure to do a bit of expectation setting as described above.>
T: What happens when you run your code?
S: It says False for [4,8,21,6] even though it should be True.
T: Ok, let’s see. Do you know why it’s doing that?
S: No, not really.
T: [State the strategy.] Alright. When I get stuck in loop problems, I like to start by tracing through an example all the way through the loop. Let’s try that. What happens when you pass in [4,8,21,6]?
S: Ok…for num in [4, 8, 21, 6]...So it starts with 4. If 4 modulo 7 equals 0…that’s false, so it goes to the next one.
T: [Stop when a mistake occurs], [Affirm correct elements from student] Wait a sec–so you’re right that it’s false there. So let’s take a look carefully at what happens next. What happens when that if-statement comes out false?
S: It goes to the next one.
T: [Point with a question] Are you sure? What line does it go to when it finishes that if statement and gets a ‘false’?
S: It goes to ‘return False’.
T: Right! And what does a return statement do?
S: Ohhh, it returns from the whole function.
T: Exactly…and what does that do?
S: Yeah so it’ll never get to the rest of the loop after that.
T: [Encourage student ideas] Right. So how would you fix it?
S: I’m not sure…maybe change it to ‘else return false’?
T: [Encourage the student to evaluate their own ideas] Let’s see…what would happen if you do that? [State the strategy.] Try plugging in a number.
S: Ok, you’d get 4 modulus 7 is not 0, so it goes to the else…then we get else return False and it goes to the next one.
T: Wait, what happens when you return?
S: Oh, it goes out of the function!
T: Right.
S: Ok, so we can’t return False there. Then I don’t know…
T: [Remind the student to think about what the problem is asking.] What is the problem asking? What do you want it to return?
S: I want it to return true if there’s anything divisible by 7 and false if not.
T: Right. So it looks like you got it for the divisible by 7 part. In this loop, it’s going to return true as soon as it finds one that’s divisible by 7, and not even go through the rest of the elements in the list.
S: Ok.
T: So what do you want to do if it doesn’t find one?
S: Return false.
T: Right. And when do you do that?
S: At the end.
T: Right, you want to make sure that it actually looks at all of them before it returns. How do you do that?
S: Just return at the end.
T: Yeah, so where would that be?
S: Hmm….return false is already there at the end…
T: Is it at the end? When does it reach there? What happened when you traced through with the 4?
S: Oh, it gets to return false the first time it finds one that’s not divisible by 7.
T: Right. And when do you actually want it to return false?
S: I guess at the very end…so it can’t be in the loop?
T: Yup!
Note that the same bug could have two different causes–the code above could have been created by a student who knows what’s going on but simply mis-indented. Asking questions about what the student’s current understanding is will allow you to find the misconception and lead them to try a different path. Rinse and repeat until they find a path that solves the problem!
Student runs the code below and receives an error message.
int func1(int n) {
n = n + 5;
return n;
}
int func2(int x) {
return x + n;
}
From https://www.ic.unicamp.br/~reltech/2017/17-15.pdf
<First, make sure to do a bit of expectation setting as described above.>
T: What happens when you run your code?
S: It doesn’t run…it says there isn’t an n variable.
T: Ok, what do you think is going on?
S: I’m not sure. I made func1 with the parameter and return like we learned in class so it should be able to use n.
T: [Mention a concept by name so that the student knows what to read/practice.] Got it. So the issue here is about scope. Did you learn about scope in class?
S: I think so, not really sure. Another option: [Point them to a resource and tell them to go read that for 10 mins and come back]
T: Ok, can you tell me what you know about it?
S: It has something to do with where you can access a variable, I think? Not really sure what that means though.
T: [Use concrete variables in the problem to demonstrate a concept.] Right. So it looks like you’re trying to use n inside of func2. We always have to keep track of who has access to what information. So let’s see…what does func2 know about?
S: I’m not sure.
T: [Use examples that the student is already familiar with.] Can you show me an example of a function from something in class?
S: (pulls up an example; let’s say it’s func(int x){ x = x/2; return x}.) Here’s one.
T: Ok, so in that function, what variables is it using?
S: It has just x in the parameter and then it divides by 2 and returns.
T: Yup. So when it’s doing that, on the first line of the function there, how does it know what x is?
S: It gets it from the parameter.
T: Exactly. So what if I instead passed in a different variable a? So if I change the function definition to be func(int a)?
S: I’m not sure…it wouldn’t work?
T: Right. What would it do?
S: I don’t know…
T: Ok, so func is getting some value for a, right? Then on the next line what does it do?
S: It’s dividing by 2.
T: Well, what is it dividing by 2?
S: x.
T: Ok, so what value of x is it dividing by 2?
S: I’m not sure.
T: Yeah, it’s weird, right? You’re giving it a value for a, but then you’re telling it to divide x by 2. How does it know what x is?
S: I guess it doesn’t?
T: That’s right. Imagine you don’t even have functions, like in your previous homework where you’re just working with a main method. If you don’t declare int x, and you just write x = x/2, what happens?
S: It’ll give an error.
T: Right. What kind of error?
S: It’ll say there’s no variable x.
T: Exactly. So if we think about our example again, we have func(int a){ x = x/2; return x}. So what will it do?
S: It should divide by 2.
T: Well, what is it dividing by 2?
S: x.
T: Ok, and how does it know what x is?
S: Oh, it doesn’t? So it’ll have an error?
T: Yup! Just like the other one. It’ll say there’s no variable x. So that’s after we changed it to say int a. What happens if you have it like the original problem func(int x)?
S: Then it’ll work.
T: Yeah! What’ll it do?
S: It uses the x from the parameter and then divides it by 2.
T: Exactly. Ok so let’s go back to your homework problem. What was going wrong there?
S: Func2 wasn’t working...it has the x in the parameter and then it does x + n…oh but it doesn’t know what n is.
T: Right! So how can you fix that?
S: We can pass in n in the parameter?
T: Yup! Try that.
The problem discussed in this dialog is adapted from “Checklists for Grading Object-Oriented CS1 Programs: Concepts and Misconceptions”: https://sci-hub.se/https://dl.acm.org/doi/10.1145/1269900.1268834
See 4.2, “Instance/class conflation” for the context of the examples used below.
In this dialog, we use a fabricated example of a student who used each of Ellipse, Ellipse_1, and Ellipse_2 for specific colors (i.e. Ellipse whenever they wanted a red button, Ellipse_1 whenever they wanted a green button, and Ellipse_2 whenever they wanted a blue button.) .
<First, make sure to do a bit of expectation setting as described above.>
S: I got points off because I created Ellipse, Ellipse_1, and Ellipse_2 instead of just Ellipse. But that doesn’t make sense. I needed to have all of them to get all the different colors they asked for in the assignment.
T: Let’s see. Why did you need all three? What is the difference between them?
S: They all have different “color” properties.
T: Right. [When you see a misunderstanding, do not immediately tell them the right answer. Ask why they/how they decided on their code.] And how did you make those different color properties?
S: Well that’s why I had those three classes…each one had a different color variable.
T: Ok. Where did you make the color variable for each one?
S: Right here in “private String color; ” at the top of the class.
T: Great, that looks good. So now how do you set it to different colors for the different versions?
S: In the constructor I say “color = red” for Ellipse, and then same with green and blue for the others.
T: Gotcha. So what did you learn about constructors?
S: They’re for setting the properties that are the same for every object of that class.
T: That’s right, they’re the same for every instance. So how can we use that in this assignment? Do you want every button to be the same color?
S: No, that’s why we have different colors for the different classes.
T: You’re right, that is one way to solve it. [Analogy.] But think of it as a machine. You have this class as a machine making lots of different buttons. The way you have it, though, you’re building three different machines to do allllllmost exactly the same thing but with one tiny change. Imagine a car factory. They have basically the same assembly line, but then a small change in the assembly line for the different colors, right?
S: Yeah, that makes sense. But that’s why I just kept everything the same except for the one change in the color!
T: Right, but whenever you find yourself copy pasting a whole class, it usually means that you can do it an easier way. You can make instances of the class and change the variables in each of those instances.
S: But I set it in the constructor. I can’t have different constructors for different instances.
T: That’s true. So what do you think you could do instead? Is there another way you could set the color?
S: I don’t think so, we always set private variables in the constructor.
T: Let’s look at some examples of constructors you learned about in class. What do constructors have?
*Some back and forth in order to pull up an example of a constructor that takes a parameter*.
T: Ok, so we see this constructor takes a parameter, right?
S: Oh, ok…so does that mean I should put color in the parameter?
T: Yup, exactly!
See the Teaching Toolkit
The tools and strategies used throughout the dialogs here are consolidated in the Teaching Toolkit. Feel free to write your own, and we can add them!
Other resources on dialog-driven student learning:
The Socratic method : Part of Luther Tychonievich’s TA Training Practicum.