Friday, August 12, 2022

CS content inclusivity guide

First of all, I am not an expert in diversity and inclusion. However, I have tried over time to learn more about how to improve my Computer Science curriculum to be more inclusive, and I have noticed what makes me personally feel excluded from other CS curriculum. I wrote this guide based on my experiences at Khan Academy (online programming courses) and UC Berkeley (CS 61A, 169A), and have shared it privately with UC Berkeley TAs and other CS teachers. I'm now sharing it publicly in case it's helpful for other CS educators.

Once again, I am not an expert, so I encourage everyone interested in inclusive CS content to learn more from others, like at the CSTA or SIGCSE conferences.

Avoid sensitive topics

There are many topics which can trigger emotional reactions in people. If you are specifically teaching those topics, then you can present those topics with the appropriate context and create a space where students can process their reactions. However, if a sensitive topic just happens to be the theme of a problem but isn't necessary for the skill being assessed, then it is usually a good idea to avoid the topic entirely and pick a different theme.

Common sensitive topics

Violence/Death. Unnecessary violence / military violence is often the theme of video games and frequently makes it into CS assignments as well. Some specific examples:

  • Hangman: A classic game but pretty horrific, especially when you learn about America's recent history of hanging men. You can instead call the same type of game "Word Guesser", and show a visualization like eating a cupcake.
  • Free Bacon: A rule in the 61A Hog game (which has since been renamed). Since bacon is derived from dead pigs, this can be considered an instance of death. Non-pork eating students may find it strange to implement such a function.
  • Ants vs. SomeBees: A 61A game where ants kill bees (which isn't scientifically accurate) and which includes function names like death_callback and ants like the TankAnt. This project still exists, but the hope is to either replace it or provide alternative projects of equal difficulty (since many students don't mind insect destruction).

Current events. A lot of current events are emotionally charged for the people affected by them- wildfires, pandemics, protests, political elections. Some specific examples:

  • People's Park. CS61A has an old midterm review question about People's Park, a park in Berkeley that is the subject of controversary. The question did not specifically bring up the history and the current protests around it, but students could still find it distracting, especially on an exam, since it could bring up a lot of their feelings about the issues.
  • Swain v. Alabama: An example used in the Data 8 textbook of bias in the jury selection for a Black man on trial. The example wasn't presented with the full historical context behind the conviction, and could easily lead to stereotyping and stereotype threat. It is difficult to bring in an isolated example of racism if you haven't fully delved into the racist history leading to that event.

Memes. Memes can be funny, but the humor can often be at the expense of someone or some group of people. For example:

  • "Karen": A 61A exam review question initially used a function named karen in an environment diagram problem about anti-maskers, based on the "karen" meme. We actually have students named Karen in our class, and I would hate for them to feel made fun of or singled out due to sharing a name with the meme. The function has since been renamed.

Harry Potter. This is a common enough theme that it's worth addressing specifically. Lots of people seem to love Harry Potter and injecting HP references, but there are two problems:

  • The author's political views: JK Rowling has publicly stated many views that are transphobic, so seeing Harry Potter references can remind students of those views and threaten their feeling of belonging. CS61A used to have Potter references in an OOP assignment but changed it in 2021.
  • Assumed cultural content: Not everyone has seen Harry Potter, so assuming that everyone has can alienate those who haven't, since they aren't in on all the references. Khan Academy used to hold a Harry Potter themed company hackathon for many years, and I was always perplexed by the many references throughout the week (like the houses), but they finally changed the theme in 2020.

Historical figures. Quite a few of the inventors of the past (and even the present) have held views that are racist, sexist, or discriminatory in some fashion. If you do mention a specific historical figure in the content (either as the theme or because they invented a theory), first research their views and see if they have publicly espoused discriminatory views. You might then decide to remove the mention of them, de-emphasize them (versus their invention), or acknowledge the impact of their views. For example, Isaac Newton came up with theories in support of scientific racism, so physics departments have started to call his physics laws the "fundamental laws of physics" versus "Newton's laws".

Cultural relevance

Something has cultural relevance if it relates to our culture in some way, helping us connect CS topics to the rest of our lives and society. However, we have a diverse student body and may not share the same cultures. Thus, in a class of mixed cultures, there are several aspects to making content more culturally relevant:

  1. Check what culture your content currently assumes.
  2. Remove unneeded assumptions about cultural knowledge
  3. Diversify the cultural connections in the content

Step 1: Audit the default culture

Generally, the default culture in US content is White, European, Heterosexual, Male.

For example, 61A has many Shakespeare quotes in the textbook, lectures, and assignments. Shakespeare is certainly not the only poet in the world, and his poems don't make a ton of sense unless you've studied them. However, there's an assumption that everyone knows/likes Shakespeare if they're in the US.

