Lessons from Tutoring

Today marks the end of winter quarter at UCSD – my official last day of employment as a CSE Tutor.

For the past two and a half years, I’ve been tutoring classes in the Computer Science and Engineering (CSE) Department at UCSD. I’ve had the opportunity to help students from all walks of life and experience levels learn new coding concepts, debug issues in their PAs (programming assignments), and review material for their finals.

It’s kind of wild to move on from this experience that has been a big part of my life, teaching me new skills and forming some of my strongest friendships. I thought I’d take a moment to glance back at my journey and reflect on some of the most valuable lessons I’ve taken away from tutoring in hopes of gaining some introspection into how this has shaped me as well as hopefully inspiring someone reading this to tutor others as well someday.

  1. Everyone has a different approach to problem solving. Everyone has their own unique way of viewing the world around them. This may appear obvious out loud, but it’s a truth that becomes readily apparent after a single tutoring session. That assignment you approached with classes and object-oriented design patterns might instead have a solution using pure functional programming. More often than not, you’ll encounter a giant main method, filled with all the code needed to solve the problem.

    When I realized this fact, I was immediately struck by the parallel seen in the software engineering industry. The differences in coding style can be significant even between engineers on the same team (albeit with no giant main methods, thankfully enough). Because of my tutoring experience however, I’d already accepted and realized the incredible variety of equally valid ways to solve a problem, and thus I was able to see the different approaches in industry as what they were - different forms of art. Richard Hamming often said programming was more similar to art than engineering, and tutoring countless students all with their own unique paintings (despite using the same brush) gave me early exposure to this fundamental truth.

  2. Look for the root of the problem. You can become a better problem solver and gain a broader perspective by understanding exactly why things happen. Regardless of which solution is better, tutoring opens your mind to realizing other perspectives exist. Early on in my tutoring career, I caught onto the fact that rather than forcing students to blindly follow one path, you’re better off understanding why a student went down their approach.

    Oftentimes we try to solve problems by fixing the bugs and errors they cause — but ultimately this is only symptomatic support, and to really prevent the problem from happening again, we need to understand why those problems occurred in the first place.

    A benefit tutoring offers is that you can easily determine what classes a student has taken until that point, and a simple understanding of all the professors will help you know if a student has been taught with a particular emphasis on class-oriented code vs focusing on cleanly organizing code into modular functions. As such, you can then use this understanding to introduce new concepts + re-emphasize old ideas. Oftentimes, mistakes are made due to misunderstandings or misapplications of a prior teaching.

    In this way, tutors can guide students in the right direction and explain exactly why their problem came up, providing them with the ability to treat all of the symptomatic bugs that arise and craft more considerate solutions independently.

    The real world doesn’t give as much clarity - but some forensic work to understand design decisions (another reason why good documentation is a must!) will help you similarly debug real-world problems.

  3. Patience matters. It’ll help you listen and detect the problem. When you’re debugging someone’s code for the first time, it’s usually better just to listen — at least for a little bit — instead of jumping into debugging their code. In industry, this idea has become so common that it has a name: rubber duck debugging, coming from the belief that talking to a rubber duck is a great way to think through your code and notice pitfalls while defending one approach — and it has clear benefits in undergraduate courses as well.

    I’ve found that not only is just listening + letting students resolve their own problems whilst talking it out really useful (seriously, I resolve the majority of my tickets like this), it also helps students realize that they have it within them to fix their own problems.

    It’s often said that the main differentiator between a novice programmer and an advanced one is their ability to Google things; to abstract further, it simply comes down to their problem solving skills. Allowing students to talk through their issues, often only prompting them to come up with better questions as to why their code isn’t working, helps them get a stronger view of their code (not mention the added benefit of learning about someone else’s thought process).

  4. Sometimes people just need support. Everyone who comes for help has it within themselves to solve their problems, and sometimes it may just take a little external validation to get there.

    I get quite a few tickets from students who don’t actually have any issues. These students tend to come in the earliest (asking for help early on in the quarter), however often have the most anxiety and fear. These students aren’t actually weak at programming; quite the opposite, they give me the best questions and seek different perspectives on how to solve a problem on their own. I realized early on that, for these students, they’re simply coming to get a bit of validation for the current approach they’re following before they go too far down one path.

    For these students, I generally noticed that the best way to resolve these issues is to (a) tell them when they’re on the right track and (b) offer ways for them to self-validate their approach through example test cases and questions they can ask. Learning how to self-validate an approach is an essential skill for a programmer, as it’s also how you’ll have to explain your code at any job, and potentially how you’ll write unit tests later on.

    As Iroh says, a little help from others goes a long way

    What I find most notable about this group of students is that they usually are my favorite group; they’re filled with potential and intelligence, but they’ve also grasped early on the importance of talking to others to validate their approach. They’re a substantial group of the students I tutor, and as long as this group of students continues to thrive, I think we’ll continue to create new and amazing programmers for years to come.

Final Thoughts

It’s truly been a remarkable experience being able to tutor for this long at UC San Diego. Throughout my experience, I’ve been given nothing but continual support from my bosses (the professors) and my fellow tutors (who were only ever happy to jump on a ticket to help me on a call). UC San Diego has also been really supportive, providing us with resources to tutor better during the pandemic (I still use my drawing tablet to help on calls), and allowing us to work seamlessly from home.

I’d like to give special thanks as well to Niema Moshiri, who I’ve had the privilege of tutoring under for the past 2 years. I’ve seen how he iterates on his coursework every single quarter, and there’s a reason that almost everyone I meet calls him the best professor they’ve ever had.

Special thanks as well to Faris Ashai for helping me edit this blog post.

Lastly, I’d like to thank my fellow tutors, and share a video that recaps the time we’ve all spent together.

CSE 100 Tutor Video