Recently, an interesting question popped into my head: how would I rank my high school classes from most to least useful in terms of preparing me for a career in software engineering? Or asked another way: of the skills that I use on a daily basis to do my job, which high school classes were responsible for seeding me with the knowledge and experiences to develop each of those skills? For the standard set of four subjects that everyone takes, my ordering would be as follows:

I expect many readers to be surprised that English is second in my list, ranking above science. Though before getting too excited, please recognize that this is more of a thought experiment for students who are determined to become software engineers than a proposal for how to reallocate classroom time for all high school students, in general.

Math

It should come as no surprise that the first subject on my list is math. It's not that you have to be good with numbers to program a computer, but designing good software often requires the same type of abstract thinking that is used to solve high school math problems. Consider the following type of question that frequently appears on the SAT I Math section:

The average math student will try to solve the problem mechanically, trying to use the techniques that they have learned for combining two equations to eliminate a variable, solving for the remaining variable, and then using that result to determine the value for the other variable. Upon solving for both variables, it should be trivial to determine the value of (x + y). Though if you try to solve the problem in that fashion, you will likely bury yourself under a heap of scratch work.

By comparison, the astute math student (or the one whose parents paid for an SAT prep course) will realize that he is not asked to solve for x and then y, but rather the quantity (x + y), and that the former is not required to produce the latter. Such a student understands the abstract concept of equality, and can leverage it to find the solution. Instead of focusing on the concrete values of x and y, he focuses on the abstract representation of the quantity (x + y).

Because multiplying equal quantities by the same value yields two quantities that are also equal, we can manipulate the first equation as follows:

4xy = 6
(½)4xy = (½)6
2xy = 3

Further, because equals added to equals are also equal, we can add 2xy to the left of the second equation while adding 3 to the right side while preserving the equality:

x2 + y2 + 2xy = 13 + 3

With a little manipulation, this can be expressed as something more familiar that can be reduced:

x2 + 2xy + y2 = 16
(x + y)2 = 16
(x + y) = ±4

Therefore, the solution is (B), 4.

As you can see from Wolfram|Alpha, all of the possible values for x and y can only be expressed using square roots, so the mechanical approach to solve for x and then y would have been very messy. Because the values of x and y are irrational, it is also impossible to precisely graph the solution on scratch paper to find the correct answer. Finally, this question is also devilishly designed to defeat a student's attempt at "backsolving," which is the process of plugging in each of the five multiple choice answers back into the original equation to try to find the one that works.

To reiterate, the only practical way to solve this problem is through abstract thinking, as more familiar, concrete solutions (mechanically solving for a single variable, graphing the equations to find the solution, backsolving) are not practical. In writing software, programmers frequently create abstractions to manipulate information to solve problems. Although there is also a physical representation of the information in the real world (in the form of computer memory), it is not practical for a software engineer to inspect or manipulate it directly. This is why the type of problem solving done in high school math class is so helpful in designing software.

One final point I would like to make about the relationship between high school math and software engineering is that calculus is much less important than you would think in order to be a great programmer. Now, most good software engineers are good at math and will have likely taken calculus and will have done well and enjoyed it, but it is by no means a requirement. Many smart software engineers do a lot of great work without ever calculating an integral or derivative. (And no one uses that multivariable shit. Trust me.)

I feel compelled to point this out because some high schools offer an alternative high level course called "discrete math," which I believe is far more useful for a programmer. The parallels between doing inductive proofs in discrete math and coding a recursive function are striking. Unfortunately, because discrete math is not an AP course, I expect many competitive high school students may dismiss it because they are focused on racking up as many AP credits as they can. Nevertheless, rest assured that as a software engineer, you will use far more discrete math than calculus in your daily work, so the more of it you can get, the better off you will be.

English

As a software engineer, I spend a lot of time reading email, writing email, writing documentation, and communicating via instant messenger. Even at a small company where all of the engineers are in the same room and we could have the bulk of our discussions in person, we often opt to communicate through an electronic medium. Outsiders may jump to the conclusion that we're just a bunch of antisocial nerds who are too introverted to speak to one another face to face, but that's not it at all (according to Myers-Briggs, the extroverts have a slight majority on our team!). Consider some of the advantages of having a discussion over an email thread rather than doing it in an in-person group:

