Fellow Engineering Managers: This is what your job is

As consumers, I think we can identify with the basic principle that we pay for goods and services. It’s how we interact with companies. As employees of a company ourselves, we have an intuitive sense that this is how our customers interact with our product or service:

+----------+      Pays Money        +----------+
|          +------------------------>          |
| Your     |                        | Your     |
| Customer |                        | Product  |
|          <------------------------+          |
+----------+     Receives Value     +----------+

As an Individual Contributor, that is, someone whose work is evaluated based on their own individual output, you might intuitively understand this same dynamic.

+----------+      Pays Money        +----------+
|          +------------------------>          |
| Your     |                        | Your     |
| Employer |                        | Output   |
|          <------------------------+          |
+----------+     Receives Value     +----------+

Note that here I’m saying “your output” and not “your time” for reasons discussed in a previous post: Fellow Engineers: This is where your money comes from.

But… how should a manager think about their job? We know that if you zoom way out, our customers pay us for our product. And, if you zoom way in, we have a company paying an individual for their individual work product. But, managers in the middle aren’t directly in either of these situations. Managers might view themselves as “glue” between the two. Their jobs might feel amorphous. Many managers, particularly new ones have a very hard time evaluating their own performance and success. Although it may not seem obvious, I think a useful framework for thinking about this is staring us right in the face:

               Allocates Resources
 +----------+    Pays You Money      +----------+
 |          +------------------------> Your     |
 | Your     |                        | Teams'   |
 | Employer |                        | Output   |
 |          <------------------------+          |
 +----------+     Receives Value     +----------+

The big shift here is twofold: (1) You are allocated resources beyond a paycheck and tools for individual work: you’ve got other people working at your direction, and (2) You’re now accountable for their collective output.

There are plenty of ways to get lost in the sea of things you’re now responsible for. You might beat yourself up about the fact that you implemented a new story points system but people aren’t estimating well. You might be upset that one of your team members is unhappy about how another team member, or some process, or the company at large. You might in fact think you’re successful because you see your team working very hard. Or, you might think you’re failing because the team is working too hard. You might be stressed out about defect rates, delivery dates, technical debt, work/life balance, quality and quantity of meetings, technical documentation, and on and on and on. Indeed you need to pay attention to them – but don’t forget these are all means to an end.

The end is the collective output of your team. Ideally you have plenty of autonomy and creativity to bring to bear to improve this. But, all of those tactics are in the name of output. If you ever find yourself getting lost in the weeds, focus on things with the greatest impact on your teams’ output.

But, there’s another dimension at work here as you traverse the IC -> manager -> company continuum: The degree to which you decide what you produce (what problem you’re solving), and the consequences of that decision. At the highest level, if a company does not provide a product or service that anyone pays for – they don’t find Product-Market Fit – it dies. The consequences are existential and the vastness of what they could choose to produce is infinite.

At the IC level, you aren’t typically responsible for deciding what problem you’re solving. Your company/boss/product manager explains what it is they’d like you to build, and you operate within that boundary. You attempt to build something that’s high quality, on time, performant, etc. But, if you were asked to build the wrong thing, you’re not accountable for that. Typically you don’t face any consequences for building the wrong thing, since that decision was not your responsibility.

And here we are again, in the middle, as a manager. Not only are you responsible for the collective output of your team, but as your scope increases, so too does your accountability for what problems your team is solving. The question of “are we working on the right thing?” is increasingly borne by you as you move up the organization. That, in fact, may become the question that eats at you on a daily basis more than any other. You’ve learned how to deliver solutions. You can help and advise members of your team to do the same. But… now you also have to start taking ownership of whether you’re solving the right problems.

Most companies fail. Their founders are usually unsuccessful at creating a viable business. But, here’s the good news, managers: you’re not a founder. The odds are not so long for you. You don’t have to deal with an infinite set of possibilities and mistakes are likely not existential. What you need to do is spend considerable time aligning yourself with the business.

