On Hiring: Developers Are Like Stocks

This post is for those of you who hire developers, and also junior developers who want to be hired. Let’s talk about how developers are just like individual stocks in the stock market. Time for a little role-playing: you’re now a stock market investor.

As a financial advisor, your company has given you $2,000,000 USD to invest in the stock market. It’s made very clear that the future of the company depends on the return on investment (herein called ROI) – “gains” – that your investments bring to the company. Your decisions will have a major impact on the company’s future. Given that kind of pressure, what’s your investment strategy for success? Begin by reviewing the kinds of stocks available to invest in.

Let’s Review Some Stocks

You take a look at stock #1. It has been on the market for a decade, has nearly consistently yielded high returns (with references you can investigate and check into), and is very reputable. Putting a good chunk of your money here is probably a reasonable call, since this stock is vetted and has historically provided value over time. It’s unlikely to suddenly drop to no value, and if you see it going south you can bail out before you lose it all.

Stock #2 is the interesting one. It’s brand new to the market. You can find no history on it, no performance trends, no reputation, nothing. It’s a total wildcard that has a reasonably low price tag – about 1/3 of stock #1. Its value could skyrocket resulting in incredible ROI. However, it could also end up being a dud, resulting in losing it all. You have little information to go on: this stock is truly a gamble. Do you invest heavily in it?

Given the two options above, what’s the smart move? In general, putting all of your money into a single thing is very risky, so you’re likely to diversify your portfolio a bit. It doesn’t make a ton of sense to invest heavily into stock #2 because it’s a major gamble, but there’s some room for potential and it might pay off. So why not put 80% into different stocks that fit the archetype of stock #1 and the other 20% in stocks that fit #2’s profile? That would make for a smart investment with some near-guaranteed returns, including some investment into gambles with high potential.

Stocks On Market == Devs On Market

Stock #1 is a senior developer with a proven track record and solid reputation. Stock #2 is a junior developer.

Hiring nothing but juniors is a recipe for high volatility and potential disaster, for reasons that become obvious when given the stock market analogy above. Hiring nothing but seniors is one way to get reasonable gains, however you miss out on significant potential to hire an incredible up-and-coming junior if you never hire any at all. A good strategy incorporates both, with seniors afforded time to mentor the juniors and develop their skills.

Getting Hired As A Junior

As a junior developer, the less artifacts that you can point to and show to companies, the more of a risk you are for them to take. You can mitigate some of this risk with a good interview, but if that interview doesn’t include coding tests which you ace then it might not be enough to get you in the door.

A junior should strive to create artifacts that reduce the risk of hiring them. These could take virtually any format, and given that everybody is different and we are not all afforded the same privileges and opportunities, one should strive to create artifacts that suit their situation. Single parent with 2 children and little free time? Put a few hours each week into an open source project (or contribute to other open source projects). You’ll be amazed how quickly that adds up. Unemployed with tons of free time? Create a project that shows off your skills and stretches your knowledge, which in turn causes you to learn. Struggling with the whole “I need a job to get the experience to get a job” thing? I’ve been there myself, and while my situation was surely not identical to yours, I found that investing some time into reading books and writing small applications to demonstrate my skills did wonders for potential employers.

The point is that all developers are going to sell themselves as hard as they can to a potential employer. To an employer, they may all look similar. Do what you can to stand out and reduce uncertainty by creating evidence of your potential and abilities, and show that to them instead. Talk is cheap, action speaks louder than words.

GitLab Data Loss: A Discussion

In case you missed the big news in the industry this week, a GitLab employee accidentally deleted a ton of production data and took their platform down for hours. It was only when everything was on fire and they were in deep trouble that they turned to their backup systems… only to find that none of them actually worked.

Backup Prod Data Regularly

Not exactly a groundbreaking statement, right? Everybody knows this. If there was a “working in corporate IT 101” manual it would have a chapter on this concept. It’s common sense.

Even still, a lot of people and companies – like GitLab – tend to “set and forget” their backups. They probably created their backup mechanism years ago, tested it at the time, confirmed that it worked, and then scheduled it to run every night at 1am EST or something. Then, since it was out of sight and out of mind, they promptly forgot about it and moved on to other things. After all, they never had a need to check on it right? Nothing had broken down. Until yesterday.

A Guide To Good Backup Process

The secret to ensuring that your backup process is effective and functional is to integrate it into your daily work. One of the best ways to do this is to use it to set up a new dev’s local environment. Have them configure and install the IDE and related tools, and then have them pull down the most recent backup and restore from it to set up their local database. What’s that, you say? It has PII and sensitive data? You’re probably right, which is why your backup process should, as appropriate, create 2 copies: 1 that strips the data (for local dev env) and 1 that doesn’t (for prod restore).

Great, so you’ve confirmed that your backups work for a local environment, but what about production? The next step in a good process is simple too: artificially destroy your production environment regularly. Set up fail-over tests at off hours (and compensate your amazing site reliability / IT team appropriately for conducting these tests in off hours too). I recommend once per quarter as a starting point: at 2am on Sunday drop your production database (but don’t delete it, just take it offline so you can bring it back if you find out that your backup system isn’t working). Let your staff work to restore a recent backup and bring the site back online. Announce the outage in advance to your users, and update people on social media or via email when it begins and ends.

There is much to be learned and gained from this intrusive and destructive process. For one, you will force your dev team to create a good “the site is down” experience since your customers will otherwise see infinitely spinning web pages or terrible error dumps. Another is that you can time the average outage and thus discern how long you’ll be down if your production database ever actually takes a spill. Finally, your disaster recovery staff will be fresh on their skills and able to fix your real outages quickly and predictably. There are many tangible and hidden benefits derived from just a few hours of planned outage per year.

GitLab Did One Thing Right

The final step in your solid, functional backup process which you test quarterly and use to spin up new dev hires is to document the hell out of everything. When you do these planned outages, have the disaster recovery staff document, step by step, the actions taken to fix it. When you have real live outages, document those too and share the knowledge with the public.

GitLab got this part right, and are being heralded as a great example and learning experience in the industry instead of spited for mysterious downtimes and no communication. I promise you that this week, many disaster recovery people are doing extra backup tests that they wouldn’t have thought to do otherwise – all as a direct result of the GitLab incident. Making your disasters and their recoveries public creates goodwill in the community, provides a learning experience, and shows people that you can be trusted.

GitLab took a bad situation and created the best possible outcome, both for themselves and the entire community. For that they should be thanked, not mocked. After all, we are all human and we all make mistakes. Knowing this, you’ll be really glad that you practice making mistakes every quarter when your production database actually goes down in flames.

Dev Team Interactions: Conducting Good Code Reviews

