Amazon is in that club of employers (Google, Twitter, Facebook, Microsoft, etc), where working there functions as a stamp of quality. Their employees are frequently cold called by recruiters working for other members of the club, middle tier companies, and start ups that cannot get enough people through their personal network. Amazon pays very well relative to most jobs, even many programming jobs, but it does not pay as well as other members of the club. The salary is just a little less than you’d make elsewhere, but equity and bonuses are backloaded such that many people are driven out before they receive the bulk of them. The health insurance isn’t as good. I realize paying for your own lunch is normal, but Amazon makes employees pay for a lot of things other companies offer for free, like ergonomic keyboards. And then there’s the work environment.
How does Amazon maintain a talent pool equivalent to the other prestige club members while paying less?
This is anecdotal, but my friends at Amazon are much more likely to have come from unprestigious companies or schools than my friends at other club companies. Working at Amazon doesn’t make them smarter, but it does provide widely-accepted proof of their intelligence that they didn’t have before, and can leverage into cushier jobs later. In some ways Amazon’s reputation for chewing people up and spitting them out is a feature here, because leaving after 18 months raises 0 questions among other employers.
So my hypothesis is Amazon invests more in finding and vetting smart people who aren’t currently holding Official Smart Person Cards, and that part of employees’ compensation is getting that card. In this way it’s like the US Armed Forces, which are grueling and don’t pay well but people tend to leave them with many more options than they started with.
I’m unconvinced this is a winning strategy. Operational turnover is expensive, and bad working conditions decrease people’s productivity even when they’re well compensated. But it does at least explain why it hasn’t collapsed already.
Recently I read So Good They Can’t Ignore You. I have well known trouble distinguishing “things the book said” from “thoughts I had while reading it”, so I’m just going to tell you what I thought and if you’re interested you can track down the book and see how original this was.
The book’s official tagline is “Why Skills Trump Passion in the Quest for Work” and it frames itself as anti-passion, but Newport eventually admits that’s a marketing hook. Mostly his thesis is that passion alone will not make you happy, and skill can be used to extract concessions from your employer that make life more pleasant, so you should focus on skill. Passion is a great driver for developing skills so that seems like a weak criticism of passion (he puts all the positive aspects of passion under “mission”), but he also suggests that it’s impossible to find something you’re really passionate about until you have a certain amount of skill, so still focus on that. Given the essentially infinite number of skills available it seems like there’s room for your interests to have input earlier in the process. I think what he’s really attacking is the idea that your job should be a source of entertainment. That has given me severe clarity in what I’m looking for job-wise.
The epitome of the jobs-as-entertainment model is “Choose a job you love, and you will never have to work a day in your life”. That is neither true nor desirable, unless you use a very specific definition of work. Let’s take this blog. No one is forcing me to write it. For the first year I had something like five readers, most of whom I regularly talked to in person. Obviously it was motivated entirely internally, which is another way of saying “powered by love.” And yet, it was still work. Even if you discount all the reading I did as “things I would have read for fun anyway”*, and the thought I put into it as “a thing I can’t stop my brain from doing”, I have to organize my thoughts and translate them to things other people can understand. I had to configure the page layout so it was neither hideous nor generic. I had to proofread and correct mistakes. I had to retype entries from scratch after WordPress broke again. I had to correct all the typos Beth pointed out to me after I published. Nothing past writing the first draft could be considered entertaining the way playing Twenty is entertaining, and even the reading, thinking, and first drafts took considerable time and effort. That sounds like work to me. And yet obviously I was doing something I loved because there was no other reason to do it. **
Love doesn’t erase the fact that something is work. It can motivate the work, it can cushion the annoyances of work, it can give you the incentive to continue when you would otherwise give up, but it can’t erase it. And I kind of resent attempts to try. I am a grown up human, I do not need swings or field trips to chocolate factories to trick me into swallowing a pill showing up.
What I do need is a good working environment, clarity around my goals, and the tools to achieve them. Those are what let me accomplish things, which is the reward I want from work. An occasional morale event when I we’re all producing really good work together can be really rewarding, but frequent events (like my job has) when I’m unhappy with my productivity feels like… like eating too much dessert when what I really need is a nutritious meal. My taste buds notice the sugar but I don’t get any of the associated psychological rewards, and it turns into queasiness. Speaking of which: office candy counts as entertainment but the nutritious-organic-local-cuddled meals at work are productivity aids. Let’s not throw the baby out with the bathwater.
Like 80,000 hours, So Good They Can’t Ignore You has a large emphasis on building career capital. This section isn’t perfect. A lot of the case studies are opportunistic (in the positive sense of the word), and serendipity is not repeatable. I feel like it’s skipping a critical step without acknowledging it. It’s also a little too “be a good worker bee until you’re called up to the the big leagues” for me; traditional corporate or academic paths work for a lot of people and the whole “the only thing holding you back is fear” narrative is stupid, but there’s a lot of other paths to success that get a lot less publicity. But this was still useful.
I have some topics I find both interesting and skills that would be useful in an associated career. But as you may have noticed, I have a lot of interests, many of which require expensive, brittle credentials to pursue. It would suck to spend years in school only to get bored with the field. I highly suspect interests are a better predictor of what will be entertaining than what will be rewarding. What SGTCIY suggests in this situation (actually all situations, but I think it applies to me more than most) is to build capital in things that will be useful in service to lots of interests/goals. Like, say, programming, a skill and job I already have but really always skated through on raw intelligence and a willingness to do low status work. Between this book and not getting a job I really wanted I’ve started make deliberate choices and investing.
It’s also really nice to read a career guide by someone with a career that is not writing career guides (Newport wrote the book in between finishing a computer science PhD and starting a professorship), and one with writing skills to boot. I finished the book in two days because it was just that readable.
*I used to read things with the explicit goal of blogging about them; they were worth blogging about so rarely I stopped.
**I was planning on using the blog as a portfolio for job purposes, but one of the reasons blogging works as a signal of interest and skill is that it’s so costly and low-reward no one would do it unless they loved it.
In Utopia of Rules David Graeber introduces the concept of interpretive labor. This will be stunningly useful in discussing how to handle sensitive discussions and yet there’s nothing on the internet about it, so please forgive this digression to explain it.
No two people are alike, everyone interprets a given action a little differently. Often you need to put work in to understand what people mean. This can be literal- like straining to understand an accent- or more figurative- like remembering your chronically late friend is from a culture where punctuality is not a virtue, so it’s not a sign they don’t value you. The work it takes to do that is interpretive labor. Interpretive labor also includes the reverse: changing what you would naturally do so that the person you are talking to will find it easier to understand. Tell culture is in large part an attempt to reduce the amount of interpretive labor required. Here are a few examples of interpretive labor in action:
Immigrants are expected to adopt the cultural norms of their new country.
Parents spend endless hours guessing whether their infant is crying because it’s hungry, needs a fresh diaper, or just felt like screaming.
Newbies to a field need to absorb jargon to keep up, or experts need to slow themselves down and explain it.
There’s a whole chain of schools that teach poor, mostly minority students business social norms, by which they mean white-middle-class norms. There is no school teaching white middle class kids how to use the habitual be properly.
Crucial Conversations/Non-Violent Communication/John Gottman’s couples therapy books/How to Talk so Kids Will Listen and Listen so Kids Will Talk are all training for interpretive labor.
Graeber himself is talking about interpretative labor in the context of bureaucratic forms, which can simultaneously dump a lot of interpretative labor on the individual (bank forms don’t negotiate) but alleviate the need to be nice to clerks.
Comments in code.
With a few very specific exceptions (accents, certain disabilities, ), interpretive labor flows up the gradient of status or privilege. This can get pretty ugly
People who insist their code is self documenting.
Girls are told “snapping your bra means he likes you” and then expected to no longer be mad about it.
Bullied kids are told to forgive and forget because their bully “is trying to say they’re sorry”, even after repeated cycles of faux-apologies and bullying.
This is more tenuous, but I think there’s a good argument that a lot of the emotional abuse on the estranged parent boards comes from parents expecting unfair amounts of interpretive labor from their children, adult or minor.
Fundamentalist husband expects his wife to know his emotions and correct for them while he actively hides the emotion from himself.
A paraphrased quote from Mothers of Invention: A woman’s house slave has run away, greatly increasing the amount of work she has to do herself. She writes in her diary “Oh, if only she could think of things from my point of view, she never would let me suffer so.”
I think a large part of the anger around the concept of trigger warnings is related to interpretive labor. It shifts the burden from traumatized listeners to protect themselves or calm themselves down, to speakers to think ahead if something they are about to say could be upsetting. That’s work. Speaking without thinking is much easier. Like, stupidly easy. Ditto for Christians who feel they’re being oppressed when they’re asked to consider that not everyone has the same beliefs. That is way more work than assuming they do.
How does this relate to altruism? Charity generally flows down the status/privilege gradient, especially from rich to poor. If the givers don’t consciously change the rules, they will end up demanding large amounts of interpretive labor from their beneficiaries, and do less good in the process. Arguably this is what’s happening when Heifer International gives people livestock and they immediately sell it- the rich people decided what to give without sufficient input from the poor people they were giving it to, and the poor people had to do extra work to translate it into something they want. Or this post on Captain Awkward, from a woman trying to teach her tutoring volunteers to not be racist.
EDIT 9/7/18: I think I in appropriately conflated two different situations in this post: situations where interpretive labor closes the whole gap (e.g. understanding an accent), and things where even after correct interpretation there is still a problem. The problem in that bullying example isn’t just that the victim doesn’t understand how the bully wants to apologize, it’s that the bully is going to keep bullying.
I had this great essay written in my head about how good testing was great when you were learning, because you can’t copy paste tests like you can product code. Then it turned out that it was impossible to test notifications. Not difficult, literally impossible. The ability to test directly has been deliberately blocked for security reasons, and you can’t mock it because the relevant class doesn’t have a default constructor. The most direct path I see right now is extending EasyMock to work on classes without default constructors, and I assume if that were easy someone would have done it already.
So here’s Hunger Tracker version 0.3, sans Aesop. It has all the features I promised in 1.0, but there’s some UX work I want to do before calling it done.
I’ve always admired Test Driven Development and longed for it from afar, but never had a chance to use it until I was on my own project. Most times when you crave something this intently it’s a let down, but no, this is every bit as fun as I thought it would be and more. It’s so relaxing, and it takes so much less mental RAM. I won’t go back to any other way.
I keep trying to explain why it is better and exactly how it made it obvious what I needed to do, but everything I write comes out boring and I don’t think it explained it anyway. Let’s try an analogy. You know how when you attempt a big cleaning project the middle looks worse than if you’d never started? And if you misjudge your energy level it stays that way, and then gets worse because you’re still living your life? Or maybe you misjudged the amount of space something required and your plan becomes unworkable, at which point you can improvise or revert? That’s what regular coding feels like to me. You don’t know if something’s working until it’s all working.
I’ve been cleaning up my apartment lately, including getting rid of things I don’t want and rearranging things I have so they are more accessible/easier to find/take less space. And I am being very careful not to do that. I pick tasks that can be done incrementally. If I want to move things from cabinet A to cabinet B, things in cabinet B get moved to cabinet C first. But cabinet C doesn’t have to be their permanent home, just a pareto improvement over the old one. I have consolidated three dressers into 1 + some other storage bins. I will probably rearrange those storage bins and the remaining dresser as I learn more about how the current arrangement works, but I was never going to be able to plan that out ahead of time anyway. This way I never get stuck halfway through, out of energy or realizing my plan is unworkable.
That is what TDD feels like to me. You might technically be writing and erasing a lot more code, but the mental effort is so much less. Every step leaves you a little bit better off, and you can concentrate your efforts on one problem at a time.
I was really unimpressed with the android tutorials I saw. I did Udacity’s, which is officially recommended by Google, but didn’t provide reference code or a way to check your project, so if something didn’t work you didn’t know where the error was. That’s bad enough when it’s a technology you’re well versed in, but with a new tech you don’t have any debugging tools. It’s like trying to learn a foreign grammar by having it explained to you in its own language, when you don’t even have any vocabulary yet, except your brain hasn’t been crafted by millions of years of evolution to do it. There are other tutorials, but most of them were written for the now-deprecated Eclipse IDE. Translating from one IDE or build system is not a big deal when you’re familiar with at least one of them, but at the beginning you don’t even know what to Google. That’s why you’re doing a tutorial. It’s even more fun with Android because it uses a bunch of very common Java tools but requires slightly different usage than everything else.
So what I actually did was do Udacity long enough to know how to make baby’s first project, come up with a concept that I was pretty sure I could subdivide into google-able problems, and then did so, one at a time. I learned testing basically from scratch, because the two tutorials that covered it required me to know a ton of abstract android architecture, and none of it was explained well enough to mean anything unless you had already coded. “Make minor changes until you understand the permutations” is how every programmer I know learns, and yet no class teaches this way.
All of which leads me to believe a test-driven tutorial could be really useful. I’m picturing a project with a few very simple UI elements, and a series of commented out tests. Users would uncomment the tests one at a time, in order. The test would fail. The error message would be informative, maybe there would be a few suggestions for how to solve it. Then they would research on their own until they found a solution. They would know they had done it right because the test would be passing. Plus they’d learn testing tools at the same time, and those are extremely useful. This may be my next project.
TDD got me all of the features I wanted in HungerTracker 0.2 except notifications. I’m still poking at it, but notifications require a deep understanding of several concepts I’ve entirely ignored until now, and need several moving parts to work together to verify any of them. So here’s version 0.2, which has a greatly improved button layout and a scrollable list that shows as many or as few entries as actually exist.
Hunger Tracker needs to persist data past the closing of the app. Knowing nothing about Android I googled “android write to file” and used the first reasonable looking thing that came up. This was sufficient to let me write to and read a file, which was good enough for a first try and powerful enough for me to release version 0.1. But as I planned the next step I ran into problems. The read function I found required me to specify the number of chars I wanted in advance. I couldn’t spot the end of the file so I grabbed a fixed number of entries every time. I could extract the data as strings but couldn’t figure out how to make a proper scrolling list (even though I’d done one in the Udacity tutorial). Attempts at fixes felt muddled and high friction, which is usually a sign I’m afraid of losing data, either to a hard drive failure or to a introducing a bug and failing to detect it.
Step 1 in fixing this was setting up my github account so I had proper version control. Step 2 was testing. I spent a long while figuring how to properly test the kind of android class I was using (“android unit testing” being a surprisingly unhelpful search term), and then some basic tests of “The text fields that should be there, are they there?”.
The next step was to test the data storage. But I couldn’t figure out how to unit test that. If I tested whether the app was writing to the correct file I needed to look for the exact same file. But that means updating the test every time I change the name of the file, which I didn’t want to do. Plus seeing if the correct thing is written to it is ugly. Tests should be atomic (meaning it doesn’t matter what order you run them in), but the file is persistent, meaning I either need to clear it every time or factor in what previous tests have done. Plus I would have to shape the test around the exact storage format the app was using, but again that means making the test dependent on an implementation detail. I could trigger writing and then reading and make sure the display element was correct, but that’s testing two different things and a unit test should only test one.
What I finally worked out was that the handling of persistent data was not actually a core function of HungerTracker’s MainActivity. What I needed to do was separate out those functions into a separate class, and then use mock objects to make sure the expected calls were made. E.g. instead of the app writing to a file and the test looking at the exact file and verifying the writing, the app calls the HungerTrackerWriter object. The test swaps out the real HungerTrackerWriter with a fake one, and monitors that the expected call is made. This leaves the HungerWriter proper tests blissfully unaware of the implementation details while still verifying that the app is doing what was expected.
[Technical details: somewhere I read that the android junit framework handled mocks easily. This was something of an exaggeration. It has built in mocking for a lot of Android specific classes, but nothing for user created classes. There are many well regarded Java mocking libraries, none of which provided comprehensive instructions that worked for me. Apparently they integrate weirdly with Android? My first round of mocking was hand-written, just so I could work on test code. I never did get the best regarded library, Mockito, working, but I eventually cobbled together a set of build instructions that made EasyMock work]
You might think that making that big a change in order to make something more testable is the tail wagging the dog, but as I was doing it something magic happened. Those problems with reading exactly as many entries as there were and putting them in a list (as opposed to reading exactly 10 and dumping them in a string) were suddenly much easier to conceptualize. What seemed so muddled when it was part of HungerTracker was suddenly easy to think about when it was part of HungerTrackerWriter.
If you are super curious, here is the code before the refactor, here is the code after, and here is the test code with mocks.