Learn your standard library

Dear new developer,

If you want to be good at interviews, learn your algorithms. Loads of companies treat algorithm knowledge as a proxy for general problem solving ability. It makes a certain sort of sense–you have to break down a problem into pieces, turn it into something software can digest, and implement it in code. You can practice these at places like HackerRank. Like any proxy, they can be gamed, which is why tech interviewing feels like a fundamentally broken process. (See this great post about humility in interviewers for another piece of the puzzle.)

But if you want to be good at your job, learn your standard library. This is the piece of software that surrounds you, in which your software will execute.

I remember the time when I was a contractor and started at a new place in the early 2000s. Someone there had written their own connection pooling library. This seemed like madness because it’s a complicated piece of work and there were several free implementations available for the language (though, to be fair, none were part of the standard library). This code, which provided very little business value, would have to be maintained and bugfixed and upgraded.

Every modern language has a definition (this includes syntax and keywords) and a set of associated, standardized classes. These classes allow developers to “stand on the shoulders of giants” and should be used whenever possible. Why? These libraries evolve over time as the language is released and have a number of beneficial properties.

  • Using the standard library lets you accelerate development. You don’t have to roll your own hash or tree, you can just use the one that ships with your library.
  • It is far more likely to be correct. This can matter a little, if incorrectness introduces a bug. Or it can matter a lot, if incorrectness causes your system to be fundamentally insecure. Standard libraries have a lot of eyes on them, including specialists.
  • As a corollary, standard libraries handle edge cases. They are well used code, in the sense of this post (source code doesn’t rust). If the language is used by any number of people, it’s going to be more bullet proof and handle weird edge cases that your self rolled code won’t handle (until a bug is discovered and fixed).
  • It will be more performant. Again, this is because the effort to make operations faster is amortized across all of the users, so specialists and experts are more likely to be involved.
  • The standard library for any popular language will be maintained over years, likely by developers you won’t have to directly pay.

All of these benefits stem from the fact that more people work on standard libraries than work on code in your company.

But, you have to know the standard library to gain all of these advantages. Unlike the syntax of a language, you don’t need to know the standard library to get things done. While you can’t roll up your sleeves and start coding until you know the syntax of ruby, php, java, clojure, haskell, javascript, etc, you can code for quite some time without knowing all the ins and outs of the standard library.

This is because standard libraries can be large: Java has thousands of classes in their standard library, and even a language with a small library like Javascript has about seventy objects, many with tens of properties or methods. It takes a while to learn. Plus, new developer, it can feel like you’re not doing much when you are reading docs. Certainly such readingĀ  isn’t as fun as banging out code. But, it will have two benefits for the codebase:

  • you will save time in developing because of all the benefits above. You may have to invest some time up front, but once you do, you’ll be faster for the rest of your career.
  • you will write idiomatic code. Other developers who are familiar with the standard library will know the characteristics and behavior of the code you write.

and one for you:

  • you will gain a transferable skillset. Learning how to write the particular kind of ruby that your company uses is not nearly so valuable to other companies as learning the standard library.

How can you learn the standard library? I’d recommend taking a high level overflight. Google for ‘<language> standard library overview’ and read whatever articles or listen to whatever presentations are available. I’d also recommend just scanning the docs and seeing what piques your interest.

After you have that, the best way to learn the standard library is to use it. When you are about to tackle a problem, make it a standard part of your process to ask “is there a standard library function for that”. It can be difficult, but as it becomes a habit your code will become better and you will learn to trust the authors of the standard library.

If you have time and inclination, you can also search for ‘<language> koans’ which are small exercises in languages. These will often exercise the standard library. See Ruby Koans for an example.

When there is more than one way to do it using the standard library, which happens more in some languages (like PHP) than in others (like golang), think about the options and then try to be consistent.

So, learn the standard library. Make the time.

Sincerely,

Dan

Know when to not throw in the towel

Dear new developer,

I wrote previously about when to throw in the towel. Now I want to mention when you shouldn’t.

Anything worth doing is hard. That includes software development. There are times, sure, when it feels like you’re a superhero. When the code is flowing. When you can hold the entire system in your head.

Those times are great, and, in my experience, rare.

There are also times when it’s a grind. When you look up at the end of the day and wonder “what did I actually do all day?” When you are picking up a new technology or system and it feels like you are on the last move of a game of Jenga, with all the pieces about to fall over.

This is the time when you need to stop, take a deep breath, and then keep going. That doesn’t mean you can’t pop up and ask questions or take breaks, but sometimes the only way out is through.