In part 2 of my series on dev team interactions, I’d like to talk about conducting good code reviews. Most dev teams will find themselves in a situation where code reviews are necessary, and in my experience many do them very poorly. I’ve even worked in companies that had such a negative code review culture that people left the review sessions upset, even considering quitting. With a few easy adjustments, you can quickly learn to conduct excellent and positive code reviews with your team.

The Ground Rules

A code review is a process. Like any good process, clear rules need to be established and followed to ensure a consistent experience. Here are mine:

  • Attack the code, never the person. Criticizing code is OK, but people are not code. It’s never OK to criticize the person and make them feel bad. Focus strictly on the code output and never make it personal.
  • Don’t laugh or make negative jokes. A person who has their work on display – often on a projector in front of others – is feeling self-conscious as it is. Don’t snicker at their work. Avoid joking about their decisions. I assure you they are trying to do the right thing.
  • Set a strict time limit as a means of focus. Make the code review 15 minutes, 30 minutes, or even 1 hour. Stick to this schedule. This forces you to prioritize the important stuff and ensures (intentionally) that you can’t review absolutely everything the person has done. Don’t take unlimited time to scrutinize every single line of code written. Ever had someone comb through your code line by line, making commentary as they go? “And how did that make you feel?”
  • Thank the person for sharing their code with you. A code review is an intimidating, scary thing – especially for developers on the junior side of the spectrum. Set the tone correctly by being appreciative of their time and sharing. Make it known that they are valued and you appreciate their work up front. This will help them feel relaxed and learn to enjoy code reviews, which in turn will cause them to want to share more of their code willingly in the future as well.

The above rules serve only as an example from my personal experience. You should create rules that work for your company and work culture. Use real and practical standards that matter to your team, not just theoretical ideologies that someone on your team read in a book. Always remember: a process is only as good as the people that follow it, so try to be consistent with whatever rules you decide on. And if they aren’t working well in practice, change them up!

Seek Understanding, Not Power

The general goal of your code review attendees should be to seek understanding, not explanations. Avoid an us-them conflict or standoff. This can be easily accomplished with a subtle shift in communication approach. Rather then asking aggressive questions that demand the reviewee explain the code to your team such as “why would you do it that way?” or “how could that possibly work?” you need to ask questions to promote understanding the code instead. Once your team and the reviewee correctly understand the code being reviewed, you can proceed to discuss a different approach without conflict or hurt feelings.

When you see some code that makes you think “what the hell were you smoking?” (explain) you should instead ask “Can you tell me why you wrote the method this way?” (understand). These statements are similar but the former gives the power to you while the latter empowers the code reviewee to share their knowledge and thought process in a non-defensive way. This approach to questioning takes a bit of practice, but is very powerful. Some other examples of how you’d change common code review aggressive thoughts and statements from explaining to understanding:

  • “This class name is wrong” becomes “This class name doesn’t conform to our standards, was that intentional?” You’ll probably find that they say it wasn’t, and agree to fix it on their own volition.
  • “I see a bug in your code!” becomes “I think there’s a null reference exception on line 28 for variable X, do you see how it happens?”
  • “This is terrible” becomes nothing – keep your mouth shut. There’s no value in such a statement other than to make the person feel bad. If the code truly is terrible, express these concerns to the person (and maybe their manager) privately for further investigation and resolution.

People are not robots, and will never conform perfectly to your shop’s coding standards. That’s OK. Pick your battles, and call out only the major violations. Let the little things (like naming and spacing) slide. If the dev is hitting 90% of the standards, the rest of the team can pick up on the 10% deviation without much worry or effort. That is to say, the code won’t be that different than what they expect to see.

If you seek understanding consistently, you’ll find that the person drops their defenses and ego, and instead feels encouraged by your positive approach and attitude. They’ll even start pointing out and suggesting fixes to their code themselves – right on the spot – which is the golden sign of trust and confidence. The best kind of code reviews are the ones that a person points out issues themselves to fix, rather than the team having to do it for them.

Avoid Opinion Wars

When reviewing code, there will be two general categories of issue:

  1. Objective, fact-based issues
  2. Subjective, opinion-based issues

Focus explicitly on objective issues, and disregard all subjective issues. An objective issue is an exception or oversight in conforming to well-defined coding standards. A subjective issue is you not liking the way the person solved the problem, or feeling that what they did is not what you would have done. You’re right because you’re different people. Striving to make others conform to your thought process as the one true standard is egotistical, destructive, and stressful. In the long run you will be unhappy because there will always be a gap between others and yourself. This is natural so go with the flow. Allow members of your team to be individuals and write code with their own flair and flavor. It’s OK, it will be OK, and you will be OK. I promise.

Be Humane

Code is for computers, but programmers are humans. Be kind to each other and always remember that the thing on the other end of the code review is a real live person with feelings and emotions. Treat them with respect in what you say and do. Recognize that they are valuable and thank them for their hard work. Together you will create a great team that others will love being a part of!

Dev Team Interactions: Accountability & Blame

As a developer working for a company, you probably work on a team. The interactions on these teams are sometimes pleasant, and other times hostile. What’s interesting to me is that a lot of the time, a hostile interaction could have been a pleasant one if only approached differently. Hostile teams are created by the actions of the people on them, not by the situations they encounter. One such hostile action is blame.

Blame

Blame is assigned externally – it comes from other people. You cannot control blame when it is directed at you. Blame tends to surface under tense circumstances, such as when the build has broken or a project has failed. It often rears its ugly head in the form of pithy and simplistic statements. “Jane broke the build again!” or “this is Mohinder’s fault!”

Blame is often facilitated – if not encouraged – by a poor workplace culture. When the patterns and practices of the management team demand that heads roll when mistakes are made, blame is the obvious solution. It allows you shift the burden of responsibility to someone else, forcing them to defend themselves from an attack while you retreat to safety.

Blame Never Helps Anything

Blame may solve the immediate problem of your head being on the proverbial chopping block, but it never solves the actual problem at hand. If anything it tends to distract from the issue as the discussion changes from “what went wrong” to “who caused this?” A challenging situation becomes even more complicated as strong negative feelings start to emerge.

Another effect of blame is that people feel alienated and attacked. Team members disengage, afraid to speak up or make changes because they may be attacked for doing so. In this way it damages the innovation and progression of your people, product, and entire company. Blame holds your entire organization hostage.

It’s not hard to see that a workplace which embodies blame culture is really the root problem in-and-of itself.

Accountability

Unlike blame, accountability is assigned internally – it comes from within. It is a positive force of empowerment that requires courage and compassion. Accountability allows people to take control over themselves and their own actions. It destroys “fault” culture while building trust and communication channels with other team members. Statements like “that was my fault team, sorry about that” are welcomed and encouraged, but not necessary.

