prater's blog

in which i hold forth upon various and sundry issues of import to persons employed in the production of software and am promptly and roundly ignored

Your Resumé Should be an Exciting Story Starring You
15 October 2019

I have been reading resumés lately in a couple of different capacities, and let me tell you all something: They suck.

The Conventional Wisdom Makes you Look Conventional

The conventional wisdom of resumé writing has you buzz-wording up your achievements and relating everything you’ve ever done in terms of crushing those KPIs and LOOK AT ALL THE MONEY.

This isn’t bad advice, but it tends to result in a whole lot of largely indistinguishable pablum. A resumé that performs all of the standard tricks is like a Ford Focus - servicable, but unexciting. (Full Disclosure: I drive a Ford Focus. It’s a fine automobile, but I don’t get excited about driving it. Your goal in applying for a job is get your future teammates excited about working with you.)

The kind of resumés I get to read are obviously for software developers and the ones that get rejected fall into two basic categories.

  1. All Computers I Have Known
  2. I Am A Self-Directed Learner Who Likes To Solve Hard Problems

As a human, these are the ones that make my eyes glaze over and skip to the end where I can plausibly say I’ve reviewed your resumé and then throw it away. Please do not make my job hard. If you make my job hard before I’ve even hired you, you have violated the One Commandment of Getting A Job:

Convince your future teammates that you will make their life easier.

Interestingly - I find that senior resumés tend toward the first type while the junior resumés are clustered around the second. I get that the plural of anecdote is not data, so take that with as much salt as you need.

Let’s talk about these two failure modes and what you ought to do to address them.

The Conventional Wisdom is Actual Wisdom Tho

Killed a Balrog, increasing Hobbit survival rate by 10,000%

But first, an aside: I kinda ran down the “conventional wisdom” back there, which was a little unfair, because there’s some good stuff in there. I’m guessing you all know or have heard of these, since we all have Google and we’ve all looked up “why does my resumé keep getting rejected?”

So quick recap:

  1. Action Words - make it sound like you’re the star of this story, because you are!
  2. Measurable Outcomes - All these graphs go up and to the right, because that’s where the future is!
  3. Please, please, please proofread - You probably won’t get dinged for dangling participles or whatever, but consistent misuse of words or a lot of common grammar mistakes (they’re, there, their) are Bad News.

Now onto critiquing the bad resumé you may have already written.

To All The Computers I’ve Known Before

Am I the only one who likes this song?

Let’s start with How To List your Skills. This is very, very straightforward.

  1. Copy them from the job ad

That’s it. That’s the whole thing. Copy each of the technologies listed in the job ad over to your resumé, then delete them if you’re not comfortable with them. If you know something adjacent then you can put that in instead. Like you can put down “Cloud Formation” instead of “Terraform” if you don’t have Terraform.

Now if there’s no overlap at this point, then maybe consider that this isn’t the job for you.

Let’s try one on for size (modified from an actual listing):

  • Experience with Processing.js
  • Experience with Python, Ruby, or Node
  • Strong knowledge in OOD, domain-driven design, and microservices
  • Experience working in Agile Teams

Skills I might write down:

  • Ruby
  • Python
  • NodeJS
  • Software Architecture including DDD, OOD and microservices
  • Agile Methodolgies including Scrum and XP

Note how I skipped Processing.js because I have never used it. With this amount of information it’s not possible to know how important Processing is to the job, so we’ll just leave that part out.

I tend to put these in a little list right under my name, so that people can read my resumé and see the intersection between what they’re looking for and what I have right away. That way, they don’t have to read several pages of responsibilities, or things like this:

Created custom dashboard for Elatic Monitoring for RHEL 6.4 clusters written in Processing.js and Graylog

I don’t know what half of that means, and I have to read your resumé really carefully to come up with the answer to my question “Does this person know Processing.JS?” - if the prime directive of job interviewing is showing how you will make your team’s life easier, start by demonstrating this by making the reviewers job easy.

If you by some chance find yourself writing a bulleted list of technologies longer than like … 5 then just stop. Back up and write down the interesting ones! I’m sure it’s interesting to the right audience that you used some Java program I’ve never heard of to do a task I don’t understand, but this is a Python shop and I just wanna know if you can AWS.

