Thursday, December 15, 2011

Learning to think and learning to do

All knowledge falls into one of two categories: practical and theoretical. The key to a successful career in computer science is balancing your interest in both.

Theoretical knowledge

I consider any topic which is independent of a specific programming language or platform to be theoretical knowledge. Theoretical knowledge encompasses abstract CS topics, such as data structures and algorithms; the underlying mathematical concepts, such as graph theory, combinatorics, and automata; and the hard problems of CS, such as computer vision, artificial intelligence, etc. These are powerful tools for solving hard problems and building things which haven't been possible before.

However, becoming an expert on a theoretical topic won't get you any closer to building a successful iOS app or web service. Without practical knowledge, you'll be dependent on your partner, team, or organization to allow you to accomplish your goals. You won't be able to implement your ideas on your own.

Practical knowledge

Practical knowledge is the stuff you need to know to bring your idea to the world. It's the connection between abstract ideas and useful products. Practical knowledge includes programming languages, APIs, applications, etc. Mastery of a few practical topics allows you to quickly build something which others can touch and use. Practical knowledge also brings independence: you can start a business if you have something to sell.

However, practical knowledge isn't enough to change the world or even make a competent programmer. Without theoretical knowledge, you will waste time reinventing algorithms and trying to solve impossible problems. In addition, your plans will be bounded by the extent of your theoretical knowledge.

In practice, it's impossible to work in Computer Science or programming without some knowledge from the opposite field. Nevertheless, you can't reach your potential in either field without seeking a balance theoretical and practical knowledge.

Friday, November 11, 2011

Landing the perfect research internship

If you're considering grad school (and you should), you owe it to yourself to experience research for yourself before you make a decision. Spend a summer working on a research project at a university, and you'll know whether research is for you. Below, I share my advice for finding and landing your ideal research internship.

1. Find your internship

The first step to getting the perfect internship is finding the perfect internship for you. You need to consider things like location, pay, required skills. Pick at most ten internships to pursue further; if you apply for many internships, you won't have the time to form relationships with your potential researchers.
One great place to find research internships is the National Science Foundation. They fund REU (research experience for undergraduates) programs at schools across the country. You can find a list of participating schools on their website. Here's a list of organizations offering undergraduate research opportunities. Some universities offer independent research internships which they fund themselves. If you have a particular university in mind, try exploring their website to see if they offer independent internships.

2. Research the positions