Accountability can only thrive if the workplace culture is tolerant and accepting. In a blame culture, accountability cannot exist. The mere act of owning up to a mistake assigns the blame to you, and scrutiny and / or punishment is sure to follow. A good work culture is intolerant of blame, instead focusing on people learning from their mistakes and growing as professionals.

A Blameless Workplace

My personal take on accountability as a manager is that “everybody makes mistakes, and as long as you make new and interesting mistakes – rather than repeating them – you have nothing to worry about.”

Mistakes are normal; we all make them regularly. A workplace culture that understands this fact and incorporates it into professional and personal development is one that succeeds with vibrant and engaged teams. Allow people to make mistakes, and follow-up only if they do not learn and grow from those mistakes. Shut down any and all blame conversations immediately. Communicate the difference between assigning blame to someone for their mistakes, and taking ownership of those mistakes themselves. Foster a workplace culture that is blameless.

At Stack Overflow, we do this via a tool that we call the Wheel of Blame. When something goes wrong, anyone in a company chat room can say “not my fault” to spin the wheel. The wheel arbitrarily picks a person from those present in the room and blames them. With blame quickly and definitively assigned, we then move on to fixing the problem.

The Wheel of Blame in action. I'm bad at making gifs so it's not quite right but whatever, I tried.

The Wheel of Blame in action. I’m bad at making gifs so it’s not quite right but whatever, I tried.

Creating Accountability

Despite the Wheel assigning blame – which clearly goes against the blameless culture which I described earlier – this tool is very powerful. It’s a clear and obvious signal to seasoned and new employees alike that we don’t care about blame. When someone is randomly assigned, it’s almost always the case that the problem wasn’t actually their fault. More often than not they had nothing at all to do with the current situation. An ironic and hilarious side effect of the Wheel is that when it does randomly assign the blame to the person who is accountable to the issue, it results in uncontrollable laughter and joking. This alone makes the Wheel worth using: it lightens the mood and communicates our rules around blame in a tribal way (there is no policy written anywhere).

To shift a culture from blame to accountability, begin by shutting down blame discussions. Explain that blame is not helpful, and that the team needs to immediately focus on resolving the issue at hand. Once the problem is solved, consider doing a retrospective which explains what went wrong and who was involved. Circulate this retrospective to any and all interested parties with the clear intention of spreading information, not assigning blame. This allows people to learn and grow from what happened. Continuing this pattern will slowly shift the team away from blame. The trick here is that you don’t have to work on accountability: it will naturally follow when people stop fearing blame.

I encourage you to work towards a culture of accountability on your development team, starting today. Sometimes this transformation can be very difficult to accomplish; particularly when the blame culture starts at the executive level. Nonetheless, do what you can to change the behavior in the part of the company that you influence. Your peers and reports will thank you for it.

Custom ASP.NET MVC Action Result Cache Attribute

If you’re working on an application built using ASP.NET MVC, you’re hopefully aware of the OutputCacheAttribute attribute which can be used to statically cache your dynamic web pages. By adding this attribute to a controller or action method, the output of the method(s) will be stored in memory. For example, if your action method renders a view, then the view page will be cached in memory. This cached view page is then available to the application for all subsequent requests (or until the item expires out of the cache), which can retrieve it from the memory rather than redoing the work to re-create the result again. This is the essence of caching: trading memory for performance.

The OutputCacheAttribute is a really powerful way to improve performance in your MVC application, but isn’t always the most practical. Because it caches the entire page as raw HTML, it circumvents a large part of the MVC pipeline and thus also skips the code that runs to generate the page. This means that if your view has dynamic content that comes from session or ViewData, such as displaying the currently logged in user’s name in the top bar, or the current time of day, or the resulting view of an invalid form post which tells your user to correct their input errors, you’ll quickly discover the error of your ways when you try to cache that page. When David accesses the logged in page for the first time and caches it, everybody else who logs in will be called David on the page. And if David fills out your empty form and presses submit, only to cache the resulting input validation error page, then everybody will see David’s completed form when they have errors too – maybe even including sensitive data like his username, password, or even his credit card information. I think that most of us have seen this kind of (often humorous) caching error before. It’s scary stuff, nonetheless.

A great way to balance the benefits of output caching with the dynamic content and features that the modern ASP.NET MVC web application offers is to create a custom caching attribute. This attribute can cache the ActionResult instead of the raw HTML of the page, and in doing so will allow you to cache all of the work that is done to generate the ActionResult (be it ViewResult or otherwise). By executing within the MVC pipeline, this custom caching attribute will not interrupt or short-circuit the MVC pipeline. This allows for things like SessionState or ViewData to vary per cached request! It’s not quite as efficient as the true OutputCacheAttribute, but my custom ActionResultCacheAttribute is an excellent tradeoff between performance and dynamic data:

/// <summary>
/// Caches the result of an action method.
/// NOTE: you'll need refs to System.Web.Mvc and System.Runtime.Caching
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class ActionResultCacheAttribute : ActionFilterAttribute
{
    private static readonly Dictionary<string, string[]> _varyByParamsSplitCache = new Dictionary<string, string[]>();
    private static readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
    private static readonly MemoryCache _cache = new MemoryCache("ActionResultCacheAttribute");

    /// <summary>
    /// The comma separated parameters to vary the caching by.
    /// </summary>
    public string VaryByParam { get; set; }

    /// <summary>
    /// The sliding expiration, in seconds.
    /// </summary>
    public int SlidingExpiration { get; set; }

    /// <summary>
    /// The duration to cache before expiration, in seconds.
    /// </summary>
    public int Duration { get; set; }

    /// <summary>
    /// Occurs when an action is executing.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // Create the cache key
        var cacheKey = CreateCacheKey(filterContext.RouteData.Values, filterContext.ActionParameters);

        // Try and get the action method result from cache
        var result = _cache.Get(cacheKey) as ActionResult;
        if (result != null)
        {
            // Set the result
            filterContext.Result = result;
            return;
        }

        // Store to HttpContext Items
        filterContext.HttpContext.Items["__actionresultcacheattribute_cachekey"] = cacheKey;
    }

    /// <summary>
    /// Occurs when an action has executed.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        // Don't cache errors
        if (filterContext.Exception != null)
        {
            return;
        }

        // Get the cache key from HttpContext Items
        var cacheKey = filterContext.HttpContext.Items["__actionresultcacheattribute_cachekey"] as string;
        if (string.IsNullOrWhiteSpace(cacheKey))
        {
            return;
        }

        // Cache the result of the action method
        if (SlidingExpiration != 0)
        {
            _cache.Add(cacheKey, filterContext.Result, TimeSpan.FromSeconds(SlidingExpiration));
            return;
        }

        if (Duration != 0)
        {
            _cache.Add(cacheKey, filterContext.Result, DateTime.UtcNow.AddSeconds(Duration));
            return;
        }

        // Default to 1 hour
        _cache.Add(cacheKey, filterContext.Result, DateTime.UtcNow.AddSeconds(60 * 60));
    }

    /// <summary>
    /// Creates the cache key.
    /// </summary>
    /// <param name="routeValues">The route values.</param>
    /// <returns>The cache key.</returns>
    private string CreateCacheKey(RouteValueDictionary routeValues, IDictionary<string, object> actionParameters)
    {
        // Create the cache key prefix as the controller and action method
        var sb = new StringBuilder(routeValues["controller"].ToString());
        sb.Append("_").Append(routeValues["action"].ToString());

        if (string.IsNullOrWhiteSpace(VaryByParam))
        {
            return sb.ToString();
        }

        // Append the cache key from the vary by parameters
        object varyByParamObject = null;
        string[] varyByParamsSplit = null;
        bool gotValue = false;

        _lock.EnterReadLock();
        try
        {
            gotValue = _varyByParamsSplitCache.TryGetValue(VaryByParam, out varyByParamsSplit);
        }
        finally
        {
            _lock.ExitReadLock();
        }

        if (!gotValue)
        {
            _lock.EnterWriteLock();
            try
            {
                varyByParamsSplit = VaryByParam.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                _varyByParamsSplitCache[VaryByParam] = varyByParamsSplit;
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }

        foreach (var varyByParam in varyByParamsSplit)
        {
            // Skip invalid parameters
            if (!actionParameters.TryGetValue(varyByParam, out varyByParamObject))
            {
                continue;
            }

            // Sometimes a parameter will be null
            if (varyByParamObject == null)
            {
                continue;
            }

            sb.Append("_").Append(varyByParamObject.ToString());
        }

        return sb.ToString();
    }
}

