Programming is creative work. Given a problem, you have to find a solution, then explain it to a computer in a way that humans can also understand. But unless you’re working on your own project, you don’t have total creative freedom. You have to use the tools and technologies that your team has selected, and your technical decisions are generally reviewed by other developers. On the other hand, it’s rare that you are told exactly how to solve the problem. If someone already knows that much about the solution, they could just implement it on their own. So it’s up to you to work out the details.
Another challenge to unleashing your coding creativity is that not every programming task is equally interesting. And I’m not talking about tasks like attending redundant meetings. Even when it comes to your core responsibilities, some tasks just don’t call for much creativity. But they’re still necessary for a software system to work. Someone has to take care of importing data from legacy systems, investigating bug reports, and running ad hoc reports for management. Programmers are often the people who have the background to handle these tasks, so they get to do them. Even at Google, where innovative technical work is clearly happening, programmers complain that they are overqualified for their jobs. Until we can teach computers to find their own solutions to these boring problems (thereby making ourselves obsolete) we’ll have to continue finding time to do them.
Most people want to work on important problems, or at least cool problems. At Google, that might mean working on self-driving cars. At Microsoft, HoloLens is getting a lot of attention. At major gaming studios, every product has inherent coolness. Though it’s unlikely that day-to-day work in these groups lives up to the marketing videos, it’s easy to compare them to your own job and daydream about applying.
Given enough time and determination, it’s possible to pick an area to focus on (like machine learning or computer vision) and use deliberate practice to learn it really well. You’ll know you’re on the right track when Sebastian Thrun starts sending you unsolicited LinkedIn messages. But in the short term, you have the job that you have. Here’s one way to make it more interesting.
Imagine that your job for the week is deployment automation. Your team has been working on a cloud service, and has been deploying it manually. But now that it’s almost done, you need a more automated process. Unless you happen to love deployment automation, this probably wouldn’t be your first choice of assignments. For various reasons, deployment automation tends to get postponed until late in the project schedule. But it has to be done. So you break out the appropriate deployment automation tools, and get to it.
Let’s assume that deployment automation on your team means writing code in some scripting language. You’re not allowed to use a third-party solution due to budget constraints, open source policy, or some other reason. You now have a choice: you can build a deployment script that does exactly what you need right now, namely deploy the specific cloud service that your team is building. Or you can build something more general, like a tool that can deploy any cloud service that your team might build. You could even go beyond that, and build a tool that anyone using similar technology could take advantage of.
How general you can make your deployment tool depends on a number of factors, including how much buffer you have in your schedule, how experienced you are with deployment automation, and how picky your manager is about exactly how you spend your time. Independent of these factors, creating a more general solution is likely to be more interesting than creating a solution that only works for solving one specific problem.
Levels of Abstraction
Why is the more general solution more interesting? One reason is that programmers want their software to be used, and a more general solution is likely to be used by more people. Programmers also like challenges. A more general solution is more challenging to implement, since it has to be more robust. It’s not enough that it successfully deploy the cloud service that you’re working on now. It has to work on the next one you write, and possibly one written by a different team.
This decision about your deployment tool is an example of selecting an appropriate level of abstraction. A solution that just scripts out the exact steps you need to deploy your current project is at the lowest level of abstraction. As you support more deployment options, it helps to use abstraction layers to hide the implementation details from users of your deployment framework.
While levels of abstraction can be a valuable design technique, they can also get you into trouble. As the saying goes, “Any problem in computer science can be solved with another layer of abstraction. Except for the problem of too many layers of abstraction.” If you make your deployment tool too general, it may not work well enough to solve your original problem. Your team may decide that it’s easier to go back to running each step manually. Or you may get so involved in designing the ultimate deployment framework that you become an architecture astronaut, and don’t end up building anything. So keep your head inside the atmosphere, but consider a design that gives you some flexibility and a chance to work out some interesting implementation details.
The Ivory Tower
There are usually opportunities to make a routine programming task more interesting by building a more general solution than is strictly required. But ultimately your job is to solve a practical problem. One environment where that isn’t as much of an issue is a university. Although students get assignments that need to be completed according to specifications, the ultimate goal is education. In most cases, the output of your work as a student isn’t as important as what you learn from doing the work. With all of the college-level material available now on the Web, you can even re-create those learning experiences and pick up topics that you missed the first time around.
Besides the focus on learning over practical outcomes, another aspect of university life is exposure to important problems. While getting on Google’s self-driving car team may be next to impossible, any CS undergraduate can take a machine learning or computer vision course.
Making Your Job More Interesting
Problems that developers solve on the job are practical manifestations of Computer Science concepts taught in the academic world. There are benefits to both approaches. On the commercial side, programmers focus on practical applications and customers get products that help them solve problems. On the academic side, researchers and students think about the limits of computation, with less concern for the restrictions imposed by the market.
If you’re toiling away on a dull problem, it can help to think about how the problem could be solved in a more general way, by removing some of the specifics of your particular application. Not only can this make the problem more interesting to solve, but your solution may be more useful in the long run. And staying familiar with what is happening in Computer Science research can remind you of what is possible.
(Image credit: smoothgroover22)