This is the most important step in the process: learning about the positions. For each position, you must determine whether you want it and whether you're qualified to fill it.
First, sift through all the research opportunities available through each internship and find some which interest you (or don't bore you). This is difficult because you don't know enough about the research domain to make an informed decision. Keep cutting until you're left with a group of projects you can see yourself working on.
Second, read some research papers about the projects in which you're interested. Projects' websites rarely have the information you'll need to make your decision. You need to determine whether you're still interested in the project and whether you have the skills necessary to contribute to it. This process also gives you more information about the researchers.

3. Make contact

Before you even write your application, you should start a conversation with the researchers you're hoping to work for. Establishing a connection before the application process is the best way to improve your chances.
Contacting a researcher at a large university directly, however, can be a challenge. Sending an email is like playing the lottery: the odds are good that you will never receive a response. You can increase your chances by contacting the researcher's grad students, secretary, or postdoc students first. Other possible approaches are calling the researcher and sending them a letter. The keys to success are creativity and persistence.
Protip: If your researcher has a postdoctorate student, contact them first. They have more time than the researcher or their graduate students.
Your first email must be "perfect": free of spelling, grammatical, and cultural errors. The goal of this email is to give the recipient a reason to reply and give them no excuse to ignore it. It must be as short as possible, conveying only the core of your message. Exclude flattery, greetings, and anything else that isn't vital to your message. Don't attach your résumé; that's disrespectful of your recipient's time.
You have several options for the content of your message. You could ask a question about a project or ask whether the researcher is looking for a summer research intern. You may include some brief statement of qualification if it's relevant, but it's not necessary.
Below is the first message that I sent to Dr. Roy Campbell, my researcher for my internship at the University of Illinois at Urbana-Champaign:
Subject: ITI Undergraduate Internship question
I'm planning to apply for the ITI Undergraduate Internship program, and my first task is finding the professors with whom I would like to work. If I were to spend the summer working with you on your research, what would I be doing? I'm particularly interested in your research on p2p distributed operating systems and ubiquitous computing. Would I be able to choose my topic of research? Thanks for the help.
It has twice the lines that it should have, and it contains two dumb questions. However, it demonstrates my communication skills gives him a reason to respond. In that respect, it does its job.

4. Do the work

Once a researcher has responded to one of your messages, start reading everything you can find about their research and the surrounding field, starting from the most recent. Pick a interesting project from each researcher, but don't become attached to it. The more knowledgeable you are about a researcher's work, the more professional and motivated you'll sound to them. Plus, it's good practice for your internship.

5. Write your application

Writing an application is probably the least important step in the application process. However, it's also the step most likely to keep you from an internship. Your application must be "perfect" in the same sense as your first message, but it need not be a literary achievement. It should tell the reviewer why you would be a productive research intern. Anything irrelevant to that goal should be excluded.
Protip: Don't list "communication" or "writing" as one of your skills. If you can write, it will show in your application.

6. Follow up

If the website for your internship program doesn't mention a decision date, plan to contact the program administrator two or three weeks after the application deadline to ask about the status of your application. This step has two purposes. First, it helps you learn the decision on your application sooner. Second, it keeps the process moving. Without supervision, the application process could stall for months.


A research internship is a great way to learn about research and the grad school experience. They key to landing one for yourself is finding the right one and connecting with your potential researcher. Good luck!

Monday, September 26, 2011

My Summer Internship

Last summer, I researched cloud network security through an internship with the Information Trust Institute at the University of Illinois at Urbana-Champaign. It was the best summer I've ever had.

First, it was exhilarating and terrifying to move to a new city with only the things I could carry on a plane. I spent my first weekend in Urbana acquiring the things I needed to live: food, towels, toiletries, and a bicycle. Once I had settled in, I found Urbana-Champaign to be a wonderful place to live. When I spent time exploring the city, it rewarded with delicious restaurants, fascinating architecture, and stimulating culture. Exposure to Black Dog's barbeque pork sandwiches and brisket burnt ends and Murphy's Pub's hamburgers has destroyed my appetite for the substandard barbeque and burgers I've found here. Every day I wish I were back in Urbana.

Second, I enjoyed working on something substantial. My job was to research computer network security, devise a new network security system, build a prototype, and document the work. The research time gave me an excuse to learn how networks work. The planning stage introduced me to the process of brainstorming and planning with a team. In the prototyping phase, John and I managed to assemble a test network with 32 virtual machines, build two prototype security enforcers, and test our prototypes on the test network. To document our work, we created two posters and wrote a research paper which will be published by the International Workshop on Resilience Assessment of Complex Systems 2011. I'm proud of what I accomplished during the summer.

Third, I was honored and delighted to befriend my colleagues and fellow interns. It was a thrill to work closely with John, my partner on the project. We spent hours together slinging code, debugging the test bed, and writing posters and papers. I also enjoyed eating lunch with the other ITI interns Tuesdays and Thursdays at the internship seminars. On the weekends, my posse and I would meet to go bowling or eat dinner. We also had a few events at Europa House for all the summer iterns: a Walking Dead marathon, movie nights, and potlucks. The things I miss most about last summer are the friends I made. However, I expect to meet them again in the coming years on the cutting edge of industry and computer science research.

In summary, my summer internship at UIUC allowed me to live in a new city, research cutting-edge technology, and make new friends. Next summer will be even better.

Monday, July 18, 2011

My epic internship quest

Here's the story of how I spent four months of my life locating and applying for internships.

My initial plan was simple. Spend the summer doing a research internship at a major CS university to simulate pursuing a postgraduate degree. I had been receiving contradictory advice on whether I should attend grad school or go straight to work once I finish my Bachelor's degree. I thought I would settle the issue by experiencing research first-hand.

I applied to two REU programs: the Information Trust Institute at the University of Illinois at Urbana-Champaign and the Summer Undergraduate Program in Engineering Research at Berkeley – Information Technology for Sustainability at the University of California Berkeley. I sent seven inquiries by email to professors from both programs, receiving two positive responses. I spoke with Dr. Roy Campbell, a researcher at UIUC, and Leo Meyerovich, a grad student working with Dr. Ras Bodik at UC Berkeley. I submitted my applications successfully around the middle of February, although my UC Berkeley application was a day late.

During the application period, I stumbled upon another internship opportunity I couldn't ignore. Fog Creek Software in New York, NY was looking for a summer intern to help them build tools for programmers. The idea of working in New York under the venerable Joel Spolsky was irresistible. I didn't think I had a chance, so I drafted an email of application and sent it within two days. I didn't want to waste too much time on a fantasy.

When Fog Creek contacted me to set up a phone interview, I was both surprised and elated. I solved a few programming challenges from Project Euler to prepare for the programming examination, and I tried to anticipate the interview questions. Unfortunately, I forgot about most important question, "What programming projects have you done recently?" When the interviewer asked that question, my confidence was shattered, and I slipped into panic mode. During my programming test, I forgot how to use static variables, writing some terrible C. However, I spent my next class mentally debugging it, and I rewrote, tested, and resubmitted a not obviously broken version with a brief explanation later that evening.

At the end of the interview, I was told that I would be told whether I got the job within a couple days. I didn't hear back for about a week. At the time, I thought that meant that everybody at Fog Creek was too busy to bother sending me a rejection email, but in retrospect, I was probably a finalist who wasn't ruled out until the end.

Around this time I realized that what I wanted was an industry internship, so I refocused my efforts on finding an internship with a big tech company. I started gathering links and working on my resume.

Early in March, I heard about the Cascadia Fellowship, a program that matched technical students with Seattle-based startups. I answered a couple questions and provided a statement of intent. The following week, I received a mass-mailed rejection, in error, and then a personalized request for my resume and couple programming puzzles. Everything was due the following day. However, before the deadline, they sent me another impersonal rejection email. I ignored it and submitted my code before the deadline (barely). When I hadn't heard from them for a week, I asked if the second rejection was sent in error. I never received a response.

It was late in March now, and I didn't have an offer. I had narrowed down my list of major tech companies offering summer internships to Facebook, Google, Microsoft, and IBM. I missed the unpublished deadline for the Facebook software engineering internship, so that left Google, Microsoft, and IBM. I wrote a spartan list of reasons for Google to hire me and submitted my application. I filled out Microsoft's on-rails application, and submitted that next. Finally, I answered IBM's primarily experience-related application and turned it in.

After all this, I had only to apply to one more program: the Google Summer of Code. GSoC was my ultimate fail safe. I was accepted last year, and I felt that I had the process figured out. Unfortunately, I didn't have much time left to apply; I hadn't even looked at the list of mentoring organizations when the student application period began. I had eleven days to find at least two interesting organizations, pick interesting summer projects, and submit a detailed proposal to each, plus another two weeks to convince the organizations that I could complete my chosen projects.

I chose two organizations: Learning Unlimited, producers of a sophisticated Django-based web app; and Sencha Labs, developers of the JavaScript InfoVis Toolkit. I thought that LU was a long shot, but I found the project more interesting than the JIT. I split my application time between designing a student registration system for LU and fixing bugs for JIT. I had some independent experience with JavaScript graphics, and the project I chose was well within my capability, but I got cocky. I didn't spent nearly enough time learning about the core library; I simply assumed I would get the project. I worked hard on the LU project because I wanted it more and it was far more demanding. In the end, I was rejected by both projects because I didn't focus on either one. If I had dedicated myself to either project, I would've gotten it.

After the GSoC application deadline but before the decision date, I received a surprising message from UIUC. Dr. Masooda Bashir informed me that two researchers were interested in working with me over the summer, Dr. Klara Nahrstedt and Dr. Roy Campbell. Dr. Nahrstedt asked me for my resume, but Dr. Campbell remained silent. I sent him an email asking what he would be working on over the summer, but I didn't receive a response.

At this point, I was frantic. I hadn't received a positive response from any of the companies I had applied to, and when I didn't receive a decision from Drs. Campbell and Nahrstedt, I assumed that I hadn't made it into the highly competitive ITI internship. I tried to start over, looking for less exclusive internships, because I didn't want to waste my summer taking classes.

It was the beginning of May now. I had almost given up, but I decided to ask Drs. Campbell and Nahrstedt for final decisions. When I asked them whether they were still interested in working with me, Dr. Nahrstedt told me that I hadn't made the cut, but Dr. Campbell responded with an enthusiastic "Yes!" It was almost too late to file the paperwork, but Dr. Bashir came through for me. I received the official offer letter May 4.

Now, I've spent half my summer working at the University of Illinois at Urbana-Champaign, and I couldn't be happier. You could say that all my hard work paid off, or you could say that I got lucky at the last second. Either way, I'm just happy that I won't have to submit any more applications until the fall.

Sunday, March 20, 2011

Lessons from gonzo programming

I recently experienced writing code under a looming deadline for the first time. After applying for the Cascadia Innovation Fellowship, I received a request for my résumé and two code samples due the following day.

The request described two pieces of code and asked me to implement them. I started immediately, dispatching the first with little effort and working on the second for a couple hours in the evening. Then, I unwisely decided to stay up to finish my second sample. I “finished” the code, “tested” it, and, satisfied, went to bed.

The following day, I worked on my résumé for most of the day, looking at the code again late in the evening. A simple test revealed a fundamental flaw in my algorithm, and I stayed up until 2:30 AM rewriting the algorithm, submitting my code only 30 minutes before the deadline.

I feel pretty good about my final code, but I didn't enjoy staying up late and coding frantically.

I learned a few valuable lessons worth sharing:

  • Test thoroughly. If you're not trying to break your code, you're not testing.
  • Prioritize. My résumé contained virtually no information I hadn't already submitted through my original application, yet I spent precious hours polishing it obsessively. I knew that the quality of my code would be the most important factor in my application, but I left my coding until the last minute.
  • Use the obvious solution first. When I first considered the second piece of code, I skipped over the obvious solution in favor of a “faster” and “more general” solution that didn't work. I made the classic mistake of trying to solve a recursive problem non-recursively without first implementing the intuitive solution.
  • Use git. After identifying the fatal flaw in my original code, I attempted to solve it with a set of small changes throughout the program. After working on the algorithm for about an hour, I rediscovered the obvious solution which was based on my original code. Thanks to git, it was easy for me to stash my changes in a new branch and resume work on my original version.
  • Don't use C++. Because the prompt implied that solutions should be written in Java, I started working in C++ and asked if that would be OK. Instead, I should have asked if I could use Python: both of the challenges would have been almost trivial in Python.
  • Never be without Programming Pearls. I left my copy at my dorm when I went home for spring break, so I couldn't refer to it to help me solve the problem. From now on, it's not leaving my side.

Saturday, February 12, 2011

Thoughtfully designed electric razor

When I plugged in my inexpensive electric razor to charge, I pleasantly surprised by this delightful animation. I deeply respect this level of attention to detail. Whoever created this animation has converted at least one Remington user into a loyal Remington customer.

Saturday, January 29, 2011

Why I want to work at Fog Creek

I'm applying for a summer internship at Fog Creek Software, a well-respected software company in NYC. I'm going to be interviewed by one of their developers next Tuesday, so I've been trying to anticipate the questions I will be asked and give them some thought. Tonight, I asked myself a simple but important question: "Why do you want to work at Fog Creek?"

First, I thought I wanted the experience. An internship at a reputable software company would look great on my résumé. I briefly considered whether I was in it for the office. Then, I thought that I wanted to prove to the world that I could build software, not just make little toys and read big books. However, I quickly realized the true source of my motivation: I want to work at Fog Creek to prove to myself that I can build software.

Until now, my most substantial project has been my work on OpenInkpot last summer. Assembling a cross-toolchain is highly technical work, but it's not a creative act. I didn't design the structure of the toolchain; I just put the pieces together.

I've tried to prepare myself for a career as a software developer by reading books on software structure and construction, but I know that's not enough. I won't know that I'm ready until I've built something real.

To become a software developer, I must develop software.

Friday, January 21, 2011

I was dead wrong

More than a year ago, I posted Programming is more than pointers and recursion, arguing that CS students don't need to learn about pointers and recursion. I wrote it in response to The Perils of JavaSchools, a 2005 blog entry in the legendary programming blog Joel on Software. I realize now that I was dead wrong, and I've decided to explain why (not only because someone from Fog Creek Software will be evaluating my blog.)

My central argument was that since pointers and recursion aren't often used in the software development industry, they aren't necessary topics for CS curricula. I was high on Python and Design Patterns at the time and fervent in my belief that all problems could be solved with straightforward, readable code. What I failed to realize is that if you can't (not don't) understand pointers and recursion, you can't have a meaningful career in programming.

Understanding pointers means more than memorizing the illogical C pointer syntax. It's an understanding of the difference between reference and value, between creating lightweight pointers and copying massive objects. Any programming job that doesn't require you to think about whether a variable should be a pointer or a value probably doesn't provide any challenge or variety. It certainly wouldn't provide any job security or marketable skills. Pointers are fundamental to programming.

Likewise, recursion is more than replacing a function call with the function's body; it's an illustration of the encapsulation of functions. Recursion is a stepping stone to first-class functions and closures. These aren't academic knick knacks with no practical application; they are powerful features in many popular languages.

In summary, Spolsky was right and I was wrong. Pointers and recursion are powerful tools that belong in the belt of every software developer. If you can't learn them, stick to HTML and CSS.