In the diagrams above, your responsibility is on the right. The party on the left is the party you need to care about to be successful. For anyone but the top brass, you’ve got a comparatively straightforward answer as to who that is. At a minimum, it’s your boss. But, unlike an IC, your boss is probably not telling you what to do. They’re hopefully telling you what problems they want solved, what metrics they want moved, what products they want shipped. If they’re not telling you that, it’s your job to either extract that information from them, or decide what you think success looks like and ensure they know what problem you’re solving.

Then, execute.

I wanted to stop sleeping next to my phone.

The painting “Mobile Lovers” by Banksy always struck a chord with me. I know I spend a lot of time looking at my phone, and am wary of it being at the expense of experiencing real life. I think it’s a very powerful visual.

Source:Banksy Gives Controversial Mobile Lovers Artwork to Bristol Youth Club

One specific scenario in which I would really like to stop looking at my phone is in bed right before I sleep. There are countless articles about the damage it does to your sleep quality. However, like many people with operational responsibilities at tech companies, there’s the possibility that I could be paged at any time, and those pages come via my phone. Turning it off before bed is not a realistic option. When I wake up in the middle of the night, I will often check my phone to see if I missed anything important. Even with Night Mode on, this is still a fairly big bright light in my face, disrupting my ability to get back to sleep. Worse, I might see some distracting thing that lures me into needless latenight phone engagement.

The reality is I didn’t need all of my phone’s capabilities at night, I just needed to be able to receive critical notifications from specific sources. I knew I still wanted something next to my bed that I could glance at – but Not My Phone.

My idea – what if I had a low-light bedside clock that could show notifications on it? I had a spare Raspberry Pi that wasn’t being put to use. Maybe I could code something up between it and my phone, using Bluetooth or similar. As I started to poke around, I found a solution that was even simpler… a company called Pushbullet had already done 90% of the work for me – they built an app that lets you get your phone’s push notifications via an API. So… I grabbed a domain and notmyphone.com was born.

The case does somewhat resemble a homemade bomb

I picked up this cheap screen & case for the Raspberry Pi since it didn’t look too ugly in the photos. As I later learned, the photos don’t show the power cord, which sticks out the top and looks ridiculous. But, c’est la vie – it worked and can be turned down nice and dim. Since the Pushbullet API supports websockets for notifications, I was able to build an almost completely static site (it’s hosted on GitHub Pages) to serve the UI, and updates are sent directly to the client. The only dynamic part I needed was the OAuth login, which I just built as a Cloudflare Worker.

While I was targeting the 480×320 screen, it’s simple enough that it can really run anywhere, and you can easily test it out in the browser. I wanted it to be able to accumulate a few notifications (it’s coded to store the last 4) in case I woke up and missed more than one thing. They just stack up and the oldest one rolls off the screen as they accumulate.

A neat behavior the Pushbullet API enabled me to add was if you dismiss the notification on your phone, it also gets dismissed from the bedside clock. This way it’s not accumulating things you’ve already seen, assuming you’re away from bed when the notifications arrive. You can also fully customize which apps send messages to Pushbullet via their mobile app, so I’ve tuned it down such that I’m not getting LinkedIn notifications, etc. Only things I deem important enough that I want to see if I wake up at 2am show up on the clock.

Okay, so it’s not a beautiful work of art, but when I go to bed, I put my phone face-down without worry that I’m missing anything. When I wake up in the middle of the night, I can glance at the clock and see that all is well and go back to bed without unleashing a phone-screen’s worth of light into my eyes.

If this is interesting to anyone, feedback & pull requests always welcome. In building this I also developed a Sentry client for Cloudflare Workers to help me debug issues, which you might find useful for your projects. Fair warning: I’m by no means a JavaScript expert.

Fellow Engineers: This is where your money comes from

Recently I saw some rather surprising conversations on Reddit’s /r/cscareerquestions which is generally a great place to talk through different CS Career issues people are having and try to help out.

In a thread about Coinbase mistreating a candidate (a legitimate complaint, it seems) someone made the assertion:

You programmers are crazy with the free work. Someone tells me they want anything over an hour and a half of my time, I will decline.

This was in the context of the interview process, mind you.

Another thread which really got my mind whirring was this one: How can I pursue technical excellence above all else, while still getting paid well? which includes this dilemma:

Ultimately, I want a profitable product to be a byproduct of my excellent engineering, not have my engineering be just a means to an end, of getting to a profitable product.