Screenshot of a textbook chapter about Python that starts with a Shakespeare quote

Here's another example from a tutorial I made for Khan Academy, where I assumed that our mascot Winston would of course get married to a woman and have some kids. Now, as someone who's made the decision to not get married but am too nervous to tweet that in a marriage-normative society, I sure wish I had made a different choice!

Screenshot of a JS program that assigns a wife to a Winston object

Of course, lots of people do like Shakespeare and lots of men and women do get married, but it's too easy to write content in such a way that assumes that as the universal truth and does not make space for non-default culture.

If you audit your content to ask "what is the default culture?", you can be aware of what your content assumes and can then decide whether to reword or replace cultural references.

Step 2: Remove assumptions about shared cultural knowledge

It's fun to use cultural references when developing CS content, and it should be totally okay to bring in a cultural reference that's near and dear to you but may not be familiar to students from other cultures. However, when you do bring it in, be careful how you word it and be sure to provide any necessary context.

Consider these examples:

  • Magic 8-ball: I have a project on Khan Academy where students code a Magic 8-ball. I discovered that international learners struggled to complete the assignment, because they had never encountered a magic 8-ball toy. So I added an introductory sentence along with a graphic, and it was much easier for them.
  • Riffle shuffle: A 61A problem started with "The familiar riffle shuffle results in a deck of cards where…". Any sentence that starts with "the familiar" should raise flags, since familiarity is culturally dependent. I personally had never heard of it, and wasn't helped by the GIF that only showed the second half of the shuffle. I reworded to "A common way of shuffling cards is known as the riffle shuffle" and replaced the GIF with a video of the shuffle from start to finish.
  • Magic the Lambda-ing: This 61A problem assumed Magic experience in multiple ways, failing to explain how cards were drawn and using abbreviations like "stat" and "ATK". Generally, any non-course specific abbreviations should either be avoided or be explicitly defined. I revised the problem by adding clarifications, removing abbreviations, and adding a reference for students who wanted to learn more: "This game is inspired by the similarly named Magic: The Gathering."

Those were all fairly subtle rewords, but a subtle reword can turn a problem from one that alienates a student into one that introduces them to some new cool thing.

Step 3: Diversify the cultural references

If you have the means to authentically do so, you can now start to bring in more cultural references. A TA that loves cooking can bring in cooking examples, a TA that loves hair braiding can show how to make braids with loops. It's difficult and risky to bring in authentic cultural references from a culture that isn't experienced by any of the content creators. That's why it's important to have a diverse team, since each of your team members can make different cultural connections that might resonate with different students.

Here's a word cloud of interests from 61A students. Seeing the wide range of interests can inspire ideas for connecting content to student interests:

A word cloud of interests, like cooking, reading, video games, etc

One way to bring in culture that's relevant to your students is to get them to bring it in themselves!

  • In lectures, when live coding, you can ask students for examples, like "Okay, what are 5 song titles we can store in this array?"
  • In coding assignments, find ways for students to express themselves. For example, Khan Academy includes projects like drawing a dinner plate or making a recipes webpage, where students can show off their favorite foods. It is harder to evaluate the correctness and skill level of more open-ended projects, especially in massive courses. However, even if you can find small ways for students to customize their program output, it can increase their sense of ownership. (See this great research on creativity, customization, and ownership)

If your curriculum references historical figures (e.g. the inventor of an algorithm), they are very often white/male/European due to the bias of historical texts and a long history of patriarchy. See if you can find lesser known figures that also made contributions (a few examples here), or consider whether it's really necessary to emphasize the inventor (versus the invention).

Mirrors and windows

Another way to think about your content is to make sure it both offers mirrors (reflections of each student) and windows (views of other students), and gives equal weight to all the possible mirrors and windows.

Names. On Khan Academy, we use names in many word problems. To make sure we're not just picking the names that we personally know, we use a random name generator:

Three screenshots, two of word problems with names Hong Lien and Lakeisha, the third of a random name generator

Gender. Considering that gender is "a non-binary association of characteristics within the broad spectrum between masculinities and femininities," we should avoid encoding gender as binary in any content examples, like database tables, classes, or UI elements.

Consider instead a class like:

