As a theoretical computer scientist, most of what I do is invisible. I can visualize it, but the work is still essentially invisible: you can't see it. The scratches on paper that I use to communicate with other theorists are just reminders, hints. When I sit on the bus, and I'm doing the work, the other bus patrons can't see the moves I'm making—they can't see that I'm doing it at all; and neither can my friends or family. They know I do something, which must be important to someone, but since they can't see it, they don't know what it feels like; they can't put any weight on the work I do.
To them I suppose it's something like being a "compliance officer." Surely those people do something, somewhere, to keep the world ticking, but I've never had any idea what.
Hereunder is a statement of what I do, and why, so that you (O my Unknown) can imagine it for yourself and judge it's value. I want to know what you think about it, so fire back, please.
My field is programming languages, which means that I want to design the tools that programmers use. In some sense, then, you can already see what I do: at least, you can see what the application programmers do (they make your email program and your web browser go) and you can imagine that I somehow support them. And on a concrete level, I guess all I want to do is to support the people who are making those apps, so that there are more good apps in the world. If you've ever used a great software app, then you know how good that can feel. And if you've ever tried writing a great app in a crummy language, then you have a sense of what I can do for the world.
But that doesn't quite convey the nature of my work—the end goal, sure, but not the nature. To explain the nature of it, I want to tell you about an idea I've just recently learned to name: the idea of a "compact understanding."
Here's how it goes.
Even if you know nothing about computers, you can probably imagine that they're somewhat complex. Trying to write a good application with a small team of people is something like trying to manage all the trains in New York, making sure that everyone can get where they want to go in a reasonable amount of time. If anything goes wrong in the New York subway system, and if (unrealism warning) you were trying to keep a high level of service, you'd have to adjust a load of other things to compensate; that's complex.
An email program, for example, needs to do cryptography, networking protocols, user interface management, search & indexing, and a lot more. And beyond all that, different computers and different operating systems can behave differently, and worst of all, any small piece can disastrously affect any other. Thinking about an application like that, I always marvel that it's possible that anyone can understand it at all—how anyone can hold it all in the mind and control it.
The answer is actually surprisingly simple: abstraction. We write pieces of code whose internal details are not important to understanding their external behavior, which is designed to be more simply understood. Quite often, these pieces are modeled on some real-world metaphor: we speak of "objects," "packages," "actors," "factories" and so on. Examples might be "MessageListingPane" and "EmailFetchingAgent." The point is that programmers give themselves a layer of intuitive "objects" which are quite easy to understand, even though (in principle, with poor design) any object could affect any other in surprising, catastrophic ways.
Better yet, a single "object" can often unify a number of different things which vary mechanically in some of their details. Because computers are good at banging out boilerplate examples of a general scheme, it's often quite easy to unify things in this way. Programmers do it all the time.
So, creating these abstractions gives you a more compact understanding of a given program: you need to pay attention to fewer issues because you've used the machine's mechanical power to take away some of the tedium. The rub is that fewer things take your attention. That makes it easier to manage the complexity of a large program.
This kind of thing works even if you can already understand the whole program. It's still worthwhile to abstract (or "refactor") it when you can, because fewer things will take your attention, thus leaving more of your time free for conquering new problems. Imagine if you could take a newspaper and remove all the annoying ads: you'd be able to glance through that newspaper much quicker because fewer things would be vying for your attention. Now imagine that you could take that newspaper and unify all the articles that talk about politics into one article: you'd see that they all share some common facts and principles, and vary only in certain details. You'd have a very compact understanding of the day's news! The sentence "Guerilla warfare broke out in Trieste, Vladivostok and Chicago" is much better than three sentences that say that, though in different ways, about those three places independently.
Of course, you can't really do this with newspapers, since newspaper articles have characteristics like "point of view," "style," "local color," and so on. But if all you cared about was some kind of raw information content (and assuming that natural language has raw information content), you could do this with a newspaper. And computer programs, for the most part, don't have these subjective variables to stand in the way of abstraction.
With programs, too, you can do the operation on many levels. So continuing the newspaper metaphor, you could "compress" the invidual words, choosing a core set of neceessary words—this way you don't have to worry about fidgety variations between, phrases like "no less than" and "at least." Beyond that, you could compress the sentence mechanics, reducing those to a minimal set, and you could compress the dynamics of the article and the concepts of the domain—politics, for example, could make use of a core set of concepts that might not be useful for art or business. At the end of the day, you'd have a very small "language" for writing newspapers: a small set of words that you need to know, a small set of grammatical principles, and so on.
So ultimately, the effort to produce "compact understandings" of a domain is a matter of picking out the essential concepts, so that people don't have to worry about needless variations between similar-but-different concepts. This allows you to read and think about the domain much more quickly and with fewer issues calling for your attention.
I am told, by a philosopher friend, that much of modern philosophy (or at least the philosophy of science) is a matter of analyzing the literature of some area and picking out the essential concepts and critiquing those—boiling down the field to its essence and working just with that. In that way, the philosophy of science has a lot in common with programming-languages research.
On the other hand, you really don't want to boil down the concepts further than necessary. In the newspaper metaphor, you mustn't lose so many words that you can no longer adequately describe the domain. In PL research, this is called "expressiveness," and the goal is to create a minimal language which is still sufficiently expressive. That's where the tension lies, and why it's not easy. Einstein famously said that "Everything should be as simple as possible and no simpler"; that's precisely the goal of compact understanding.
This all becomes quite exciting when you think about all the layers of abstraction, and thus the power of compact understandings, that operate in our modern world. Here's a good example: the Coq theorem prover advertises a very simple core logical language. That logical language is easy to look at, understand, and trust: it only takes a couple of pages to write the whole thing out, and it's made of elegant concepts. Built on top of that core is a rich and expressive language for expressing logical statements and proving them. But you don't have to understand this rich language to trust the theorems that come out, since they're all written in that core language. Now, the Coq prover can be used to prove statements about a program, such as that it doesn't crash, or it produces the right answer or whatever. In fact, Coq could be used to prove that a compiler is correct, which gives the programmer more confidence that his code will be run in the way he thinks it will, even on different machines.
Next, the programmer might use "libraries," which give a simple view into a complex piece of functionality, like cryptography or searching & indexing. These might be proven correct, or their usage might be proven correct. Such libraries constitute an additional layer of abstraction on top of the prover and the compiler. All of this compactness of understanding allows programmers to move quickly, to meet their (users') needs, and still be confident that the program meets certain criteria.
These programs, in turn, will become desktop applications that present information workers with a clear and simple view of the data they work with—whether that be Google search results, or a large Word document, or currency exchange rates. Yet more examples appear, even above the world of programming: a historical stock price chart is an example, or any of Edward Tufte's carefully designed "visual displays of information"—all these things help us achieve more compact understandings.
This is essentially the food chain I work in. I work way down near the bottom level, making languages that are eaten by programmers that are eaten by information workers that are eaten by. . . . But I'm building infrastructure that underlies, in a nice way, all of the information economy. That's what I do, and why I do it.