You are unique, just Like every other self-directed learner who likes to solve hard problems

Does it really matter that they're all unique when there are eleventy-billion of them?

Next to “I’m sorry sir, but that’s our policy.” - this has got to be my least favorite sentence in the English language. It’s almost entirely content free and everybody knows that you’re either lying or dissembling.1

For the love of dog, if you have this sentence in your resumé or cover letter, please remove it unless you know for a hard absolute fact that you are talking to a machine. It is the platonic form of “telling not showing” in writing. Like the sentence “Sir Gilroy the Fair is the hero of this story” - it only really works as satire. You need to find a way to demonstrate this truth to your reader without just baldly stating it.

Think about this: What’s an engaging way of telling this story, without resorting to asserting it free of context? Start by telling a story about a time it was true of you:

“This one time, I was supposed to make a poker game, but I didn’t know anything about poker, so I learned all about poker, and wrote a program that I couldn’t beat at poker.”

Now, if you’re a newish developer you might have to dig pretty deep on this one - and you probably only have a limited set of really good stories to draw on. But think about it - when was the last time you encountered a seemingly intractable problem you needed to do some research to solve? Last week? If you’ve never had to do this, then you might need to do some more training. Being a “self-directed learner who likes to solve hard problems” is a significant fraction of being a developer. Everybody has this.

Tell Me A Story

People tend to approach cover letters and job applications as opportunities to list a lot of good things about themselves, or to tell other people about themselves. I think this is exactly the wrong approach. Tell me a story with you as the hero. Make it engaging. Make it a thing that I want to read so that at the end of your resumé I’m having a The-End-of-Return-of-the-Jedi moment. “Yeah, that was awesome! What happens next? Let’s make a sequel! And not wait 30 years!”

Me and this stick gonna mess you up

Okay, RoTJ might be a bit of a stretch, and I’m not advocating for you to include tiny, savage bears in your cover letter, but please make your job application engaging. I read enough boring business writing everyday. I do enough work. Again, the main dimension people are hired on is “is this person going to make my life easier,” and if you begin by making me read a long, boring document then you’ve just demonstrated the opposite. STAHP.

All of that is easier said than done. Here are some actionable tips to make your resumé better.

  1. Read. It. Aloud.

    Seriously do this one. This is like the secret to good writing. Read it aloud, maybe even to an audience and see if it sounds engaging. Perform your resumé like a one act play and make sure that you’re the hero.

  2. Write the Resume You Wish You Had

    Do not send me lies, but write down a fictionalized account of your career up to this point. This shows you your values. Did you write “* Improved performance of page load 1000%” or “* Created a new process for gnarfling the garthok that saved the company $1000 per millisecond”? You have revealed the kind of thing you’d like to write down, and the sort of story you’d like to star in. Now go back to your “real life” and write the same sort of stories from your experience. “* Decreased page size from 20M to 150K” and “* Developed a Garthok Gnarfling Guide to share with other developers.”

  3. Keep it short. Tailor it to every job.

    Every job is different. Get good at tailoring your experience and accomplishments to individual companies. Do not tell me how good you are at sword fighting if we’re going to get in a laser gun fight on Endor. This seems like a lot of work until you do it a few times and you find that you can remix a lot of the same content. A sentence here, a phrase there. You want to tailor it for every company because you want to keep it under two pages. I’m busy, and I have reasonable expectations about how exciting a resumé can be. Think Cat in the Hat not War and Peace.

  4. Action! Excitement!

    A Jedi might not crave these things, but your resumé reviewer does. If you’re a clever person who likes to have a good time don’t be afraid to let that come across in your resumé. I mean, don’t try too hard, but don’t wordsmith your introduction to the point that it sounds like it was written by a lawyer. If you’re a detail oriented perfectionist (good for you!) then make sure your resumé reflects this - a single conservative font with perfect kerning!

    It is okay for your resumé to be a statement about who you are, that’s why we read it.

  5. Read. It. Aloud.

    Did you just say “yeah sure” before and then not do it? I mean it. Do it.

Here is your Handful of Salt