You can use this method on a controller to affect all action methods:

[ActionResultCache(Duration = 60 * 60 * 24)]
public class HomeController : Controller
{
    public async Task<ActionResult> TermsOfService()
    {
        return View();
    }
}

Or just apply it to individual action methods:

[ActionResultCache(Duration = 60 * 60 * 24)]
public async Task<ActionResult> TermsOfService()
{
    return View();
}

You can also use it with the VaryByParam property to vary the cached result by the parameter(s) of the action method:

[ActionResultCache(Duration = 60 * 60 * 24, VaryByParam = "username")]
public async Task<ActionResult> ViewUser(string username)
{
    var model = new UserModel
    {
        Username = username,
        ...
    };

    return View(model);
}

The main benefit of this custom caching attribute is that your session state and all global action filter attributes, etc. still run in the MVC pipeline as they would normally. The only code cached and skipped over is the method body of the action method.

Please use and enjoy! Feedback welcomed in the comments.

Our Industry Needs Compassion

Well, I’ve utterly failed to blog at regular intervals, writing only three posts in 2016. Ouch. To be fair, one of those posts is insanely famous (the one about NPM and left-pad.js), but still, I’ve really let my readers – and myself – down.

So, I resolve to write a blog post every single week of 2017, starting today. This will probably mean that I write slightly shorter posts, and maybe even multi-part series posts. My traditional style has been “come upon something that is really bothering me or is really tricky, and proceed to blog about it in great detail writing thousands of words for all to benefit from” which doesn’t really scale well. Instead I plan to take the approach of “write about a new or interesting topic each week, and see what people like and what they don’t like” which will hopefully be better.


This week’s post is about compassion, especially in the field of programming. Let’s use an example that is both recent and practical, if a tad emotional.

3 days ago our dog Ruby died. She was 16 and lived a good, long life. Having said that, her death was unexpected and rather painful to go through. My wife and I were up with Ruby all night comforting her as she slowly passed away from sudden heart failure. The last breath she exhaled will forever be seared into my brain. It feels like it’s all I can think about right now.

My wife and I have been grieving for the past 72 hours in our own ways. This has surfaced as mostly a mix of depression, tears, quick but sad chats about the things we miss about Ruby, and sorrow every time we look somewhere in the house for her only to find that she is no longer there. It sucks.

What’s important to realize is that I am not unique or special in this circumstance. Animals die all of the time, and you don’t feel sad about them because you never met them. They are out of sight, out of mind. Yet they are out there, and the passing of good dogs and cats – as well as other households pets – is happening every single day. Even as you read this.

These events occur in the scope of individual’s lives. There is no national news story about the passing of Ruby to make us all aware of it and help us all feel the effects of it. There never will be. This event is confined to the lives of me, my wife, and our extended family. We suffer through it silently (other than my writing about it and a few social media posts).

This silent suffering is the point that I want to drive home. Others out there are silently suffering too. It might be the death of a family pet, or it might be something else entirely. It’s not a contest of who has it the worst. I want you to simply realize that crappy things are happening to people, even if they are not in your domain and thus you are not aware.

Odds are that someone in your life or workplace is suffering with something that troubles them. Right now for me it’s the passing of my dog. For a close friend of mine it’s stress about work and finding the next permanent job. For another person I know it’s about being a brown man in America and how scared they feel about the future. We all battle demons every single day.

With this in mind, I ask you to be compassionate everywhere, but especially at work. You work with people, not cogs of some machine (even if management may think of them in that way). These people have real feelings and some of them are surely fighting battles you’ve never even fathomed.

Your responsibility as a good member of the IT field – and as a good citizen of this planet – is to demonstrate compassion. Be nice to everyone you work with until you are given a reason not to be. Consider that they might be having a bad day if you feel they’re lashing out or being an asshole, and forgive them. Try to sympathize with what frustrates them. Work to understand them beyond their role at the company and their job output.

We are all in this together. Now more than every we need to be compassionate, respectful, kind, and considerate to others. It is my opinion that our industry has a long history of being hostile to certain people and demographics – such as women – and we must each work individually to change that.

My last request to you: please think hard about what you’ve read here as you begin your first week of work in 2017. I know I will.

Let’s Talk About Rock Stars & Egos

On Plumbers

Picture this situation: you woke up this morning to find that there’s no water coming through your valves and taps. No sink water. No shower water. Having no plumbing experience, you call around for a plumber.

Plumber #1, let’s call him Mario, tells you he can’t be bothered to come check out your issue because it’s minor and he’s very important and too busy for it. You explain that you really need a plumber, and he explains he’ll do it for 1.5x what everybody else costs, and only if you have lunch and coffee ready for him when he arrives. You have no water, keep in mind, so making coffee is an extra special effort.

