
How to crush it in COMP 105 at Tufts (and similar CS classes)
Five years ago, I took COMP 105 (Programming Languages) in my last semester at Tufts, and the first half of that class almost torpedoed my whole final semester into disarray. I was regularly starting the projects for the class late and working on them solo. Many of the more theoretical questions on homework assignments went unanswered with 0 points. And any time I caught up in 105, I fell behind in my other classes. All-nighters were frequent — and ineffective.
Despite how the first half went, the second half was an epic rebound to the proudest C I’ve ever gotten on something. And the things I learned in 105, like functional programming, understanding programming languages you don’t regularly work on, and tackling problems with teammates, all turned out to be incredibly useful for learning new languages and for coding on the job.
You really can get a lot out of the class even if you have no plans to be an academic, so I would like to share my advice on how to do well and get the most out of 105 at Tufts, and similar courses at other schools. The tips all seem pretty obvious, but I saw firsthand that following them was pivotal to changing 105 from a nightmare class to one of the coolest classes at Tufts.
Self-compassion is important!
This first tip I am giving more retroactively, but self-compassion is incredibly important not just in 105, but in the whole software industry. Sadly, burnout and impostor syndrome (feeling like you pulled the wool over people’s eyes to get where you’ve gotten, and not being able to internalize your own success) are big problems in a “10x-engineer”-deifying tech culture. I dealt with a lot of burnout and impostor syndrome myself in 105, and self-compassion would have helped a ton. It makes it easier to “let yourself be a n00b”, which is a healthy growth mindset for learning the material, getting help from TAs, and recovering from slip-ups as a stronger engineer.
As an introduction to self-compassion in tech, I highly recommend this blog post by April Wensel, founder of Compassionate Coding. In that post, she advises that you name how you feel when things are going wrong rather than letting your emotions stay amorphous, speak to yourself like you would speak to a close friend, even when a mistake is totally yours, and recognize that you’re not alone in what you’re dealing with.
This isn’t just a buzzword, by the way; a lot of startups have succeeded by having a blame-free culture so when something goes wrong, people feel safe reporting a problem that might involve code they wrote. So to me, self-compassion is like giving yourself a blame-free culture for 105, with a lot of the same benefits. This includes less pressure on yourself to cut unhealthy corners like all-nighters and late-night energy drinks, an emphasis on learning from mistakes, mitigating impostor syndrome by recognizing you’re not alone or a bad engineer for having trouble in 105, and seeing that there is no shame in getting help if you need it.
Like blame-free culture for startups, though, self-compassion does take practice to develop, so don’t judge yourself if it doesn’t come naturally at first. It can become second-nature faster than you might think. Also, how to do self-compassion is different for everyone. For myself, I find being part of supportive tech communities that encourage being a mentor over being “10x”, such as the Go community and the #CodeNewbie and #NLPNewbie Twitter chats, to be a huge help for beating the tech toxicity conducive to impostor syndrome. There’s also a great list of self-care resources at selfcare.tech, and a guide to handling burnout at burnout.io.
Practicing self-compassion, by the way, does not make you “weak”. By doing what you need to do to stay physically, mentally, and emotionally healthy in this class, be it exercising, going to Counseling and Mental Health Services, socializing, or even just stepping away from your work to take a walk, you’re making your work more sustainable, you’ll be able to get more learning out of the class, and that will also make taking care of oneself more normal in the tech industry. And to any other guys reading this, that’s not “unmanly” either; self-compassion is not unmanly because compassion is not unmanly!
Talk to everyone
Easily the #1 piece of advice I tried while I was in 105 was to talk to everyone who has something to do with the class. The biggest mistake I made in that course was that I didn’t start pair programming or doing homework in Halligan until after midterms. As a result, it took forever to understand the material and I couldn’t finish most of the assignments, leaving quite a few questions unanswered with no credit. Talking to everyone, however, was the crown jewel to my mid-semester comeback, as well as to familiarizing myself with new codebases and business objectives at work.
While COMP 40 is considered the pair programming class in Tufts CS, I would actually say 105 is more deserving of that reputation. 40 has long assignments, but not much theory, so a 40er could solo pretty much any of COMP 40’s projects with a few extra hours. 105, on the other hand, is more theoretical and has more new concepts to delve into, like operational semantics and the theory behind type systems. Because of that, in addition to a second set of eyes for faster bug-spotting, pair programming adds a second person to think about the concepts with. That more than doubles the speed of you and your partner mastering the material. You will figure out how to finish the projects as your two brains throw the wrong ideas at each other until they reforge into the right ideas.
Besides pair programming, “talk to everyone” also applies with showing up at Halligan for TA and professor office hours. The TAs are all former 105 students, and unlike in 40, they answer questions from everyone at once, rather than one programming pair at a time. As a result, when I started going to office hours I was not only getting answers to my own questions, but also hearing the class go over questions other people had, which were often in my blind spots. Not to mention, by going to TA office hours you’ll get to know more of your fellow Tufts CS students, so that’s another win.
⚠️WARNING⚠️: While communication was key to doing well in 105, make sure you read up on the academic integrity rules for the class! The big ones I can remember are that you can’t show your code to anyone else or read anyone else’s code, and you have to cite anyone you shared ideas with when you send your homework in. Obviously, though, follow all the rules so you have a clean transcript.
Keep up the habits from 40
If you already took 40, basically anything that helped you succeed there also works in 105. As I mentioned, pair programming and working in Halligan consistently will save you a lot of time. Besides that, there’s a big takeaway from COMP 40’s design documents. They’re not part of your grade in 105 like they were in 40, but in 105 (and on the job), taking the time to clearly specify what you want your code to do is a “secret sauce” to rival the peanut sauce from Stir Fry Night at Carmichael. That planning helps as you’re thinking about how to solve the problems on the project and figuring out whether or not your code works. If you haven’t taken 40 yet, you can also get in the habit of specification by getting your feet wet learning test-driven development (TDD). Many popular languages have frameworks for that, like JavaScript (Mocha), Go (standard testing library), and Ruby (Minitest). Knowing TDD, by the way, also happens to be a great skill to have for coding on the job!
Another important habit 40 taught was to document your code well. Documentation is part of your grade on both 40 and 105’s coding assignments, so if anything it gives you more points. But like with specification, documenting early on forces you to think more about the code you’re writing during the period of time where you’re stuck figuring out how to make it work. Moreover, if you can only get some parts of a programming problem solved, documentation will help the TAs understand what your thought process was as you were writing your code.
Finally, the design documents and pair programming in 40 made it really hard not to start early. In 105, as Norman said in the first lecture when I was there, starting early is more useful in 105 than in a lot of other classes. I’m totally with Norman on that; since a lot of 105 questions are theoretical, you’ll want those questions to enter your head as soon as possible. That’ll get your brain to start working on them, and you’ll also figure out what in particular you’re stuck on so you can ask good questions at professor and TA office hours!
Read before lecture so you know what the experts are saying
Something else I found when I was in 105 is that any time I did the reading before class, I was able to follow along. If I hadn’t done the reading beforehand, though, I would fall off the lecture about halfway through, which meant I had to do a whole lot more reading afterward to pound the ideas into my head. Even if the material doesn’t make sense the first time you read it, it’ll be clearer hearing it in class if you’re seeing it the second time there.
If you’re taking 105 as an undergrad, you’ll probably be seeing a lot of the concepts in the course for the first time, like the theory and mathematical notation of how programming languages work, and how interpreters work to give you features like higher-order functions, type systems, pattern matching, and type inference. Your professor will be someone who really knows this material well, so you’ll want to be able to follow along so you can learn the material from an expert. While it can be tough to find the time, if you invest in doing the reading ahead of time, you will have already wrestled some with the theory and you will have it in your head going into lecture. Then even if you don’t completely have the lay of the land on the material, you’ll still be able to pick up in class where you left off.
Develop your notetaking technique for coding
This is one other tip I’m giving retroactively. In addition to taking notes in class and as you read, for the programming problems in your homework, it’s really useful to have a notetaking technique to capture your thought process and questions as you code. This especially comes in handy in the second half of the class where you’ll be adding features to an interpreter that was written in Standard ML. You are reading someone else’s codebase in those assignments, so that means you’ll be spending time building your context on the problem, which your notes can turbo charge.
An ergonomic notetaking style to track your ideas has a lot of benefits. You will be able to keep track of how different pieces of code are related and which concepts in the codebase you currently understand so your mental map of the code can keep growing. Additionally, by tracking what you don’t currently understand and which ideas and approaches you’ve already tried on a problem, you and your pair programming partner will have your questions more clearly formulated for really productive office hours with TAs.
As I mentioned, you’re working on adding to code someone else wrote in ML, which probably isn’t your main language, so the interpreter problems in 105 make a great place to develop or improve your style for your code notes. Everyone’s notetaking technique is different, and there’s no wrong way to take notes as long as they’re making you more productive. What I find to be really effective in my style, though, is the use of color coding and sectioning so my eyes have to do less work to find my ideas or concerns on the paper, and the small set of abbreviations I use to write quickly and still understand the notes (some of my symbols, I got from this class!). I talk about my technique in detail in this blog post I recently wrote, but below you can see a 1-page summary of my style.