So first off - this is not a “How to Get A Job” post - this covers just the resumé and cover letter section. There are several other steps you need to pass, all of which have higher signal. Interviews, code challenges, phone screens, etc. If you’re an asshole or you have no relevant skills, no amount of “kickass resumé” is going to overcome that deficit.

Second - I read the resumés of software developers, so if you’re applying for a job as a Marketing Manager, understand you’re outside my area of expertise. Some hiring processes are designed to remove as much personality as possible from the process (looking at you, academia.) So, while software hiring may be broken in many ways, so far we’re doing an okayish job at not reducing “Do I want to spend eight hours a day discussing math and puzzles with this person?” to a list of impersonal checkboxes.

Now, I’m sure there are companies in the world that get so many resumés that nobody reads them, and most of them are simply run through a keyword analyzer. So in that case, follow this advice anyway. The strategy of copying qualifications directly into your resumé ought to overcome simple keyword filters, and anything more complex than that is just a pile of linear algebra nobody understands anyway. Just ignore scare-mongering about automated systems. Those kinds of systems are designed to generate plausible deniability, not “find good candidates.”

Now, for a uncomfortable truth: There is a giant element of chance in getting past an initial screen. There isn’t a whole lot to go on in a resumé, so a chunk of what gets a reviewer to give you a thumbs up hinges on whether your resumé speaks to them. The Lord of the Rings is probably my favorite book of all time, but a lot of people find it terribly dull. You cannot write for all audiences, and attempting to do so will result in you writing for no audiences. Be yourself, tell your story in an engaging way, and you’ll land at a place where people want to spend half their waking hours engaging with you.

And, when you think about it, would you want to spend that much time at a place that thought you were just too interesting?


1. “But I’m not lying, that’s really true!” - You know, I’m sure it is, but have you ever said this outside the context of a resumé or cover letter? If not, you need to find a more engaging way of saying this that not every person with a pulse is also writing in their applications. If you have said this in “real life” … you need to go to better parties.


The Book of NATS I - Chapter 3
13 March 2018

Sit down everybody, lemme tell you a story. Flicks the lightswitch

In a time long ago, there was ActiveSupport::Notifications, and it was good. But the people desired to send messages to remote applications without crafting specific calls to special API endpoints. And Prater came upon this problem and decide “I will fix it” so he paired with Peychich and created the NATSAdapter for Goldstar Notifications, and it required no code changes to work with existing code. And he looked upon his PR and saw that it was good.

And then, behold he tried to deploy it to Staging and all was well, and he looked upon his code and he should have been suspicious, but his mind was undone with the promise of the beauty of the world to come, and the elegance of the thing he had crafted, and he put down his doubts, and he pushed himself to deploy.

And deploy he did. In the beginning the Deploy was with Jenkins and the Jenkins had the deploy - and lo it came to pass that Staging was Very Different Than Production, and signals that were received in Production were not received in Staging, and therefore that case was not handled. So Prater went back to his editor, where he introduced reconnection logic. And the PR review saw that it was good and smiled. And they deployed the reconnection logic to Staging, and all was well.

But when, in the fullness of time, he deployed to production again, the Great Enemy MultiThreading bared it’s mouth of fangs and said “Lo, beware, for although you have introduce reconnection I have Thread Safe Concurrency Constructs that are as Queues and Condition Variables and it is not my will that your deploy should go smoothly.”

Indeed, when the time for the deploy was upon the developers, the Unicorn processes would shut down, and they would disconnect from NATS, and they would send messages that said “We are no longer interested in what you have to say, for we are tired, and wish to shut down. Give your messages to the children of the new master!” But little did the developers know, that they had been deceived - for no messages could be received on any channel when they were disconnected, and there was much wailing and gnashing of teeth - for every deploy resulted in 15 seconds of intermittent downtime.

But then Prater and Jared beheld the situation and in their folly they proclaimed “A one line change!” and so they changed the one line and proceed with testing. For in in the darkness had been crafted that most terrible of sins, the thing that developers have dreaded since the dawn of time - a library bug. And Prater and Jared looked upon their minimal reproduction case and despaired - for the bug was not in their code, but deep within the library, and any method called from within the threaded closure would fail, and it’s children would fail, and so-on for ever and ever, deadlock.