Plumber #2, let’s call him Luigi, agrees to show up and assess the damage. He walks in your door, doesn’t bother to shake your hand or introduce himself, and immediately gets to work. A few minutes of inspection later and Luigi is telling you that all of your plumbing is wrong. None of the pipes are plumbed how he’d plumb them, so they’re wrong. He needs to rip out the whole plumbing system and do it all again from scratch, which will cost you thousands of dollars. He has a reputation for being skilled: his past references love him, but this is going to cost a lot of money and take a lot of time. It’ll be at least a week before you have running water again.

Plumber #3, let’s call her Peach, asks you some detailed questions about the problem over the phone. “How long have you lived in the home?” “Have you had any prior plumbing issues?” “Has this happened before?” “Do you have any other sources of water?” Based on this analysis, she tells you she has a good idea of what the issue is and agrees to come over later that day, since she’s in the area anyway. She shows up, immediately discovers that the pesky neighbour kids shut off your water main, turns it back on, and then gives you some advice: “it’s not something you need to do right now, but you should upgrade to a locked main switch that operates with a key so that this won’t happen again! Call me if you want something like that installed.”

Now, which one would you hire?

Back to Programming

Let’s take this [terrible] analogy back to programming. Plumber #1 is a rock star developer who demands special treatment and pampering. Plumber #2 has a huge ego, a serious case of not-invented-here syndrome (they didn’t plumb the house so it’s wrong!), and might also be a rock star. Plumber #3 is pragmatic, friendly, sensible, analytical, and balances cost of time and money with urgency. For me personally, #3 is the only one I’d happily hire.

It seems so obvious that egos and not-invented-here cost a lot of money and do a lot of damage in that analogy. It’s less evident in the workplace. Some companies foster the ego and demand to hire rock stars, believing that the “ten ex” developer will outperform others they could hire. What they don’t realize is that the cost of this hire almost certainly outweighs the benefits.

There’s no place for ego in programming. An egotistical programmer does incredible amounts of damage to those around them. They do cultural damage to your company, emotional damage to their peers, and financial damage to your budgets. Those rewrites aren’t cheap!

Don’t be a rock star. Rock stars are cold, hard to approach, notoriously unfriendly and self-absorbed, make no time for others and teaching them (because everything’s about ME!), and are frequently dramatic and rude (to get in the “news” – after all, any publicity is good publicity).

I don’t know about you, but I want to work with Peach. I prefer a humble, thoughtful, talented peer that can teach me while maintaining respect and a relationship of trust. That’s the kind of workplace that I get up every morning excited to go to. Peach is probably not perfect, and has her flaws, but the lack of an ego and attitude means she’s willing to learn and grow – and that’s the key to success in this industry.

If this analogy hit a little close to home, it’s time for a little introspection. The beauty of the human condition is that we are always on a path, growing and changing. Who you are today is not who you are forever. Think about which plumber you resemble above, and then adjust. Next time you’re about to say “that’s all wrong!” or “we have to write it ourselves!”, pause and think: there’s probably a decent a reason that the code exists in its current state. Is now really the time to undertake a very expensive rewrite / greenfield project? Probably not.

NPM & left-pad: Have We Forgotten How To Program?

Okay developers, time to have a serious talk. As you are probably already aware, this week React, Babel, and a bunch of other high-profile packages on NPM broke. The reason they broke is rather astounding:

A simple NPM package called left-pad that was a dependency of their code.

left-pad, at the time of writing this, has 11 stars on GitHub. The entire package is 11 simple lines that implement a basic left-pad string function. In case those links ever die, here is the entire code of the left-pad package:

module.exports = leftpad;
function leftpad (str, len, ch) {
  str = String(str);
  var i = -1;
  if (!ch && ch !== 0) ch = ' ';
  len = len - str.length;
  while (++i < len) {
    str = ch + str;
  }
  return str;
}

What concerns me here is that so many packages and projects took on a dependency for a simple left padding string function, rather than their developers taking 2 minutes to write such a basic function themselves.

As a result of learning about the left-pad disaster, I started investigating the NPM ecosystem. Here are some of the things that I observed:

  • There’s a package called isArray that has 880,000 downloads a day, and 18 million downloads in February of 2016. It has 72 dependent NPM packages. Here’s its entire 1 line of code:
    return toString.call(arr) == '[object Array]';
  • There’s a package called is-positive-integer (GitHub) that is 4 lines long and as of yesterday required 3 dependencies to use. The author has since refactored it to require 0 dependencies, but I have to wonder why it wasn’t that way in the first place.
  • A fresh install of the Babel package includes 41,000 files
  • A blank jspm/npm-based app template now starts with 28,000+ files

All of this leads me to wonder…

Have We Forgotten How To Program?

On what possible plane of existence is this a better solution to past problems? How are hundreds of dependencies and 28,000 files for a blank project template anything but overly complicated and insane?

I get the impression that the NPM ecosystem participants have created a penchant for micro-packages. Rather than write any functions or code, it seems that they prefer to depend on something that someone else has written. It feels to me as if the entire job of an NPM-participating developer is writing the smallest amount of code possible to string existing library calls together in order to create something new that functions uniquely for their personal or business need.

Functions Are Not Packages

Functions are too small to make into a package and dependency. Pure functions don’t have cohesion; they are random snippets of code and nothing more. Who really wants a “cosine” dependency? We’d all really like a “trigonometry” dependency instead which encompasses many “tricky” functions that we don’t want to have to write ourselves. This is much more akin to how .NET and other frameworks create a “core” library of basic functionality. Such a library is vetted by the creators of the language and pretty much guaranteed to be correct and bug-free.

Third Party Problems

There’s absolutely no guarantee that what someone else has written is correct, or even works well. Even if correct, is it the most optimal solution possible? At least when you write the code yourself, you can easily modify it to fix bugs and improve its efficiency. Not that there should be many bugs in 1 line functions.

Second, even if the package’s logic is correct, I can’t help but be amazed by the fact that developers are taking on dependencies for single line functions that they should be able to write with their eyes closed. In my opinion, if you cannot write a left-pad, is-positive-integer, or isArray function in 5 minutes flat (including the time you spend Googling), then you don’t actually know how to code. Any of these would make a great code screening interview question to determine whether or not a candidate can code.

Finally, stringing APIs together and calling it programming doesn’t make it programming. It’s some crazy form of dependency hacking that involves the cloud, over-engineering things, and complexity far beyond what’s actually needed to create great applications.

What’s worse is that if any of your code (or the 3rd party dependency code) has a bug or breaks, you won’t know how to debug or fix it if you don’t know how to program.

Strive For Few Dependencies

Every package that you use adds yet another dependency to your project. Dependencies, by their very name, are things you need in order for your code to function. The more dependencies you take on, the more points of failure you have. Not to mention the more chance for error: have you vetted any of the programmers who have written these functions that you depend on daily?