But, I also want to be paid well.

My worldview is so far misaligned with the framing of these questions that it’s hard for me to engage with them directly. If you’re an engineer building a product or service, and you care about getting paid, I think the most important thing you should be thinking about is where does that money come from?

There are a lot of valid answers to that question, but I think most of the time the calculus reduces to: we get our money from our customers. Sure, you may be early stage and getting paid by investment money for now… but the reason they’re paying you that money is because they’re betting that eventually you’ll have built a real business and customers are going to pay for your product or service.

So, if the money that pays your paycheck can be traced back to your customers… how do you justify getting paid more money? At that point it’s simple… find a ways to impact the value your company is delivering to customers. But, there are a few subtleties here:

  • Your customers are not paying you for your time (slightly different for consultants).
  • Your customers are not paying you for your education.
  • Your customers aren’t even paying you for your individual output.

That last one can be counter-intuitive, but your customers are paying your company for the value your company delivers to them.

If you want to spend your life crafting beautiful code with headphones on, you can absolutely do that. You will get paid just fine for that. But if you’re not influencing others and helping the broader team execute, you’re setting a ceiling on the degree to which you can contribute to the company’s output. All you can contribute is what your own two hands can code.  In basketball, there’s a metric they started tracking in recent years called on-off splits. Simply, it’s meant to capture how much better your team is with a given player on or off the court. I love this metric because it’s an attempt to measure an individual’s impact on a team’s performance with an acknowledgement that individual statistics can’t paint the full picture.

This is why engineering career ladders start to layer in responsibilities for things that a single individual can’t accomplish themselves. This doesn’t mean you need to become a manager, but it does mean you need to look beyond yourself to maximize the value you’re able to bring to the people who are ultimately paying you.

There are other jobs where this is not the case. If you’re a cashier at a store where you have no real control over whether 0 people walk through the door that hour or 100 people, then you’re in a scenario where you’re simply being paid for your time. The value you’re delivering to customers is marginally within your control. In software, this isn’t the case at all. There’s no limit to what you can build, nor a cap on the value you can deliver.

I’m not trying to make a simple capitalist argument here either. Pretend you’re doing open source for free. Do you care if anyone on planet Earth ever uses that library you built? If so, your focus again is going to need to be on the value you’re delivering to your customers. They’re not using it because you put a lot of hours into it. They’re not using it because you went to a good school and read a lot of academic papers. You know this first hand, because you yourself are a user of open source projects and that’s not how you choose them. Subtract the money part of the equation and the premise still holds.

But wait! You may be saying… my job is a lot more like that cashier scenario… I have no control over how many customers walk through our door. And yes, this is the reason why if you care about how much you get paid, you need to evaluate the company too. You know this, and you even do this… but you may not have directly linked these two concepts together. In order for the value you’re creating to be realized by customers, a lot of other components of the business need to be working well. If you go to work on Google search, you’re walking into a situation where they’ve already solved the problem of attracting billions of searches per day. Lucky you – you’re handed an opportunity where you can directly deliver value to users.  However, if you’re joining a stealth startup… there’s a lot more risk there. Is the company solving a meaningful problem for customers? Are we starting with the right featureset? Is our marketing team going to be successful in marketing it, and our sales team to sell it? This stuff has a direct impact on you, because it deals with where your money comes from.

This is why I struggle with scenarios where people discuss pay and work without considering value. If you want to increase your compensation over time, continue to put yourself in a position where you can deliver the most value.

Covariance and Contravariance

The concept of covariance and contravariance is fairly straightforward for basic datatypes, but it gets a lot less intuitive when you start dealing with generic collections. I recently, finally, got my head around it.

Here are some simple cases with simple classes in C# (for brevity, I’m leaving out the rules for basic datatypes). A covariant conversion is when you convert from a derived class to a class that it inherits from. It requires no casting and makes logical sense:
string foo = "foo";
object o = foo; //you can assign an string to an object

A contravariant conversion is the opposite, and assignment requires a cast (which could throw an exception if it can’t be converted):
object foo = "foo";
string s = (string)foo;

Enter Collections