Many changes were thrown against the problem that day - and many dark avenues of promising fixes came to their ends in alleys of shared state, but finally, in a a final fit of desperation, Prater and Jared decided to use the weapons of their enemey against them, and introduced a Thread Safe Queue to their own code.

And there was much rejoicing in the land, for all of their testing indicated that it would work. The developers recreated an environment with forks and signals locally and they applied their changes, and everything worked as expected, and connections were not lost, and the people did feast upon the glory that was a distributed pub-sub system, and there was much rejoicing in the land.

But still, Prater is watchful - for he has been burned before and it has left scars upon his heart, and fell mood upon his mind.


The Path of Least Cost
07 November 2017

In raster GIS analysis there is a relatively common piece of analysis called the “least cost path.”

I wonder where the river is.

The algorithm itself is pretty simple - given a “cost surface” find the cheapest way to get to a different point on the plane. The “cost surface” itself is essentially a grayscale picture where the highest numbers represent the highest cost. The analysis is excellent for finding the path that water will take down hills, or if you want to get a little creative, the fastest way from your house to the coffeeshop given what you know about road conditions.

It’s a simple algorithm - it finds all the paths to the goal, adds up the costs, and takes the cheapest one. Does that process sound familiar? Could it be SATAN AGILE?

Spoiler: Probably Not

But the algorithm is not infallible.

One of my favorite examples of how people “know” better than the least cost algorithm comes from archaeology. (Disclaimer - I am not an archaeologist, but I am married to one so I get some osmostic learning.) Here’s the story:

In Central Arkansas, the Arkansas River runs near the base of Petit Jean mountain. Petit Jean is covered in Native American rock art, but there’s little evidence of long term habitation there. Instead, it seems that most of the people in the area lived in the nearby bottom land and “commuted” to the top of the mountain for ritual practice.

Wanting to know what sort of path they might have taken to get to the top of the mountain - a researcher runs a “least cost analysis” between a known village site and a known rock art site. The path leads straight into a shear cliff, and happily climbs directly up it. Turns out that it’s cheaper to climb the cliff than to go round to the nice, gentle slope, and cool refreshing water falls on the other side of the mountain.

I mean … c’mon. Clearly - no reasonable human is going to stumble upon a shear 100 meter cliff and think to themselves “I bet scaling this is easier than going around.”

Now - if you’re a developer and not a rock art specialist you’re probably thinking one of two things depending on your personal proclivities.

  1. “Agile’s such horseshit - no longterm thinking and now we’re staring down a metaphorical cliff of technical debt.”

  2. “This is probably MVP. I wonder if we could just do the ritual right here at the base of the precipice.”

Perhaps suprisingly - this story has an obvious ending.

Nobody climbs a hundred meter cliff.

They especially don’t climb a hundred meter cliff if you can go a few kilometers out of your way and take a nice easy walk through bountiful forests.

Maybe there’s a story here - that the “easiest next step” is not always the “correct next step” - a little bit of vision here can go a long way. We can no more imagine clueless native pilgrims stumbling up to a surprise cliff face than we can them climbing it. Because they weren’t stupid.

Without robotic devotion to process we all see the cliff coming - but the desire to make Software into a Factory has produced a type of willfully ignorant Agile Cult that (like all cults) has convinced themselves to believe things they know aren’t true, and to deny truths they can plainly see.

Software Is Not A Factory

We (by which I mean “the people who write the checks and the code”) want, and maybe even need, to believe that once we ‘discover’ the correct way to write Software we can eliminate human creativity from it and get right into producing software exactly like we do cars or houses or anything else that’s mass manufactured by humans.

Eliminate the ability (or need) to make decisions and we can Taylorism our way right into profitability. I’m pretty sure this is mostly wrong for several reasons - but one of the biggest gets back to our parable of the Least Cost Path.

Software Is Not A Factory - but it is also not a journey with a map. There is little doubt given the “least cost path” analysis that it is in fact cheaper to climb the cliff. It’s not really arguable that from the birds-eye view (where you can clearly see the entire cost surface) that walking around the cliff is the more expensive option. But while planners like to see themselves as the algorithm - with perfect foreknowledge of the lay of the land and all of the costs associated - we are far, far, far more like the people trying to get to the top of the mountain to make some Rock Art.