class Person() {

constructor(string name, []string gender, string pronoun) { = name;
        this.gender = gender;
        this.pronoun = pronoun;

new Person("Hunter", ["male"], "he");
new Person("Lee", ["female", "non-binary"], "they");
new Person("Emily", ["female"], "she");

Or a UI like:

A screenshot of a UI with a gender-picker that allows selection of multiple genders and offers a lot of possible genders

Pronouns.Similarly, refrain from relying on “he/him” as the default or assumed pronoun. Instead, be sure to use a natural, diverse selection of pronouns. I received bug reports for using "they" as the pronoun for a non-binary character in some AP CSP word problems on Khan Academy, but I kept "they" as I think/hope that people will become more accepting as their exposure to non-binary pronouns increases.

Sexual orientation. As discussed earlier, heterosexual is often the presumed default in our culture, but many people are homosexual, pansexual, asexual, etc. If you have content where it's appropriate to refer to people and their relationships, consider shining a light on the many kinds of relationships. We have a famous grammar problem on Khan Academy that brings in a ton of hate mail, but also brings in a lot of love mail from learners who have never before seen their relationships reflected in an educational website before! Here it is:

A fill-in-the blank problem with the sentence 'Brittany and Sofia went to lunch with their _ every Saturday' and options 'wifes' or 'wives'

Thursday, August 11, 2022

A browser-based runner for Faded Parsons Problems

A Parsons Problem is a kind of programming exercise where learners rearrange blocks of code in order to create functional programs, and has been shown by CS Ed researchers to be an effective way to learn code writing skills. One particularly helpful aspect is that students are re-creating an expert solution, versus writing sub-optimal or messy solutions, so they pick up better programming practices along the way. [See Barbara Ericson's dissertation for more details.]

However, one issue with Parsons Problems is that some learners may brute force the solution, trying all possible orders without thinking. Fortunately, UC Berkeley Ph.D. student Nate Weinman invented Faded Parsons Problems, a variant where the blocks sometimes have blanks in them, and learners must fill in the blanks after arranging the blocks. Learners are no longer able to brute force, but they still receive the other benefits of Parsons Problems. [See Weinman's CHI 2021 research paper for more details.]

While I was teaching CS61A at UC Berkeley, we experimented with integrating Faded Parsons Problems into our Python class assignments. To complete the problems, students ran a local Flask server on their own machine that sent data to our OKPy grading infrastructure. It seems to have been a positive addition to the course, though we discovered it was difficult for many students to run a local Flask server on their personal laptop. [A research paper is in the works with more details on what we learned.]

I wanted to try using Faded Parsons Problems in my upcoming Python course and to make it generally easier for any teacher to use them, so I've made a website that can run Faded Parsons Problems entirely in the browser (no backend). The website uses Pyodide to run the Python code and localStorage to remember learner progress.

The website checks the correctness of the learner's solution using Python doctests and displays pass/fail results. It also shows syntax errors, which can happen if they indent the blocks incorrectly or write something syntactically incorrect in the blanks.

The website is deployed on my Github pages currently, but it can be deployed on any static website hosting platform. If you're a Python teacher and would like to make up your own problems, you can learn more from the Github project README. Let me know if you end up using this in a class; I'd love to see your problems and hear how it goes.

If you teach a different language besides Python, it may be possible for you to get it working if there's a way to run that language in the browser. Forks or pull requests are welcome.

Tuesday, August 9, 2022

My bed-sharing setup

When I had my first baby, we struggled a lot with finding a sleep strategy that worked for both me and the baby. I talked about that journey in a blog post a few years ago, and how I ended up deciding to share a bed with my baby. I've now had another baby, and we're using the same bed-sharing approach again. Thanks to making the decision early on, I'm much better rested this time around.

Just like people share their office setups filled with geek gear, I'm going to share my bed-sharing setup. Maybe it'll help other breastfeeding mothers out there, or perhaps inspire someone to invent better gear!

Here's the sleeping setup:

Photo of floor mattress with sheets and pillows

Let's break down the sleeping components:

  • Floor mattress: 6" full-sized firm memory foam mattress. I bought the same one for baby #2, since baby #1 is still using it as a three year old. I figure these will be their mattresses for life, or at least their life in my house.
  • Slats: With my first baby, we had the mattress directly on the hardwood floor, and that led to black mold. I found some Korean-made slats on Etsy that fit the mattress size well enough and bought slats for both our mattresses. They're super low down so they don't make the mattress significantly higher (i.e. more dangerous in case of rolling), but hopefully they'll help prevent mold. Sadly, their Etsy shop is closed now, so you'd have to find similar ones or construct them yourself.
  • Bedsheets: You have to be super careful with bedsheets/blankets around babies, since they don't have the dexterity to move them away from their face. I wrap the sheet just around me, and often only use the blanket on the bottom half of my body. (Making milk keeps me pretty warm at night anyway, I often awake at 2AM in a sweat!)
  • Kindle: My favorite thing, both to help me fall asleep and to entertain me while nursing. I lean it against a pillow so that I don't have to hold it and can just flick it with whatever finger/limb is available.
  • Burp cloths: For late night spit ups. Yay.
  • Noise machine: The little elephant makes a heartbeat-like white noise. I'm not sure if it helps her, but it does help my partner to get less distracted by her little grunts and cries at night. We also have a humidifier in the room, as that's often recommended by doctors.
  • Alarm clock: I haven't set an alarm on it for years, but I do use it to make sure we haven't slept too long, since babies are supposed to nurse every 4 hours. Whenever I wake up, either due to my internal clock or her restlessness, I check the clock and decide if it's time to nurse.

So now let's talk about the nursing setup:

Photo of floor mattress with sheets and pillows in nursing position
  • Back support pillow: I lean against the wall while nursing, so this pillow makes that position more comfortable for me.
  • Boppy pillow: This is my favorite nursing pillow, and is the same model I use during the day.
  • Adjustable height pillow: I bought this to try as a nursing pillow (its intended use), but the form factor didn't work out that well for me. However, it's the perfect height/firmness to put under my knee when nursing, to elevate whichever side of the body my baby's nursing on.
  • Cooler: This stores an icepak and a Haakaa, a manual pump that works via suction only. I use the Haakaa to get extra milk out of whatever side my baby isn't nursing on, especially if she isn't eating much that night, and then I transfer the milk to a freezer bag in the morning. The Haakaa is an amazing invention, I still can't believe it works!
  • Nightlight: It helps to have a little light when positioning the baby. I also use my Kindle for additional illumination as needed.

That's my setup! I'd love to see more mothers sharing their gear. Let's nerd out on nursing! :D

Monday, August 8, 2022

Porting a project from spaces to tabs

I'm currently working on a JavaScript codebase that has some old crusty code, and I'm modernizing it in various ways, like upgrading to ES6 syntax and linting with ESLint. I also like to add in Prettier to every codebase, as an automated step, so that my code is always consistently formatted, and so that future pull requests from other developers can easily follow the same conventions.

But I had a dilemma: half my code was written with 2 space indents, the other half was written with 4 space indents, and I needed to tell Prettier what to use. What's a girl to do?? Well, I considered averaging it for nice 3-space indents everywhere (I kid, I kid), but I instead made a radical decision: just use tabs! I'd heard that Prettier is considering making tabs the default anyway, and after reading the many comments on their PR thread, I became convinced that tabs are better than spaces, at least for an autoformatted project.

Since my projects and editors have used spaces forever, there were a few things I needed to do in order to smoothly move over to tabs. Here's the steps I took:

  • Reformat files to use tabs. To change all my current files to tabs, I used Prettier. First I configured it by specifying "useTabs" in my .prettierrc.json:

    	"useTabs": true

    Then I ran the prettier command on all my JS/JSON files:

    prettier \"**/*.{js,json}\" --ignore-path ./.eslintignore --write
  • Ignore the reformat commit in git blame. I really hate when reformatting commits make it harder to use git blame to track logical changes, so I was thrilled to discover that there's a way for Git/Github to ignore particular revisions while blaming. I followed this blog post, adding a .git-blame-ignore-revs with my most recent commit:

    # Reformat js/json with Prettier, spaces to tabs

    Then I ran a command to tell my local git to ignore the revision:
    git config blame.ignoreRevsFile .git-blame-ignore-revs

    Once I pushed the commit with that file, I saw that Github does indeed ignore changes from that commit when I use the blame feature. So cool! Screenshot from Github blame UI

  • Make Github render tabs using 4 spaces.For whatever reason, Github defaults to 8 spaces for tabs, and that is too dang much. To make Github render the tabs in my projects with just 4 spaces, I added an .editorconfig file to my project:

    root = true
    indent_style = tab
    indent_size = 4

    Github also allows users to customize tabs across all project repositories, and that user setting takes precedence over the per-project .editorconfig setting. That's likely for accessibility reasons, since some folks might require a large number of spaces for better readability. To change my account preference, I opened up Settings > Appearance and selected my desired number of spaces:

    Screenshot of Github settings

    So, if I visit my project in an incognito window, Github will render the tabs with 4 spaces, but if I visit the project from my logged in browser, Github will render the tab with 2 spaces.

  • Make VS Code insert tabs when I tab. VS Code tries to adjust its indentation style with autodetection based on the current file, but I wanted to make sure it always inserted a tab in new files in my project, too. It defaults to inserting spaces when it isn't sure, so I needed to explicitly override that setting. I could have changed the setting across all projects, but most of my other projects use spaces, so I instead figured out how to change it in just this project for now.

    To change it, I opened up Settings > Workspace, searched for "insert spaces", and un-checked the "Editor: Insert spaces" setting. That created a .vscode/settings.json file with an "editor.insertSpaces" property:

    	"editor.insertSpaces": false

    Another option for VS Code is to use a VS Code plugin that understands .editorconfig files. If you go that route, you don't need to finagle with the VS Code settings yourself.