Though it’s obvious that you can convert a string into an object, shouldn’t you also be able to do this?
var strings = new List<string>();
List<object> objects = strings;

The short answer is no. Though converting from string to object is covariant, converting from a List of strings to a List of objects is not. A cast won’t compile either.

Want to see why? You can actually try it for yourself with an array, because an array is covariant (considered by some to be a mistake):
string[] strings = new string[2];
strings[0] = "foo";

object[] objects = strings;
objects[1] = new Object(); //things go BOOM.

This throws an OverflowException because you just tried to put an object into an array of strings. So, when Microsoft implemented generic lists, they didn’t allow you to expose yourself to this mistake, and they catch it in the compiler. That’s where covariance gets tricky.

In fact, contravariance gets tricky as well. To steal part of Eric Lippert’s example here, shouldn’t this compile? (Assuming Giraffe inherits from Animal)
void Foo(Giraffe g) {...}
Func<Animal> action1 = Foo;

This code is trying to make the assertion that the Foo method, which accepts a Giraffe as a parameter implements a delegate which accepts an Animal as a parameter. The problem is, if you actually called action1 with an Animal aside from a Giraffe, Foo wouldn’t be able to handle it and would produce an exception.

But, aren’t there other cases that don’t cause problems?

There are, which is why a number of changes were made to C# 4.0.

In our list/array example… what if you never added elements to the list? Wouldn’t the covariant conversion be safe? You’d never be able to add an object to an array of strings. The answer is yes, which is why the IEnumerable interface is marked covariant. This is perfectly valid (same example as above, swapping out List for IEnumerable):
var strings = new IEnumerable<string>();
IEnumerable<object> objects = strings;

IEnumerable is now considered covariant since it’s interface only exposes methods related to reading.

Similarly useful capabilities were added with regard to contravariance (example taken from here):
static string GetString() { return ""; }
Func strFun = GetString;
FuncobjFun = strFun;

The last line used to throw an exception, however this is actually a safe operation – any caller expecting an object to be returned will also be able to handle a string.

"Easy" Problems

In software, you wind up spending most of your time solving easy problems. Problems that have been solved before and, thanks to Google, have solutions available in an instant. Thousands of well-defined, no-risk, completely solvable problems.

Virtually everything having to do with a user interface, if you’ve seen it done before, is “easy.” Gmail has a drag-and-drop attachment feature, so clearly that problem has been solved. Facebook has a live-scrolling ticker of events – piece of cake, just do what they did. Also, anything that has an open source solution is easy. Thank you Solr/Lucene, search is easy. Thank you Hadoop, doing computations on huge datasets is easy. Thank you Ruby on Rails, building complete websites can be done in 15 minutes.

I actually do think all of these things are easy, to the extent that “easy” means you’re going to be able to solve them without needing to hire an expert and you won’t need to dust off your old Algorithms textbook at any point in the process. But there are a few things “easy” doesn’t mean:

Easy != Fast

Just because you know how to do it, that doesn’t mean it can be done quickly. We all know how to mow a lawn. Can you do 10 acres in 5 minutes?

Depending on the problem you’re solving, usually one of two reasons explains why Easy != Fast

1. The problem is clear, but tedious to solve

Building a sign-up form is simple – some text boxes, and a submit button. Of course, what sign-up form would be complete without validation, autocompletion/correction, tooltips, markers for optional/required, anti-bot/spam protection… and each of those things is easy too, but you’ve just got a lot of lawn to mow. (photo from: smashing magazine)

2. The problem is solved by a 3rd party tool, and it’s got it’s own… problems

Solr does, in fact, make it very easy to build a search engine that produces fast, relevant results. Now, bone up on schema.xml, db-data-config.xml, the various query parsers and their associated syntaxes, then review what the best/current libraries are for whatever language you’re using. It’s true, you don’t have to write any algorithms. You’ve also saved yourself time over building this thing from scratch – no question. But, you’re still about to spend a considerable amount of time on this.

Easy != Well Defined

There are still the fundamentals of software engineering at play. The example of the registration form above was also partially an tale of vague requirements.