Take on a dependency for any complex functionality that would take a lot of time, money, and/or debugging to write yourself. Things like a database access layer (ORM) or caching client should be dependencies because they’re complicated and the risk of the dependency is well worth the savings and efficiency.

But, for the love of all that is programming, write your own bloody basic programming functions. Taking on dependencies for these one-liners is just nuts. Don’t believe me? Just ask the React team how well their week has been going, and whether they wish they had written those 11 lines for left-padding a string themselves.

Follow David Haney on Twitter at @haneycodes

Updated Jan 13 2017 with some minor grammar and sentence structure changes.

Developer Compensation: Stack Overflow Doesn’t Stack Rank

Are Developers Good Negotiators?

Developers come from all walks of life, and have many unique interests, passions, and hobbies. Often the only thing that developers have in common is their love for programming. It follows that some are good negotiators; others get the double digit percentage finance rate at the dealership when they go in to buy that new car.

How Does Your Company Determine Compensation?

When you hire developers, how do you decide on their salary? Do you allow for negotiations to take place? Is there a strategy in place where you offer a low value, expecting the candidate to counter with a higher number? Are you pleased when they don’t counter, and you get good talent for cheap?

The thing is, developers are the linchpin in your tech company. They make or break your products – quite literally, in fact. They’re worth a lot of money. You should be paying them what they’re worth as one of many strategies to keep them happy. If you’re low-balling developers with a salary strategy that rewards negotiation skills, you’re probably underpaying them while overpaying the developers who are good negotiators (but maybe not amazing coders).

Your underpaid talent might not feel comfortable asking for a raise to the income that they are worth. Can you guess what happens then? They leave your company for another that values them correctly. The result is that your department has high turnover, lots of churn, and high costs around replacing the fleeting talent.

Stack Ranking: Upsetting Developers Everywhere

One of the most common ways to compensate employees is by employing a stack ranking system. There are varying approaches to stack ranking, but a typical implementation of a stack rank system is as follows:

  • A company employs a ranking system, often a scale of 1 to 5, to assess employees.
  • These numbers often come with generic and impersonal descriptions. The scores themselves are bucketed with percentages that limit the number of employees that may receive a given grade:
    • 1: Exceptional (10% of employees)
    • 2: Highly Effective (20%)
    • 3: Consistently Strong (40%)
    • 4: Partially Effective (20%)
    • 5: Not Effective (10%)
  • Managers are given a fixed $X in raises to hand out for annual reviews.
  • The $X budget for raises is distributed per the grading, with the 1’s getting the biggest chunks, and 5’s often getting nothing.
    • Note that this is how stack ranking is used to control budget costs. You always know exactly how much money is being given out in raises.
  • The 4’s are warned that they’re on the way to being fired if they don’t shape up.
  • Typically, the 5’s get fired or put on a performance plan.

This system – also known by the endearing terms “rank and yank,” “forced distribution,” and “grading on a curve” – is popular because it control costs, both in terms of annual raises and also under-performing employees. It serves as a system that forces the bottom 10% (or whatever the bucket is set at) out of your company regularly. This is not a bad thing in-and-of itself, assuming that the replacements hired are any better. Of course, this is where one of the major problems becomes evident.

Why Stack Ranking Sucks

Here’s the thing: someone always has to be a 5. This system is built on the false assumption that there’s always someone who is Not Effective on your team. It institutionalizes the idea of mandatory mediocrity.

It is easy to see how ridiculous this concept is when you apply it to objects instead of people. For example, let’s review 5 cars with stack ranking: a Ferrari, a Lamborghini, a Maserati, a Porsche, and Rolls Royce. Which one is the exceptional one? Which two are under-performing and mediocre? In this all-star set, they’re all great, but stack ranking demands that one is worse than the others by a large margin.

What happens if you employ good hiring practices and recruit a team of 10 amazing developers? What if they’re all 2’s and 3’s, but you have to give out 4’s and 5’s? You end up having a difficult annual review where you find yourself apologizing and telling your developer how great you think they are. Because you really do think that. But your words are hollow, and their raise and review are the actions that speak louder; at this company they are thought of as mediocre, because someone has to be.

Have you ever had a review where the actions of your manager didn’t match their words? You’re being told what an all-star and amazing player you are on the team, how important and awesome you are, and how everything you touch turns to gold, but your review says “you’re average” and that big fat 3 rating is searing itself into your brain. You’re wondering “if my boss thinks I’m so great, why is my rating average?” That’s what stack ranking gets you. This review probably upset you, and now you’re contemplating your options. Not a great outcome for you or the company.

Stack ranking also stifles the desire of your developers to try new things, take on new roles with more responsibility, and take risks to grow their careers. This is because a 1 or 2 player won’t want to take on the risk of joining a new team, or getting a new boss, who might rank them as a 3 or lower compared to their more seasoned colleagues. Indeed, the smart play is to stay right where they are, and reap the benefits of being on the good end of this ridiculous bell curve.

My biggest concern with stack ranking is the fact that compensation is relative. Your assessed performance depends entirely upon the performance of your peers, as subjectively assessed by your manager. You might have been a 1 if it weren’t for that person who happened to claim it. Now the best you can be is a 2. But if they didn’t work there, perhaps you’d be a 1. Doesn’t seem fair (or even rational), does it?

My Personal Experience With Stack Ranking

I have had a few jobs in the past that employed stack ranking. At one of them, developers picked 3 projects to be assessed on, and then both they and their manager ranked their performance on the projects from 1 to 5. One of the projects that I picked was something that I had built from scratch with a team of 4 people. The thing we built had made the company millions of dollars that year, and I was the lead on it. Naturally, I gave myself a 1 on it. My manager gave me a 3.

I asked him how I could possibly be average at the thing which I created, was the most experienced with at the company, and which had led to millions in additional revenue. His reply was that I was awesome and not to worry too much about the grade. It was very confusing; what he said didn’t match what he wrote.

The review continued, and I ended up being given a 3 out of 5. I got a small raise. This was all conveyed to me as my boss happily told me that I was awesome, to keep up the great work, and that to keep it between me and him but I got the biggest raise on the team.

The idea of having the biggest raise made me feel less wronged… Right up until I found out that it was a lie. My team and I were at lunch a few days later when one person bragged that he got the biggest raise on the team. Another immediately said “what? I was told that I did.” I began to laugh as I realized what my manager had done. He had told us all that we received the biggest raise, and to keep it to ourselves. Perhaps as damage control for the pain that the mediocre grades had inflicted, but unfortunately for him we talked to each other. The jig was up, and now most of us were madder than we would have been had he said nothing to us at all.