It’s a pretty sensible approach to not start out with idea that we’re going to go the long way round - and so start hiking directly toward the peak of the mountain (where lies our Finished Product) - but we don’t have to walk all the way up to the base of the cliff to realize the cliff is there and that maybe we should go another way. And, on our next trip, there’s no reason to take a several-days detour to the base of the cliff to see if it’s still there - we can start planning for the walk around.

Convincing yourself that you don’t know things that you do know is just as much of a cognitive bias as convincing yourself that you do know things you don’t know - and it has the same kind of negative impact.

You plan for the world as you see it, and if you see it wrong, you plan for it wrong. That’s something of a truism and extraordinarily reductive - but I think it’s something that we could all benefit from remembering. Programmers even have an acronym for this: Garbage In Garbage Out.

So it goes, watch out for cliffs.


So you wanna be a programmer
09 November 2016

Before I start dashing your hopes and dreams, let’s get one thing out of the way.

You are smart, you are capable, and if you desire, you can find success as a software engineer.

You already have a leg up on the vast majority of people for whom computers are a magical black box, so even though it may seem daunting, be aware that once you’ve left orbit, you’re halfway to anywhere.

Now for the unpleasant bits:

  1. No one will hire you based on your boot camp experience (unless they have a program designed to hire boot camp graduates.)

  2. Most of that knowledge is syntax and technology. These are orthogonal to your actual skill set, which is the ability to LEARN syntax and technology.

  3. You will never be “good” at this job.

No one hires bootcamp graduates

This is not strictly true. Lots of places hire bootcamp graduates, but few of those graduates are hired BECAUSE they went to bootcamp. Bootcamp code is generally throw-away quality, and that’s okay. Hiring managers and engineering teams care more about your ability to contribute than anything else. Convincing your future teammates that you will make their life easier / better is not a guaranteed job, but failing to convince them of this is a significant hurdle, and convincing them of the opposite is a success-proof strategy.

Whatever shall I do?

One of the ways that you show you CAN contribute is to ACTUALLY contribute. Find an open source project and make some patches. With a few notable exceptions, OSS projects love receiving well thought out patches from new contributors. If there is a project you like and an itch you’d like to scratch, that’s an excellent way of writing “real” production code without actually having a job. This doesn’t need to be an established OSS project. You have a hobby right? Aim coffee and code at your hobby and write some software to make your life easier. Nothing speaks louder than your code, so show off as much of it as is reasonable.

The other avenue for this is freelance. Be careful about accepting freelance too far above your skill level, but don’t be afraid to seek out and perform work that is outside of your comfort zone. Although you probably do not command top tier freelance rates, don’t feel bad about charging for your work. You will know when something doesn’t seem fair - adjust your time accordingly, or seek out non-profit or low-budget projects where you can work at your own pace.

A bootcamp graduate with meaningful open source contributions (make them on Github!) is immediately a cut above junior level devs without them.

I’m sorry to have to tell you that the answer is “work for free” - but so it is. A lot of the hiring managers and Sr. Devs now working grew up hacking around on things in their free time. The expectation is not that you “work for free” but that you apply your skills to things you care about, and that your copious youthful energy be directed into ‘meaningful’ things.

Your actual skills are not programming

Two of the main skills that a “good” Jr Dev will have are stubbornness and curiosity.

You’ve probably already got a stubborn streak if you’ve made it this far, and you’re going to want to nuture that in a certain ways. Don’t give up, even when you are defeated, and have an no-quit attitude. This is HARD. One of my mentees was interviewed at a financial services firm, and they gave her a coding test as part of the interview. The test was UTTERLY beyond her abilities, and she had no hope whatsoever of completing it. She was obviously upset as this was her first interview at a promising company, and she was devastated to know that she was going to blow it. I encouraged her to complete the test even though she would miss the deadline (she missed it by almost 3 weeks, but she did complete it.) She did not get that job, or the next one, but by her third interview coding tests were old hat, and she aced it and got the job. You WILL lose. Keep fighting.

Bo Staff Skills