“We want a sign up form just like foo.com has” is the easiest way to spec a feature – you just point to something else and say “do it like that.” Even though that may seem less vague than “we want a sign up form”, unless you truly understand the thing you’re referring to you may have accidentally added more requirements than you meant to. Did you notice the foo.com has a live, password strength calculation and doesn’t let you sign up unless the password is strong enough? Did your developer just lose a few hours researching the best plugins/schemes for that, then implementing them, all to build something you didn’t actually need?

Easy == Solved, but what does Solved mean?

Google makes billions of dollars on CPC ads. Paypal makes billions of dollars in processing payments. They each have plenty of competitors doing the same things, so the technologies behind processing CPC ads and sending payments are surely mature, and these are cases of solved problems.

But how much time and effort do these companies spend fighting fraud every day? Google has an Ad Traffic Quality team. Paypal has a Fraud Investigation Team.

Sometimes a solved problem only looks that way because there is a metric ton of ongoing work making it appear that way.

Want to know why Nordstrom has beautiful, consistent photography of all of their products on their shopping pages, with the ability to zoom in on, and see a product at multiple angles? Solved problem: simply unbox every single thing you sell and photograph it the exact same way from the exact same angles. After that little exercise, adding a zoom feature is pretty straightforward.

Piece of Cake

I don’t object to using the word “easy” in software. It’s useful to acknowledge that something has minimal technical risk. But, be careful when it creeps into discussions about scheduling or operations. Time is not measured in units of difficulty.

Gmail’s new scrollbars subtly prevent me from sending mail.

In the last 2 weeks, I’ve noticed on several occasions I’ve thought I’d sent mail only to find it sitting as a “Draft” in Gmail. I began to think there was a horrible bug in Gmail and was having flashbacks to the days of figuring out why Outlook would leave mail stuck in your outbox.

Today I figured it out. It’s the scrollbars.

When you start replying to the message, assuming you scroll down a little into the body (which I seem to do often on my laptop’s screen, but less often on a desktop screen) the “send” button scrolls off. But, it’s not obvious that you’ve lost the send button, because there is still a top row of buttons. I wind up, subconsciously, clicking the “back arrow” button as the closest thing to “send” or “reply.”

If the scrollbars were the traditional browser-standard ones, it would be obvious to me that I’m in a frame that had scrolled down. For example, it’s obvious inside the message pane itself. As it stands now, I don’t even notice that a row of buttons has scrolled off of the page, since only part of the page is scrolling, and it’s doing so very subtly.

Windows Resource Monitor

Windows has always made it very easy to see what your CPU is doing, and how much memory you’re using, via Task Manager. However, the bottleneck in many cases is disk I/O, and it’s not nearly as obvious. Though you could add additional I/O-related columns in the task manager process list, I/O isn’t summarized in a graphical form. Windows Resource Monitor does it though, and it’s actually a click away once you’re in Task Manager:

If you fire it up, the UI is oriented around the resource you’re looking to monitor – CPU, Memory, Disk, and Network. The Disk panel has graphs of Disk Queue Length, which you’ll recognize if you’ve used Perfmon before as one of the most useful counters for spotting I/O bottlenecks:

After discovering it, I dropped a second drive in my machine to do builds on. There is still a lot of activity on the C: drive that I’ve yet to pick through, but moving the builds to a different drive has made a noticeable difference in the responsiveness of my system while the compiler is running.

Howto: Copy a Certificate out of IIS and into a Coyote Traffic Management Sever

No one probably wants to read this, but I couldn’t find the full end-to-end walkthrough on the internet, so I figured it should be there. Here are the steps (please suggest a faster way if you know of one!):