A side note: leaving that job was one of my favorite resignations. When I quit, my boss was distraught, but I said (paraphrased) “hey [boss], don’t worry about it! I’m a 3 out of 5, so you should have no issues hiring any other average developer to take up the work I was doing.” The look on his face told me all I needed to know: he had now realized for himself why stack ranking sucks.

How to Properly Review & Compensate Developers

The key to happy developers is fair compensation. Fair compensation is all about transparency. At Stack Overflow, we have a transparent system for assessing employee skills and compensation, which is lovingly called Be More Awesome. There is no magic in employee compensation here, and all developers know exactly what they’re getting paid, why, and what they could get paid in the future. There are no negotiations, no bell curves, and no quotas.

Be More Awesome (BMA) is pretty simple. It is meant to measure skills; we use performance as evidence of skill. A person may rate highly on their BMA for a skill, even if they haven’t used it in the previous year. There are 4 possible grades that can be awarded for each skill:

  • B: Could be more awesome. This is a good thing to work on over the next year — and your manager will help. This can also be applied for new employees who haven’t been in the company long enough to demonstrate that they deserve a higher grade.
  • A: Does as expected, at our high Stack standards. Completely, utterly able to accomplish what is needed.
  • A+: Does more than your team expects, even at our high level. Exceptional and noticeable skills.
  • A+++: Widely recognized level of amazingness. Does and teaches. When people think of this skill, they think of you (or would if they knew you). This will be rare, even on our amazing team.

You might notice that there is no grade below a B. We don’t have C’s or lower because we believe that everyone that works here is awesome. If one of our developers were doing C, D, or F level work, we would already be working closely with them to correct it – prior to reviews.

It’s also not uncommon for people who are earlier in their programming career to receive a lot a B’s. This doesn’t mean they’re doing poorly at all. It just means they’re closer to the beginning of their career than the middle and there’s a lot of opportunity for them to grow.

The actual skills that we assess each year change, but the 2016 BMA chart for developers currently looks like this:

2016 Developer BMA

2016 Developer BMA

There are descriptions that explain what each of these categories are, and they are available for all employees to review at any time.

Once a developer is assessed on a BMA, their letter grades get converted into a numeric score by using a formula that is also published internally for all developers to review. This formula outputs a numeric score between 0.00 and 5.99 (with 5.99 being the best grade), which is then rounded down to the nearest whole number. In short, a developer can receive a score of 0, 1, 2, 3, 4, or 5.

Next we assess the years of programming experience. This is a value that falls in a range from 0 to 25. Naturally, this goes up by 1 at every annual review.

The score and years of experience are then looked up on a chart that has years of experience on the X axis and score on the Y axis, and details salary amounts at each cell. It’s worth redundantly noting that this chart is published internally also and can be reviewed by all developers at any time. Unsurprisingly, the cell that your score and experience points to is exactly what you get paid.

Make Compensation Transparent

There are no secrets or magic in our compensation system. All aspects of it are published internally for all developers to review at any time. They also get input into the changes to the BMA skills each year, well in advance of their annual review. They know the formula that we use to calculate salary. Most importantly, their compensation doesn’t depend on the performance of anyone else. Everybody can be a 5 in our system and everybody can be a 0.

Above all else, our system is fair and evaluates individual performance, not team performance. If you want happy developers and low turnover, I highly encourage you to try adopting such a system yourself. If your company is unwilling to do so, perhaps evaluate why. Are there secrets and magic in the compensation system that you don’t want your employees to know about? Why do you value these hidden metrics? Do your employees feel valued?

A happy developer is a productive developer, and while a fair system does not allow you to easily control salary costs in terms of budget (because everybody can be a 5), it does help increase job satisfaction, lower turnover, and maintain a relationship of trust with managers. And as I’ve written about before, if you don’t have the trust of your employees, you will fail.

EDIT (7/27/2016): We have published a salary calculator based on our internally transparent compensation numbers! Take a look.

PS – hate stack ranking but love Stack Overflow? Come and work with us!

Follow David Haney on Twitter at @haneycodes

Diversity Is Really Freaking Hard

Background

I’m going to discuss an important topic that affects everybody in tech: diversity.

No, this won’t be some preachy post about how diversity is great and how you should be a better human being. Rather, I’m going to tell you about the things I’ve experienced working on diversity – particularly the interesting events of the last few days that happened internally at Stack Overflow.

It’s no secret that the tech industry is not that diverse. It’s mostly dominated by white males, with a few women and minorities making appearances. Those who do enter the industry as a minority often feel marginalized and excluded.

Of about 40 engineering employees at Stack Overflow, maybe 8 are not white men. We can clearly do better.

As you may have learned in my last post, earlier this year I was promoted to Engineering Manager at Stack Overflow (formerly Stack Exchange (formerly Stack Overflow)). One of my first projects was to work on diversity at our company. As a part of this goal, I was given the opportunity to create a new diversity page to showcase our efforts.

There’s a volunteer group that we have internally called the Diversity & Inclusion Panel (DIP). This group works to make Stack Overflow a more open, diverse, and welcoming environment.

There were some awkward feelings that came with taking the lead on the diversity page project. For one, I was a straight white male running a project about diversity, which might raise some eyebrows or make people feel weird/jaded. To mitigate those feelings, and also because I value their opinions, I took the approach of including the DIP in the creation and review of the page. My rationale was that by including a group of self-selected folks who are passionate about diversity, we could reach a solid page design that wasn’t biased by building it myself. To this end the DIP were consulted multiple times and ultimately had the final say on the copy of the page.

Diversity Page Goes Live

After a few months of iterating with designers and the DIP, last week we rolled out the new page. Here’s what it looked like in all its glory (please don’t critique it in the comments – if you do, you missed the point of this post):

Our Shiny New Diversity Page

Our Shiny New Diversity Page

I was excited that we had made progress on such an important and sensitive topic. I announced the roll-out to the DIP group with little feedback or response, which at the time I didn’t think much of. I also broadcast it on Twitter, with very few others from Stack Overflow doing as such themselves. Again, I thought nothing of the lack of engagement.

A few days go by with the new page rolled out where things are mostly business-as-usual from my perspective. And then, last weekend, something really interesting happened.

The Blog Post

An employee at our company wrote a blog post titled “Discussing diversity terrifies me” on their personal blog. They have since taken the post down – a decision they made themselves. The post described this person’s feelings about our new page and how it made them feel uncomfortable in ways that they couldn’t fully explain. This person also explained how they felt terrified to discuss diversity with anyone, ever – even their best friends. This was because of prior experiences at prior companies where the discussion went poorly.

I came across the post on Saturday night at about 9pm. It did not call out me or the page as doing something wrong; it was a way for this person to express some thoughts that were very important to them, but that they otherwise felt they could not bring up.

I Felt Wronged