The other “winning” attribute is curiosity. A different mentee of mine was working with me on a complicated graphics project. I had mentioned offhandedly some point about RGB color math. He didn’t understand what I meant, and although I explained the immediate application to him, he wasn’t satisfied - instead he went home, read a bunch of articles and blog posts on the subject and came back a few days later with questions that I couldn’t answer. He wound up writing the color math portion of the project because he understood the problem better than I did.

If you apply these two traits to your work, that will go much farther than knowing the basics of an additional framework. Jr Devs are hired based much more on potential than on actual production, and displaying an unwillingness to accept defeat at the hand of a machine and a deep curiosity for problems you encounter is a good way to convey to teammates that you will be an asset to them in the future.

Note that this doesn’t necessarily mean you shouldn’t have a life outside of computers - you really should - but that your potential teammates are primarily concerned with your life vis-a-vis computers. Stubbornness and curiosity maybe your two most important skills, but it’s also important that you not be a raging jackass to everyone you meet. Try to be humble, approachable and teachable. For a discipline revolving around unfeeling machines, people skills are shockingly important to your career as a programmer.

You will never be “good” at this job

Remember when we talked about a refusal to accept defeat? Get ready to lose. A lot. Your career from here on out will be near constant terror that you just fucked up so royally that THIS time they’ll finally find you out. Spoiler alert: you didn’t. Everyone feels this way all the time. Seemingly misplaced confidence is another good trait for junior engineers. “I don’t know how to do that but I can certainly figure it out!”

This is very much a “fake it until you make it” sort of behavior. If you’re always moving forward, trying SOMETHING, eventually you find that the things you try work more and more often, and that you really pooch it up way less frequently. More spoiler alerts: the number never gets to zero.

A lot of freshly-minted developers take the exhortation “Be Confident!” as a sexist scold to stand up for yourself. To an extent this is true, but the take away from “Be Confident!” is not to develop a “rock-star-ninjaneer” ego but to be confident in your ability to solve problems. Developers have been talking around this problem for as long as the discipline has existed - “Strong opinions weakly held.”, etc. Be willing to fail, be willing to try. The good news is that, as a computer programmer, things rarely explode when you make a mistake, the better news is that as a Jr engineer, you are likely to (and should!) be insulated from making critical errors by Sr Developers and managers. So, go for it. What’s the worse that could happen?

How is a developer like a writing desk

This sounds all negative-nancy and Eeyore’s pity party - and to a certain extent learning that the several thousand dollars you spent on a dev bootcamp is not a job guarantee is certainly bad news - but I’ll reiterate - you are already half way there.

Awwwwwwwwwwwwwk

Being a Jr. Developer is HARD. In a lot of ways it’s harder than being the grizzled old vet. You don’t know what you don’t know, and you’re entering an industry, where, frankly, social and professional norms are different. You might face additional challenges like being from an under-represented race, gender, or sexual orientation. You might not have the kind of hacker personality that makes engineering and logic problems come naturally to you. And that sucks. It won’t be easy, things worth doing rarely are. You don’t need to have a lifelong dream of being a programmer to be a successful one - if your passion is romantic French literature (my boss for instance) that’s fine. You don’t have to follow your passion, but you need to be passionate about doing good work. I won’t say that you won’t encounter some people who are just useless assholes. People like that are everywhere. If you stick with it, you’ll (hopefully) get to the point where you’re well paid. But, if you’re in this for the money, you’re going to have a hard time. Being subject to continuous failure and the relentless, heartless criticism of the machine can suck the joy out of any paycheck, no matter how big.

I will say this though: The people who become successful programmers often have the same basic traits that you do. They are passionate, they are curious, and fundamentally they want you to succeed. They have ALL been where you are now, confused, uncertain, excited, and amazed at what they can make that machine DO.


Stupid Ruby Tricks
18 October 2016

1] pry(main)> a = { foo: 'bar' }
{
    :foo => "bar"
}
[2] pry(main)> a * 2
NoMethodError: undefined method `*' for {:foo=>"bar"}:Hash
from (pry):3:in `__pry__'
[3] pry(main)> [a] * 2
[
    [0] {
        :foo => "bar"
    },
    [1] {
        :foo => "bar"
    }
]
[4] pry(main)>