1. Export the Certificate using the MMC Snap In Tool (instructions found here but summarized below.

There are a bunch of ways to export a certificate, each of which misses various parts that you’ll need. This makes sure you get the cert chain and the private key:

  1. Start > Run type in “MMC” and click OK
  2. Go into the File Tab > select Add/Remove Snap-in
  3. Click on Certificates and click on Add.
  4. Select Computer Account > Click Next
  5. Select Local Computer > Click Finish
  6. Click OK to close the Add/Remove Snap-in window.
  7. Double click on Certificates (Local Computer) in the center window.
  8. Double click on the Personal folder, and then on Certificates.
  9. Right Click on the Certificate you would like to backup and choose > ALL TASKS > Export
  10. Follow the Certificate Export Wizard to backup your certificate to a .pfx file.
  11. Choose to ‘Yes, export the private key’
  12. Choose to “Include all certificates in certificate path if possible.” (do NOT select the delete Private Key option)
  13. Enter a password you will remember
  14. Choose to save file on a set location
  15. Finish

2. Convert the binary pfx file into a .pem file with openssl (tip here, but reproduced below)
openssl pkcs12 -in publicAndprivate.pfx -out publicAndprivate.pem

3. Strip the password out of your private key
openssl rsa -in publicAndprivate.pem -out private.pem

4. Put the password-less private key into your .pem file
Open your “publicAndprivate.pem” file, and replace the private key section (marked with —–BEGIN RSA PRIVATE KEY—–) with the contents of your private.pem file.

That new file now has your cert, and password-less private key for uploading into a Coyote box. There may be a faster way (openssl may have a different combination of flags) but that did it for me.

The Facebook F8 story that no one seems to be writing…

If you develop Facebook applications, or have a website you’d like to integrate with Facebook connect, you have undoubtedly seen at least some of the videos from the F8 Conference this weekend. By and large, I found the announcements impressive, the technology decisions smart, and the overall direction of the platform to be very exciting. Plenty of stories have been written about these initiatives and the impact they’ll have on the internet at large.

But, here’s a story that I haven’t seen written (or at least, hasn’t bubbled up in Hacker News): a lot of this stuff doesn’t actually work. All of the developers must know this. The forums have been down since launch. In some of the talks they admitted that although these features are live right now, they are not yet documented (ie. you can’t use them). And, there’s my favorite: they released the Like button for the web… which works everywhere except on Facebook.

The Like Button

With the announcement of the social plugins, I was immediately interested in getting the Like button up and running. This was, after all “just one line of HTML” per the presentations, so it should have been brain-dead simple. For the Like button (just one part of the Social Plugins inititative which is just one part of the overall announcements) I encountered the following interesting things:

  1. It was live on CNN.com… sometimes. Various times throughout the last few days the button was there, then it was broken and had an error screen where the people’s faces would be.
  2. If you use Facebook Connect already, you’re going to have to upgrade to the latest libraries to make use of the Like button. Not only is this upgrade undocumented, but where you used to find documentation for the old version, you now get redirected to the new documentation home page. So, even if you wanted to see how things used to work, you need to do some digging.
    This search result, which used to take you to the documentation for this method, now redirects you to the home page of the new documentation.
    You will eventually find that the new library has not reached feature-parity with the old one, and some of the features you used to rely on have not yet been implemented.
  3. The Like button itself does not work on Facebook applications. If you write a facebook app, or want to put some FBML on a Boxes tab, etc… the Like button does not work there. <fb:like /> produces nothing.


I thought the Facepile plugin made for a great pitch. Imagine going to a site and seeing your friends who are on it before you even sign up! A great way to increase conversions. The problem is, again, that it doesn’t actually work.

The Facebook developer forums were up earlier in the week, just after F8, but very few people could log into them. There were literally a handful of posts in the entire forum about all the new features that had just gone live. There was, if I recall, only one thread on Facepille. First post was that it didn’t work, and there were a few responses that were effectively “+1“.

Facebook Connect

Log in to sites around the web with your Facebook password. Pretty handy when it works – one less password to remember. When it doesn’t work? Pretty disastrous. Facebook Connect was up-and-down regularly throughout the last few days. It didn’t even work on the Facebook forums. Most of us were locked out (they had a backup signin mechanism, but that wasn’t working either). Just remember if you’re going to build a site and support Facebook Connect, having it as your sole authentication provider is a bad decision. Consider it a nice-to-have that might ease the friction of people signing up, but this is not a 99% SLA uptime universal login system.

Fixes Coming Soon?

I’m sure Facebook will get all of this cleaned up in time, I’m just surprised the degree to which they’ve been allowed to skate for 5 days without seeing stories pop up. When popular software companies put out sub-par products, the media slaughters them. The most popular site on the web is getting a pass.