Upon reading it, I was really pissed off. I couldn’t believe that this person, given numerous opportunities to shape the page as part of the DIP, had remained silent during the project. I couldn’t believe that they didn’t come to me or anyone else at work, and instead took to talking about their issues on their blog, in public, which at the time I felt served to embarrass me in front of the company. After all, they were given tons of opportunities to talk about it internally, so why didn’t they? I felt slighted and wronged. I selfishly felt that this was all a personal attack on my work. I wasn’t happy.

The Company-Wide Revelation

On Monday afternoon I had a private conversation with the person who wrote the blog post. We had a really constructive chat about how the person felt, and ways to improve upon the new page and make it more sincere and reflective of our true values and current workplace diversity. It ended on a positive note. Later Monday evening, I sent out an anonymous survey to solicit broad feedback from folks on how to improve the page. The plan was to iterate to a better version ASAP. Satisfied with trying to improve the situation, I went to bed.

On Tuesday I found myself in a few conversations about our new page. The people engaging me were mostly straight white males (not unlike myself) who all said something similar: “talking about diversity scares me to death” and “it feels like one wrong word and I’m fired.” These conversations continued until about 1pm, when a forward-thinking co-worker realized that we all needed to get on the same page. They brought the diversity page controversy up in our company-wide chat room for literally anyone and everyone to discuss. Many people jumped in and what followed, for lack of better description, was quite an epic conversation. It involved a lot of people from a lot of departments – both people who were visibly diverse and those who were not – and even included 4 executives. The conversation rolled on for a few hours and culminated in a few important outcomes:

  • The person who wrote the blog post felt very uncomfortable talking about diversity at all, with anyone
  • Their blog post gave a voice to many others who felt the same way but were afraid to speak up
  • The diversity page was making people within Stack Overflow uncomfortable

As a result of the company-wide chat, the new diversity page was taken offline.

I Felt Even More Wronged

Conveniently, all of this discussion happened while I was at the doctor’s office for a check-up. As a result of the timing I didn’t get to participate at all. When I returned from the doctor and read the chat transcript, I became very, very upset and angry. I felt betrayed by the company and wronged by almost everybody who participated in the conversation. In hindsight, I think that I probably would have said some things that I’d now regret had I been around to participate in the chat. Ignorance is sometimes bliss.

I was boiling over. Many unfair, selfish, and angry thoughts crossed my mind as I read the chat transcript. I thought things like “f*** it, I’m never touching another diversity project ever again” and “how could these people do this to me?” and even, for a brief moment, “what am I doing working somewhere where I’m undermined and treated unfairly?”

I called it quits a few hours early on Tuesday and had a few drinks of the alcoholic nature. I was fuming, and ranting to my wife, and otherwise upset about how I had been so wronged by the people that I was trying to help. I took some ibuprofen (for the impending hangover and headache) and passed out, unsure of what Wednesday would bring.

Worth noting, I don’t recommend self-medicating with alcohol when you’re upset – it’s a bad strategy.

This Wasn’t About Me At All

I awoke Wednesday morning with a clear mind and new perspective on the events of the past few days. I realized some really important things:

  • Absolutely, literally, none of this was about me. I was being selfish and making it about how I felt, when in reality it was about how we all felt.
  • We had created a diversity page that did a poor job of accomplishing our goals on diversity.
  • Taking the page offline was the right thing to do, because it was making a lot of people in our company uncomfortable. If it had this effect internally, it surely had a similar effect externally. In this case, the page existing was perhaps worse than having no page at all.
  • The person who wrote the blog post was completely in the right, and arguably did the right thing. The alternative was that if they hadn’t spoken up on their blog, nobody may have. This would leave everyone silently feeling uncomfortable.
  • The person who wrote the blog post felt uncomfortable speaking up about diversity at work. They talked about it on their personal blog to keep it outside of the company. This was an important revelation as it showed me that we have a serious issue at our company: people feel as if they don’t always have the right to speak up about difficult subjects like diversity. One person described it as “a manager’s word being law and difficult to contest.”
  • Nobody had been malicious at all. We were all trying to do the right thing, assumed the best of intentions in each other, and were simply expressing our honest feelings on the topic. Feelings are always valid.

Diversity At Stack Overflow

Through all of this I realized some of why diversity is such a hard topic for people to discuss: no matter what position you are in, you probably feel like you’re not entitled to participate in the conversation. When nobody feels like they’re able to talk, silence soon becomes apathy.

On the topic of diversity issues, apathy rules all. It’s a safe and easy play to do nothing at all. Taking a stance means meeting resistance and having conversations where everyone feels invalidated. Unfortunately, doing nothing enables and furthers the issue.

One of the mistakes that I made was not considering the emotional response of the new diversity page that we created. How the page makes people feel is the only measure of success. The people in our company felt that the page was insincere and made them uncomfortable.

Here’s the truth: despite what the page said, we’re not great at diversity. We have about 40 engineering team members, and only 4 of them are women. At most, 8 or 9 total are of a visible minority. We certainly have a diverse team in the sense that we’re located all over the world, but that isn’t how everybody defines diversity, and maybe isn’t even the most important form of diversity since those geographically diverse people aren’t necessarily marginalized.

It’s really easy to feel as if your company sucks at diversity when any discussion is met with frustration and hurt feelings. However, I am really proud of the fact that at Stack Overflow we are able to have these conversations. We had a company-wide discussion on how the page made everybody feel, and even though that discussion got extremely heated and many people felt many strong emotions, not one person made it personal. There were 4 executives in the conversation and nobody quit or got fired.

I’m thankful that one person had the courage to write a blog post and speak up about their overarching fear of discussing diversity. What scares me as a manager is the idea that people might feel as if there’s no channel to talk about things that make them uncomfortable. If people don’t express their concerns, they suffer silently. It was the actions of one person that saved us all from a much worse outcome.

Ultimately, we made a company diversity page that’s like every other company’s diversity page, at a company that prides itself in not being like any other company. We’ve identified that people at Stack Overflow sometimes feel like they are unable to speak up on difficult topics – both inside and outside of the company – and that’s something that we need to work on.

What’s Next

As I said earlier, the easy and safe play is to do nothing. We could leave things in their current state of no longer having a diversity page, but it would also be the wrong thing to do.

What we must do now is continue the conversation. We need to talk honestly about diversity and discuss the feelings that we have around it. We need to channel those feelings into a better diversity page that accurately reflects our company and how we feel on the subject. We need to admit that diversity is hard, but that we’re working on it. Most importantly, we need to assume the best intentions of each other and make progress together in all of our diversity initiatives.

I hope that in reading this, you feel inspired to start or continue the conversation about diversity in your workplace. Like many companies, we have a long way to go. It’s challenging, but as a co-worker said, “the hardest conversations are often the ones most worth having.”