There’s an art to knowing the difference between a grind that you have to get through and a wall that you can beat your head against without making progress. I don’t have a simple way to differentiate, other than to say that the grind often happens at the beginning of a project (when you don’t know what you don’t know) and at the end of a project, when that last 5% that you put off because it was hard balloons to 25% (or more).

I have told teams in the past that “if we aren’t learning and making mistakes and doing new things, we aren’t doing it right”. That’s because if a software engineer knows how to do something, they’ll likely automate it (and then they won’t have to do it again).

Sometimes that learning process is joyful. Sometimes it grinds. You have to push through.

Sincerely,

Dan

Laziness, impatience, hubris

Dear new developer,

Larry Wall has created foundational software (perl, patch). He coined the three virtues of a programmer:

  1. Laziness: The quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful and document what you wrote so you don’t have to answer so many questions about it.
  2. Impatience: The anger you feel when the computer is being lazy. This makes you write programs that don’t just react to your needs, but actually anticipate them. Or at least pretend to.
  3. Hubris: The quality that makes you write (and maintain) programs that other people won’t want to say bad things about.

These may seem crazy. Who wants to be seen as lazy, impatient or full of hubris?

But if you think deeply about it, Larry is saying that laziness makes you work in the short term to save effort in the long term. That impatience makes you write better code because computer time is less valuable than your time. And that hubris makes you want to develop software that you can stand proudly behind.

Makes a bit more sense, no?

Sincerely,

Dan

Learning to read code is more important than learning to write it

Dear new developer,

Coding is fun! You get to take a few words on a page, breathe life into it through your understanding, type rapidly into a text editor, and display it to our colleagues. It’s an amazing profession that is changing the world.

However.

The vast majority of code is read far more often than it is written. This is true for a few reasons:

  • Companies pay for code. Code is expensive. They want to amortize the costs of writing it across as many years as they can.
  • Business requirements change. That means that the code that supports those business actions needs to change. But before that software can change, the modifier needs to understand what is currently happening. Even if the requirements dictate a whole new feature is implemented, the developer still needs to understand how the new feature fits into the existing codebase.
  • Bugs occur, where the software is almost correct, but not quite. Again, anyone fixing the bug needs to understand what the existing code is doing.

And over the years, there will be many changes and bug fixes.

There is, to be true, the occasional piece of software that is just “set and forget” where changes are minimal over the years. I once was responsible for a piece of software that ran for five years with no changes. That’s rare enough that it sticks in my mind.

So this means, that of the time you actually spend coding, it’s likely that more of it will be spent trying to understand existing code in order to make changes to it than it will be writing new code. And of the applications you support, more of them will be already written than not. Of course, depending on what company you work for, things might be different. A startup with no existing systems will need more new code than a running business. (I wish I had numbers to support these statements, but all I have is my experience.)

What does that mean for you, new developer?

It means that spending time learning to read code is a good idea.

When I approach an existing project that is new to me and need to have an understanding of it in order to make changes, there are a few different aspects I consider.

  • Scanning. This is the high level overview. What problem does this code try to solve? What language and/or framework is it using? Is it using them in an idiomatic manner, or in a unique way? What are the big pieces of the application, and how do they fit together? This information is perfect for a document, but sometimes needs to be pulled from someone’s head or from the code (you should write down what you learn).
  • Diving down. This is where you focus on the problem at hand, and try to identify where the changes should be made. This will probably involve having multiple files open and moving between them, and trying to understand all the logic of this part of the system. You can also look for more granular patterns in the code, including different levels of abstraction, homegrown libraries or frameworks used, and coding idioms. Consistency matters, so you want to write in the style of the current codebase (which doesn’t prohibit you from noting where the current style is flawed and should be changed).
  • Use the scientific method. Write a hypothesis, make small changes and see what happens. If you can make changes in a staging system or on your local machine, that’s great.. A debugger is super helpful here, as are unit tests (or any kind of automated test). If you can’t make a local copy of the entire, you can typically still set up the language runtime locally and run various chunks of code to get a better understanding of what the system is doing.

Beware of the temptation to try to understand the entire system before making any changes. Whether you need to do so is based on how entwined the system is, how well the system is tested, and how critical the system is. Only discussions with the business and other members of your team can determine the best course forward, but an understanding of the entire system will likely only come with time.

Also, beware of the temptation to just throw away the old code and rewrite it. Especially if you don’t understand all that the code is doing. Old code is reified knowledge, and you ignore that at your peril. See obligatory link to the classic post “Things You Should Never Do, Part I”.

Reading code is more important than writing code because software systems spend the majority of their lifetimes after launch, and change happens.

Sincerely,

Dan