By the way, building a consistent style for your coding notes isn’t just useful for COMP 40 and 105; both when I do startup work on the job and side project work at home, I regularly take handwritten notes. That way I know which things I should read, who I need to talk to in order to move forward on a problem, which unconfirmed or known bugs to keep track of, and where I was last time I was working on a feature that I’m coming back to to finish. This is especially helpful at a software engineering job where chances are, you’ll be using multiple programming languages together, for example if I have to keep track of how my Go code on the backend talks to the JavaScript on the frontend, or if I have to understand a Makefile or shell script.
Where to go after 105
Like I said at the beginning of this post, one of my favorite things about 105 is that it sets you up to quickly learn any new programming language you want, and with so many languages popping up, it’s a great time to do just that. I highly recommend learning more functional programming with the knowledge you will have gotten in 105 since it’s getting popular even in imperative languages. In Go for example, it’s common to pass a function in as an argument to another function, for example in web middleware. Functional features are also in newer versions of the big-name imperative languages Java and C++, so functional programming is here to stay.
Haskell is the main language I recommend learning straight out of 105 because in addition to being my last name, it has all the best features of Standard ML like pattern matching and type inference! Also, while Haskell is stereotyped as something only academics use, that’s rapidly changing; startups like Helium, an Internet of Things startup, use Haskell in production, so if you thought ML’s type system was cool but you want to code in industry, don’t be discouraged by Haskell’s reputation. You can check out the video below to hear about how Helium uses Haskell in production.
If you were new to functional programming before 105, this class also teaches you how to tackle new programming paradigms. That you can use to learn concurrent programming, where you write code to do things simultaneously. Functional languages like Erlang and Elixir are natural fits for concurrency since they offer the safety of working with immutable data, as well as a history of being used for telecommunications. But these days concurrency is becoming easier in imperative languages too. While pthread.h is a nightmare to work with in C, Go uses a “share memory by communicating” style for intuitive concurrency, and Rust’s ownership system guarantees safety when working with your concurrent code, plus a sweet Haskell-like inferred, generic type system.
By the way, if you’re gonna be at Tufts or close to Boston after 105, you’re in a city with AWESOME programming communities. You can find a Boston group on Meetup for just about any language you want to learn, so you can meet professionals in your favorite languages, learn how to code in them like a pro, find contributors for your own projects, and even give tech talks. If you’re learning a language, going to these meetups is a great way to really bring the language to life! I happen to be an organizer for Boston Golang, and if you’re interested in Go, all Go experience levels are welcome at our meetups!
If you’re in 105, while it’ll be a hard class, there is a ton you can learn there that you can use as a polyglot programmer and as an engineer in general. If you make yourself a regular at office hours, pair program, do the reading in advance, do what you did to succeed in 40, have self-compassion, and take notes, the class will get a whole lot easier and you’ll get more out of it. Best of luck, Jumbos, and stay slothful!