When trying to recall the conversation, it is possible to search for it and resurrect it in its entirety without any loss of information. The information is still accessible to others after those who contributed to the conversation have left the company, and could also be forwarded to those who have joined the company after the conversation happened.

Responses can be asynchronous rather than synchronous. For less technical readers, that means that when someone responds to the thread, it is not required that someone else immediately respond as social conventions would dictate in a personal discussion. This affords those responding the opportunity to research their response before giving it. This allows others to work on other things while waiting for a response, saving a lot of people's time. Further, because responses are researched, they can be of higher value.

Those who are not physically present (because they work remotely, are out sick, etc.) can have an equal say in the conversation as those who are physically present. (Though admittedly, those who are not in the physical office may miss out on side conversations that might heavily influence the discussion on the email thread.) Many successful open-source projects are maintained by engineers who have never even met!

Rather than enumerate all of the benefits of email (which no doubt also has its share of drawbacks), let us just agree that being a software engineer entails dealing with a lot of written communication. Surprisingly, much of this communication is in English prose rather than in software code. Therefore, being able to write well is an important skill for a software engineer.

This includes grammar and spelling! Especially spelling, as creating variables with misspelled names is infuriating to those who know how to spell, and such misspellings have a tendency to proliferate throughout the codebase once they are present. As is the case for all things software related, a programmer's worst nightmare is inconsistency, be it in the data model or in named references in the source code. In the case of spelling, a misspelled word can defeat what would otherwise be a trivial search-and-replace operation. Such an inconsistency creates an exceptional case which fails to get updated along with its brethren, and suddenly it's time to break out the debugger.

Although grammatical errors in comments are not as likely to result in software errors as misspelled variable names, bad grammar becomes jarring to those who are trying to understand the comments in your code. More importantly, if you want to advance in your career from individual contributor up to architect, you will likely have to produce design documents, which often require many pages of prose. Therefore, even if your design document is free of technical errors, an abundance of grammatical errors will obfuscate your ideas, making it very difficult to communicate them effectively.

Similarly, it is also important to have a good command of vocabulary, not so much that you use a lot of "SAT words," but that when you do, you are sure to use them correctly. As my high school English teacher Mr. Moran taught us, all of these types of errors cut away at your ethos, which detracts from your credibility with your audience. In software where you may only communicate with remote coworkers through email, a carefree attitude towards how you compose yourself in writing may limit your career advancement.

Though despite my emphasis on the importance of high school English, I think that it would be far better if it were divided into two subjects: rhetoric and literature. If English were divided this way, then my list would be as follows:

Math

Rhetoric

Science

Social Studies

Literature

Or thought of another way, let's prioritize subjects about "shit that actually happened" over subjects that are about "shit that didn't." It's not that I want to live in a world without art (I don't!), but for the purposes of this thought experiment, not having read Twelfth Night has never, to my knowledge, held me back in being successful as a software engineer.

Personally, one issue I had with the approach to literature in school was that, starting in middle school, reading transitioned from a privilege to a chore. That is, in elementary school, if you were done with your work, you "got to" read. There was a small carousel of children's literature in the classroom (not picture books, but your Encyclopedia Brown and Judy Blume books) that you could pick from, sit quietly, and enjoy. The quicker you finished your work, the more time you got to read.

Then starting in middle school, reading felt a lot heavier because most of the reading I did was "assigned." One of the first things we read in sixth grade was And Then There Were None by Agatha Christie, and "reading" was now "homework," as we were assigned to read a fixed number of chapters a night. Because it was a mystery novel, we were also instructed not to read ahead, for fear of spoiling what happened for the other students.

Now is that any way to develop a child's appreciation for literature? To partition it out into little bits that have to be checked off one night at a time? To stymie any excitement about the work by having a predetermined limit about how much of it to read? Perhaps I interpreted things too strictly (I was twelve!), but I got in the mentality of reading no more and no less than what was "assigned," and the amount of pleasure reading I did dropped off precipitously in middle school and never recovered.

Science

When I think of a high school science curriculum, three year-long subjects come to mind: biology, chemistry, and physics. They are generally taught in that order, which I argue happens to be the inverse of the order of which they are of use to a software engineer (though this is unsurprising, as the later subjects require students to have more math classes under their belt). Without question, an understanding of physics is much more important in producing Angry Birds than an understanding of ornithology ever would be.

But why is science not at the top of this list with math? For sure, the scientific method has a strong analogue in debugging software: identify a problem, propose a hypothetical solution to the problem, and perform an experiment that will either verify or reject the hypothesis. How could anything be more similar to the tasks of a software engineer?

From what I recall of high school science class, students are rarely responsible for identifying the problem, proposing the hypothesis, or formulating the experiment to test the hypothesis. Instead, the teacher provides all of these things which is collectively called a "lab," and the responsibility of the students is to "do the lab." Doing the lab is more about following directions and cleaning the equipment when you are done (which is more analogous to the cooking class we were required to take in eighth grade) than problem solving, which is really the impression of science that students should come away with.

Of the three primary science courses, doing physics problems has the strongest analogue to writing software. In mechanics, the challenge is often to take an unsolved problem from the physical world, represent it in a mathematical system such that the problem can be solved, solve it, and then map the solution back to the physical world. Such problems are solved not through direct observation, but by reasoning.

My impression is that, generally, the goal of science is "to explain phenomena." Most people assume that a "phenomenon" is anything they don't understand, but actually, a phenomenon is "an observable fact or event." That means that just because someone doesn't understand computers, that doesn't make it right for them to computers a "phenomenon."

When you think about it that way, the goals and techniques of a scientist are often very different than that of a software engineer because the engineer primarily works in the non-physical world of information. As famously described by Fred P. Brooks in The Mythical Man-Month: Essays on Software Engineering: "The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination." In this way, the programmer has to reason about things he cannot see, about quantities of information that are too large to represent in a physical realm. To solve problems in this domain, he must find a way to represent the problem in the memory of computer, write software to manipulate that memory, and then translate the state of that memory into a real-world solution. The software engineer's only practical option for problem solving is to work in the abstract, whereas the scientist may often fall back on making observations in the physical world as an alternative to mathematical modeling.

Social Studies

When I originally conceived of this question and tried to answer it for myself, I realized how spectacularly little of what I learned in social studies has any impact on my performance as a software engineer. I know, I know: "Those who do not learn from history are doomed to repeat it." That said, I do not feel "doomed" to inadvertently enslave thousands of people and build a giant pyramid in the middle of a desert, though I do admit that without a good understanding of Silicon Valley in the late 90s, I could be doomed to repeat the mistakes of the engineers from that time period. (Incidentally, one of the most compelling history lessons from my undergraduate CS education at MIT was about Therac-25.) But of those two topics, which is an aspiring software engineer going to be likely to learn more about in his high school social studies class today?

Personally, I think that replacing social studies with a 40-minute period where students are required to read The New York Times (or equivalent) and then discuss the most pressing issues of the day would be a better use of their time. Today's news is tomorrow's history, is it not? Further, as the world has changed so dramatically in recent history, it makes the world of today that much different from that of ancient history. It stands to reason that to solve the problems of today, we could learn a lot more from studying the past 100 years in detail with less emphasis on older civilizations, though my recollection of the curriculum of my high school social studies class was that it was quite the opposite.

Conclusions

I am a software engineer, which requires a certain skill set to succeed. I recognize that there are other jobs that require different skill sets, and that most students attend a public high school that is designed to empower students to succeed in potentially any field, not just software engineering. This is a difficult and ambitious goal.

I am not an expert in education. But that said, in an April 2009 speech to Georgetown University by President Obama, he called for an increase in engineers to help stimulate our economy, so it is worth asking how America's public school system can be changed to help achieve that result. For example, my English class in middle school took up two periods whereas my math class was only one (at the time, I desperately wished it were the reverse). In a world in which producing the best technology is critical to success, it is worth asking whether that allocation of classroom time should be swapped.

Detractors from my argument may claim that students need a balance, though those that do are missing the point: this is a hypothetical ordering for students who have made the decision to succeed as a software engineer. For the purposes of discussion, I am assuming an extreme.

But at the same time, if we look at many of the world's greatest innovators, the "bright minds who are going to save our economy," "balanced" is not often used to describe them. Most of these unique individuals are far more likely to be described as "manic," so perhaps an overly conservative focus on balance will fail to produce the talent we so desperately need. At least for myself, having had more math and less literature in high school would not have stymied my creativity: it would have empowered it. For others, it may have done the opposite: I only claim to know how I would spend those four years if I could do it all over again.