work management reviews 13 comments suggest edit

Who doesn’t love the smell of performance reviews in the morning? A smell welcomed by employees and managers alike with joy and delight. An efficient ritual that is fair and definitely motivates everyone to improve. A ritual that no one doubts is worth the investment of time and energy.

Yes, I’m kidding. No, I haven’t been hacked (I am and will always be haacked though).

Dilbert can provide a better introduction to performance reviews:

Dilbert on performance reviews

Yes, it’s a crutch to quote Dilbert on a post about management, but forgive me. On this topic, Dilbert is so spot on. I’ll only do it twice, I promise. Now back to the point…

Companies should abolish the charade of annual (or semiannual) performance reviews.

They are expensive, biased, and they don’t work. Yet, companies persist in the Sisyphean attempt. They take it as a given that the dread and anxiety they create serves a noble purpose. It’s like believing that constant face slaps will lead to stronger cheek muscles.

It’s bullshit. Constant face slaps lead to a sore face.

As you can see, I’m pretty tepid about this issue. But a lot of researchers and experts are not. In this post I quote a lot of them, because I don’t expect anyone to take my word for it.

Let’s start with Dr. William Edwards Deming.

Deming’s Argument

The annual appraisal of performance, or the so-called merit system. Of all the forces of destruction that have beset American industry, this one has dealt the most powerful blow. It destroys people, our most important asset.

This quote is from The Merit System: The Annual Appraisal: Destroyer of People as included in The Essential Deming.

It’s hard to overstate how important Deming was to the field of business management. He changed the very idea of how businesses approach quality and organizational efficiency. His ideas on continuous improvement and total quality helped Japan recover from World War II and become an automotive powerhouse.

His focus went beyond process. He taught companies to create a culture of quality.

He goes on to describe why reviews fail people (emphasis mine).

The merit rating nourishes short-term performance, annihilates long-term planning, builds fear, demolishes teamwork, [and] nourishes rivalry and politics. It leaves people bitter, crushed, bruised, battered, desolate, despondent, dejected, feeling inferior, some even depressed, unfit for work for weeks after receipt of rating, unable to comprehend why they are inferior.

Tell me how you really feel, Deming. Deming goes on to note what reviews really reward.

The merit rating rewards people that conform to the system. It does not reward attempts to improve the system. Don’t rock the boat.

In case it’s not clear that Deming had a strong distaste for annual performance reviews, he lists them third in his Seven Deadly Diseases of Management list.

Reviews are Wildly Inaccurate

Dilbert on reviews

Not only do people dislike reviews, they are also unreliable. In the article, The Corporate Kabuki of performance reviews, the author notes,

They’re wildly inaccurate, for one: CEB’s research finds that two-thirds of employees who receive the highest scores in a typical performance management system are not actually the organization’s highest performers. Go figure.

The Push Against Performance Reviews adds more weight to this assertion.

Studies suggest that more than half of a given performance rating has to do with the traits of the person conducting the evaluation, not of the person being rated.

The article notes one source of inaccuracy,

Managers have incentives to inflate appraisals; even accurate feedback can feel biased and unfair, making people less motivated and hurting relationships between supervisors and subordinates; and organizations don’t do a good job of rewarding good evaluators and sanctioning bad ones. “As a result, annual appraisals end up as a source of anxiety and annoyance rather than a source of useful information,” Murphy wrote.

Women especially lose out

Performance reviews should be fair, but in practice they are fertile ground for bias.

The author of Valley Boys notes,

In a recent study of almost two hundred and fifty performance reviews, the tech entrepreneur Kieran Snyder found that three-quarters of the women were criticized for their personalities—with words like “abrasive”—while only two of the men were.

In How Gender Bias Corrupts Performance Reviews, and What to Do About It, Paola Cecchi-Dimeglio writes,

One of my findings, using content analysis of individual annual performance reviews, shows that women were 1.4 times more likely to receive critical subjective feedback (as opposed to either positive feedback or critical objective feedback).

Reviewers describe high-achieving men and women in different terms for the same behavior! In a study of 248 reviews conducted by Kieran Snyder.

Chart showing women are criticized more than men

Note that the gender of the manager did not impact these results. This is a clear example of implicit bias.

As if the odds weren’t stacked enough against women, it turns out that Men Get Credit for Voicing Ideas, but Not Problems. Women Don’t Get Credit for Either (emphasis mine).

Across both studies—using both field and experimental research designs and very different populations of respondents—we saw the same pattern of results: Men who spoke up with ideas were seen as having higher status and were more likely to emerge as leaders. Women did not receive any benefits in status or leader emergence from speaking up, regardless of whether they did so promotively or prohibitively. Neither men nor women who spoke up about problems suffered a loss of status or had a lower likelihood of emerging as a leader (though they weren’t helped by speaking up, either). Also of note, men and women both ascribed more status and leadership emergence to men who spoke up promotively, compared with women who did so.

They don’t even work

Do we forgive these flaws because reviews improve performance?

Not so, suggests the evidence. Performance appraisal’s fail at their primary goal, to improve performance.

Again, citing The Push Against Performance Reviews,

An earlier study, published in 1996, found that while job appraisals generally improved people’s performance, they had a negative impact on performance more than a third of the time, notably in cases where the assessments focused on individuals rather than on their performance at particular tasks.

More than a third of the time, they have a negative impact. But 2 out of 3 ain’t bad, right? Well, not so fast.

In Why Incentive Plans Cannot Work, we learn that any gains tend to be temporary.

Do rewards work? The answer depends on what we mean by “work.” Research suggests that, by and large, rewards succeed at securing one thing only: temporary compliance. When it comes to producing lasting change in attitudes and behavior, however, rewards, like punishment, are strikingly ineffective. Once the rewards run out, people revert to their old behaviors.

They do not create an enduring commitment to any value or action. Rather, incentives merely—and temporarily—change what we do.

Lazlo Bock, former head of people operations at Google backs this up in Work Rules!,

Intrinsic motivation is the key to growth, but conventional performance management systems destroy that motivation.

This aligns well with Dan Pink’s own research into what really motivates us.

Negative feedback has a negative effect

Rather than improve performance, reviews often have the opposite effect. Negative feedback demoralizes those with bad ratings.

The article Why Performance Reviews Don’t Improve Performance notes (emphasis mine),

Research by psychologists at Kansas State University, Eastern Kentucky University and Texas A&M University examined how people respond to negative feedback they receive in performance reviews. Conventional wisdom is that people who are really motivated to improve their performance would respond well to getting critical feedback in a performance review. The research demonstrated this wisdom is wrong.

In an article published in The Psychological Bulletin, psychologists A. Kluger and A. Denisi report completion of a meta-analysis of 607 studies of performance evaluations and concluded that at least 30 percent of the performance reviews ended up in decreased employee performance.

The Case Against Performance Reviews offers an explanation for this effect,

“We’d rather be ruined by praise than saved by criticism,” wrote Norman Vincent Peale, the author of the 1962 book The Power of Positive Thinking. It sounds like a glib aphorism, but that’s actually pretty close to the research consensus. Criticism stinks.

But what about workers who readily say they want to get better at their jobs—maybe they’d appreciate a critical nudge? Yeah, right. After administering negative feedback to both groups, the researchers found that the first group hated the feedback round, and the second group—employees with the strongest “learning-goal orientation”—was nearly as unhappy with the criticism.

The New Yorker - The Push Against Performance Reviews supports this assertion,

In 2013, psychologists at Kansas State University and other institutions studied how different kinds of people react to negative feedback. They invited more than two hundred employees of a university to rate how they felt about a recent performance evaluation, and asked questions meant to categorize the employees based on how they approach personal goals. The researchers figured that people who seek out learning opportunities would react better than those who avoid situations in which they might fail. This was true—but even the avid learners disliked performance reviews, they just disliked them less.

They focus on the wrong thing.

What does help improve performance? As mentioned before, Dan Pink’s research suggests intrinsic motivation. He notes three elements that increase intrinsic motivation: autonomy, mastery, and purpose.

Laszlo Bock notes that having clear goals also helps improve performance,

On the topic of goals, the academic research agrees with your intuition: Having goals improves performance. Intrinsic motivation is the key to growth, but conventional performance management systems destroy that motivation.

Performance reviews do not support any of these goals. They are also too focused on the individual and can harm teams.

In Incentive Pay Considered Harmful Joes Spolksy warns,

If you’re in this position, the only way to prevent teamicide is to simply give everyone on your team a gushing review. But if you do have any choice in the matter, I’d recommend that you run fleeing from any kind of performance review, incentive bonus, or stupid corporate employee-of-the-month program.

What Google Learned From Its Quest to Build the Perfect Team describes Project Aristotle, research that Google conducted to find out what actually leads to high performing teams. The results were very interesting.

What interested the researchers most, however, was that teams that did well on one assignment usually did well on all the others. Conversely, teams that failed at one thing seemed to fail at everything. The researchers eventually concluded that what distinguished the ‘‘good’’ teams from the dysfunctional groups was how teammates treated one another. The right norms, in other words, could raise a group’s collective intelligence, whereas the wrong norms could hobble a team, even if, individually, all the members were exceptionally bright.

Performance reviews focus too much on individual ability. A collection of high achieving individuals does not ensure a high output team. Rather, psychological safety factors most in high output teams. The goal of any feedback process should be to create high performance teams. Instead, they produce individual vanity report cards.

They’re largely ignored

Employees ignore reviews for two main reasons:

  1. They put people on the defensive.
  2. Employers tie reviews to compensation.

The Corporate Kabuki of performance reviews highlights the first case,

Studies have shown over and over again, Jenkins says, that “people simply think they perform better than other people. Unless you rate someone in the highest category, the conversation shifts away from feedback and development to justification.

“Ratings detract from the conversation,” says Stockdale. “If an employee is sitting there waiting for the number to drop, they’re not engaged in the conversation, at best. At worst, it can actually make them angry and disaffected for a period of up to a year.”

Most companies tie reviews to compensation and discuss both in the same conversation. This is a terrible mistake. Lazlo Bock explains,

At Google “Annual reviews happen in November, and pay discussions happen a month later.” “As Prasad Setty explains, “Traditional performance management systems make a big mistake. They combine two things that should be completely separate: performance evaluation and people development. Evaluation is necessary to distribute finite resources, like salary increases or bonus dollars. Development is just as necessary so people grow and improve.”

I have a bone to pick with that last part about “Evaluation is necessary to distribute finite resources,” but that’ll have to come in a follow-up blog post. The main point stands though.

Netflix also separates performance conversations from compensation conversations.

So why do continue to do them?

If performance reviews are so bad, why do they persist? Well for one thing, they’ve been around a long time.

The Case Against Performance Reviews notes,

one of the earliest examples of formal appraisal comes from China’s Wei Dynasty, around 230 AD, when an Imperial Rater invented a nine-grade system to evaluate members of the official family.

In his book, Out of the Crisis, Deming writes that he understands why companies are so bought into performance reviews…

The idea of a merit rating is alluring. The sound of the words captivates the imagination: pay for what you get; get what you pay for; motivate people to do their best, for their own good. The effect is exactly the opposite of what the words promise.

There’s also a lack of imagination for what to do instead.

As Laszlo Bock, former head of People Ops for Google notes in WORK RULES!,

The major problem with performance management systems today is that they have become substitutes for the vital act of actually managing people.

There’s also survivorship bias to contend with. As the Atlantic article notes,

Perhaps one specific group appreciates criticism: The workers least likely to be criticized.

It stands to reason that those who benefit most from reviews get the lion share of promotions. They tend to become in charge. It creates a natural incentive to perpetuate the system.

That last point may be the strongest reason they persist.

What should we do instead?

Give up and go live in a monastery in the mountains.

That might be a bit drastic. The answer to this question could be its own blog post. And someday I might try and tackle the question in more detail.

I don’t have all the answers, but I can I have a few ideas to share for now. The first is a suggestion by Seth Godin from Your soft skills inventory,

The annual review is a waste. It’s not particularly useful for employee or boss, it’s stressful and it doesn’t happen often enough to make much of an impact.

If you choose to, though, you can do your own review. Weekly or monthly, you can sit down with yourself (or, more powerfully, with a small circle of peers) and review how you’re shifting your posture to make more of an impact.

The Push Against Performance Reviews also advocates for informal check-ins,

Instead, Morris implemented a more informal “check-in” process that takes place throughout the year, with employees receiving feedback on what they’re working on at any given moment.

Netflix does this with informal 360-degree reviews,

When we stopped doing formal performance reviews, we instituted informal 360-degree reviews. We kept them fairly simple: People were asked to identify things that colleagues should stop, start, or continue. In the beginning we used an anonymous software system, but over time we shifted to signed feedback, and many teams held their 360s face-to-face.

The Case Against Performance Reviews suggest more diversity in the review process,

…involve a diverse group of people in the evaluation process to water down individual bias, as Jeffrey Pfeffer wrote in Bloomberg Businessweek. One-on-one evaluations can feel personal. Groups critiquing groups isn’t just more constructive; but also, it’s a realistic way to evaluate systems and workflow, which are often as important as individual merit in larger organizations.

My advice is to emphasize managers as trusted mentors and coaches, not as report card graders. Their focus should be to improve people and grow teams. They should provide continuous feedback with occasional informal check-ins on progress towards goals

At the very least, separate pay increases from performance evaluation because. Incentive pay does not work. Pay according to the market instead.

Experiment with approaches and follow up on results. It’s important to iterate on whatever approach you choose. As always, keep the end goal in mind and make sure the cost of whatever you implement is worth the benefit.

RESOURCES

jekyll comments blogging 21 comments suggest edit

If you are a long time reader of my blog, you might notice something different starting today. No, the content hasn’t gotten any better. What’s new is the comment system.

The Graffiti Tunnel 38 by Greger Ravik - CC BY 2.0

A long time ago, I migrated comments on my blog to Disqus using this technique to preserve the existing comments. Overall, I’ve been pretty happy with Disqus.

However, they’ve made some recent changes that lead me to consider other options. For one thing, they started adding ads to the free version of Disqus. That doesn’t bother me too much, they are a business after all and they need to make money. I’m just not a fan of the type of clickbait ads warning you about what information the internet has about you, better click here and search your name to find out! No thank you.

It’s possible to pay for an ad-free version of Disqus, but if I’m going to pay, I might as well consider my options. Not only that, but I’ve long had a nagging worry about storing comments outside of my blog. Disqus has a nice export feature, but will they always?

A Jekyll-based solution

That’s when Damien Guard mentioned to me that he’s working on a Jekyll-based comment system.

But wait, you say. Jekyll is a static-site generator. How can you build a comment system? So astute. What Damien realized is we can use data files in Jekyll to store comments and some liquid templates to render them. That all can be static.

The dynamic part is the bit of code that’ll receive a comment form submission and create the appropriate data file in your Jekyll repository. Fortunately, that’s pretty easy using something like an Azure Function or AWS Lambda combined with the GitHub API.

This is what Damien built. He wrote an Azure function that calls the GitHub API using Octokit.net (Install-Package octokit when using NuGet) to create a Pull Request that contains a data file with the content info rendered as Yaml.

Making it Haacked.com

I wrote an importer that takes the Disqus export file and creates all the Jekyll data files. In my case, that ended up creating 25,381 files since there are that many comments on my blog. Wow!

You can see the work I did on haacked.com to implement Damien’s comment system for my blog in this Pull Request. It’s hard to look at the changes because there are so many file changes, but this PR contains four commits:

  1. The changes to my Jekyll templates.
  2. Import all of the comments.
  3. This blog post announcing the change.
  4. A commit where I update the post to link to the third commit. Obviously I can’t link to this fourth commit without creating a fifth commit unless I can break SHA1 and guess the commit SHA of the blog post before I commit.

The first commit is the most interesting for anyone looking to implement this system for their own blog.

The other part you’ll need is to set up an Azure Function. You can pretty much fork my repository and make that the source for your Azure Function. In your Jekyll site’s _config.yml make sure the comments.receiver setting points to your function not mine.

Comment Spam

One thing we lose with this approach is a robust comment spam filter. There are two things that mitigate this - first, when you click to send a comment, the button asks you to click again to confirm sending the comment. This is a poor person’s implementation of spam filtering, but seems to get the job done.

The other part of it is by the very design, all comments are moderated because I have to merge the Pull Request created any time someone submits a comment. However, once I have robust comment spam filters implemented in the Azure function, I could decide to auto-merge those pull requests or even bypass the creation of a pull request. That would simply require that I change the Azure function.

Feedback

As you can see by all the effort I’ve put in over the years to preserve the comments you’ve made on my blog, I value your input. Well, most of it. So next time you leave a comment, consider how important they are to me. Let me know what you think about this new comment system in the comments. And in the off chance you can’t leave a comment because of a bug, open an issue on GitHub.

github csharp dotnet scientist 0 comments suggest edit

I have some big news! Scientist.NET 2.0 is now available on NuGet.

Install-Package Scientist

This release includes two main features:

  • A fire and forget result publisher
  • Better support for IoC/DI scenarios.

Fire and Forget

Result publishers should be very fast in order to avoid delaying code under experimentation. However, if a result publisher needs to talk to a service, it might have a noticeable impact on code execution times. With this release, a result publisher (class that implements IResultPublisher) can be wrapped in a FireAndForgetResultPublisher so that result publishing avoids any delays in running experiments and is delegated to another thread.

Scientist.ResultPublisher = new FireAndForgetResultPublisher(new MyResultPublisher());

Better support for IoC/DI scenarios

Scientist is primarily for short-lived experiments such as when you are refactoring code and need to test the old code and the new code together. With that in mind, it is designed to require minimal configuration. You can add an experiment in without the need to configure a dependency injection container. This is why it’s designed as a static API.

While an individual experiment may be short lived, it’s possible that you always have an experiment running somewhere in your code. In that case, you may want to use dependency injection to configure and acquire an instance of Scientist. In this PR, Martin Costello added support for these scenarios.

The old static approach should still work if you’re just playing around with Scientist, but if you need this DI/IoC approach, it’s now possible.

Thanks!

Once again, thank you to all those who have contributed to Scientist! Without you, this release would not be possible.

github VisualStudio pull-request 5 comments suggest edit

The Information Industry Association adopted the motto “Putting Information at Your Fingertips” way back in the hazy days of the 1970s. However it was during a 1990 Comdex keynote (you can watch a scratchy VHS recording of it on YouTube), when a relatively young Bill Gates articulated a vision to bring that idea to reality.

Look at him, so young and hopeful.

In the intervening time, that vision has mostly come to fruition…for VIM users. For the rest of us, it’s more like information at the end of your mouse clicks. But close enough.

Visual Studio is a salient embodiment of this vision. It contains a rich set of features along with a third-party extension ecosystem such that nearly every task a developer needs to accomplish can be done in the IDE. Tools like IntelliSense provide helpful context while coding.

This creates an environment where developers who use Visual Studio love to stay in Visual Studio. So much so that their friends start to worry about them, like that friend who just went through a rough break up and hasn’t left their apartment in weeks. I say that out of love as one who has spent many fond hours churning out code assisted by the helpful embrace of IntelliSense.

GitHub For Visual Studio

This week, the Editor Tools team at GitHub (the team who brought you the GitHub Extension for Visual Studio) released a new version that contributes to this vision by bringing Pull Requests closer to your fingertips!

The three main features included in this release are:

Reviewing a PR with submodule changes

Besides rebasing and merge conflicts, submodules may be one of those features that cause the most angst in Git. This feature seeks to reduce that angst. When switching to a PR branch, it brings any submodule changes to the developer’s attention. There’s even a handy little button to update them for you!

Submodule status and update  button

Previously, there was no indication that submodules had changed apart from random build failures and checking Git status on the command line. From there, you would have to sync and update submodules from the command line. This unnecessarily forced developers outside of Visual Studio when doing a GitHub related action (opening a PR).

Show current PR on status bar

Prior to this release, you would have to go to the PR list and take an educated guess based on the current branch name to find the active PR:

Which PR is active?

Oh it's this one!

With this release, you can see which PR you are on directly from the status bar, and navigate to its details by clicking the PR number!

PR at your fingertips

Enable navigation from diff view to editor

Finally, this update enables developers to quickly switch from a diff view back into the editor.

When viewing a diff view in Visual Studio, it is a jarring experience for a developer to be within their IDE and not be able to edit (since you can’t edit a diff view). This releaseadds a simple way for developers reviewing a diff to jump right back into coding. All you have to do is press Enter in the file! (Video here for a better view of what this animated gif shows):

Switching from diff to code

Shout outs

A special thanks to Jamie Cansdale (you may know him from such hits as TestDriven.net) for working on these three main features and getting them out to you!

Thanks to Sarah Guthals, the relatively new manager of the Editor Tools team for doing the real work in writing this post. And to

And to the rest of the Editor Tools team for making this release possible. It takes a village! Be sure to follow them on Twitter!

Busy in 2017

And in case you haven’t paid close attention last year, here are some cool features we shipped in 2017.

azure azure-functions serverless github sentiment ml ai 4 comments suggest edit

Tragedy and Comedy - Scarbrough Hotel, Bishopgate, Leeds - by Tim Green - CC BY 2.0

Developers are real passionate about their semi-colons; or lack thereof. Comment threads on GitHub can get a bit…testy…on this topic. What’s a beleaguered1 repository maintainer to do when an issue comment thread gets out of hand?

GitHub provides community tools maintainers can use to define community standards for their projects. For example, it’s easy to add a code of conduct to a repository. It’s also possible report offensive comments directly to GitHub. However, a code of conduct is only a set of words on a page. It’s only effective if you enforce it. And face it, enforcing it can be very time consuming.

What if a bot could help? Now I’m not so naïve to think you can take the very human problem of enforcing community standards and just sprinkle a bit of Machine Learning on it and the problem goes away. Clippy taught me that.

But perhaps the combination of machine learning and human judgement could make the problem more tractable.

The Idea

This was the idea I had in mind when I decided to explore some new technologies. I learn best by building something so I set out to add sentiment analysis to GitHub issue comments.

Sentiment analysis (also known as opinion mining) is the use of computers to analyze text to try and determine whether a piece of writing is positive, negative, or neutral. It relies on multiple fields related to AI such as natural language processing, computational linguistics, machine learning, and wishful thinking.

To make this work I need to do four things:

  1. Drink some whiskey
  2. Listen to and respond to GitHub issue comments.
  3. Analyze the sentiment of the comment.
  4. Update the comment with a note about the sentiment.

The idea is this: when an issue receives a negative issue comment, I’m going to have my “SentimentBot” update the comment with a note to keep things positive.

DISCLAIMER: I want to be very clear that I chose this behavior as a proof of concept. I don’t think it’d be a good idea on a real OSS project to have a bot automatically respond to negative sentiment. If I were doing this for real, I’d probably have it privately flag comments in some manner for follow-up. You’ll probably see me make this clarification again because people have short memories.

The GitHub Listener

Webhooks are a powerful mechanism to extend GitHub. There are three key steps to set up a webhook.

  1. Set up an application that can receive an HTTP POST from github.com.
  2. Register the application as a webhook on a repository.
  3. Configure the repository events the webhook listens to in the repository settings page.

That first step is a bit of a pain. I need to write an entire application and host it at a publicly available URL? Ugh! So 2015!

All I really want to do is write a tiny bit of code to respond to a Webhook call. I don’t care how its hosted.

Serverless architecture to the rescue! The “Serverless” nomenclature has been the source of a lot of snide comments and jokes. The name may lead one to believe we chucked the server and are hosting our code on gumption and hope. But it’s not like that. Of course there’s a server! You just don’t have to worry about it. You just write some code and the Serverless service handles hosting, scaling, etc. all for you.

Azure Functions and AWS Lambda are the two most well known examples of Serverless services. I decided to play around with Azure Functions because they have specific support for GitHub Webhooks. GitHub Webhooks and Azure Functions go together like Bitters and Bourbon. Mmmm, I’ll be right back.

Follow these instructions to set up an Azure Function inside of the Azure Portal that responds to a GitHub webhook in no time. The result is a method with a signature like this.

public static async Task<object> Run(
  HttpRequestMessage req,
  TraceWriter log)
{
  string jsonContent = await req.Content.ReadAsStringAsync();
  dynamic data = JsonConvert.DeserializeObject(jsonContent);

  // Your code goes here

  return req.CreateResponse(HttpStatusCode.OK, new {
    body = "Your response"
});
}

The shape of the data is determined by the event type that the webhook subscribes to. For example, if you subscribe to issue comments like I did, the payload represented by data is the IssueCommentEvent.

In my example, we use a dynamic type for ease and convenience (but at the risk of correctness). However, you can deserialize the response into a strongly typed class. The Octokit.net library provides such classes. For example, I could deserialize the request body to an instance of IssueCommentPayload.

Analyzing Sentiment

The next step is to write code to analyze sentiment. But how do I do that? A naïve approach would search for my favorite colorful words in the text. A more sophisticated approach is to use something like Microsoft’s Cognitive Services. They have a Text Analytics API you can use for analyzing sentiment.

And of course, there’s a NuGet package for that.

Install-Package Microsoft.Azure.CognitiveServices.Language

I installed the package, wrote a bit of code, and had the sentiment analysis working in short order. The API returns a score between 0 and 1. Scores close to 0 are negative. Close to 1 are positive.

static async Task<double?> AnalyzeSentiment(string comment)
{
  ITextAnalyticsAPI client = new TextAnalyticsAPI();
  client.AzureRegion = AzureRegions.Westcentralus;
  client.SubscriptionKey = "YOUR_SUBSCRIPTION_KEY";

  return (await client.SentimentAsync(
    new MultiLanguageBatchInput(
        new List<MultiLanguageInput>()
        {
          new MultiLanguageInput("en", "0", comment),
        })
  )).Documents.First().Score;
}

Updating the comment

Now that all the sentiments are determined, let’s do something with that information. For the sake of this proof of concept, I will update overly negative comments with a little reminder to keep it positive. After all, we know how much humans enjoy being chided by a software robot. Again, I want to reiterate that I wouldn’t use this for a real repository. I’d probably just flag the comment for a human to follow-up.

I will also update positive comments with a nice thank you for keeping it positive. Gotta reward the nice people from time to time.

In order to update the comment, I’ll use Octokit.net! Once again, NuGet to the rescue.

Install-Package octokit

The code is pretty straightforward. We use Octokit to post an edit to a comment using the issue comment API.

static async Task UpdateComment(
  long repositoryId,
  int commentId,
  string existingCommentBody,
  string sentimentMessage)
{
  var client = new GitHubClient(
    new ProductHeaderValue("haack-test-bot", "0.1.0"));
  var personalAccessToken = "SECRET PERSONAL ACCESS TOKEN";
  client.Credentials = new Credentials(personalAccessToken);

  await client.Issue.Comment.Update(
    repositoryId,
    commentId,
    $"{existingCommentBody}\n\n_Sentiment Bot Says: {sentimentMessage}_");
}

Deployment

It’s possible to build an Azure Function entirely in the Azure Portal via a web browser. But then you’re pasting code into a text box. I like to write code with my favorite editor. Fortunately, Azure Functions supports continuous deployment integration with GitHub. It’s quick and easy to set up.

I set up my repo as my deployment source. Every time I merge a change into the master branch, my changes are deployed.

Try it!

The source code is available in my haacked-demos/azure-sentiment-analysis repository

If you want to try out the end result, I created a test issue in the repository. I know you’re testing out a sentiment bot, but you can still be negative and civil to each other. Please abide by the code of conduct.

Also, I don’t want to pay a lot of money for this demo, so it might fail in the future if my trial of the text analysis service runs out.

Future Ideas

My goal in this post is to show you how easy it is to build a GitHub Webhook using Azure Functions. I haven’t tried it with AWS Lambda. I hope it’s just as easy. If you try it, let me know how it goes!

The possibilities here are legion. With this approach, you can build all sorts of extensions that make GitHub fit into your workflows. For example, you may want to flag first time issue commenters. Or you may want to run static analysis on PRs. All of that is easy to build!

But before you get too wild with this, note that there are a lot of GitHub integrations out there that might already do what you need. For example, the Probot project has a showcase of interesting apps that range from managing stale issues to enforcing GPG signatures on pull requests. There’s even a sentiment bot in there!

Probot apps are NodeJS apps that can respond to webhooks. I believe they require you host an application, but I haven’t tried to see if they’re easy to run in a Serverless environment yet. That could be fun to try.

Resources

1 I admit, I have to look up the spelling of this word every time, but it’s so perfect in this context.

personal career management 7 comments suggest edit

In The Case Against Pay for Performance, I argued against increasing pay based on performance reviews. Checkmate. Case closed. Or so I thought. Like many bloggers, I suffer from delusions of grandeur that millions ponder every word I write, are enlightened by insight, and then compelled to action.

Alas, it’s not to be. Instead, I find that belief in the power of rewards to spur higher performance persists despite the ample evidence to the contrary.

I suspect that one reason people continue to believe that pay for performance works is rooted in Theory X thinking.

[it] reflects an underlying belief that management must counteract an inherent human tendency to avoid work”

Offers of bonuses and raises are one lever to do that.

Another reason is that they seem to be effective, temporarily. As Alfie Kohn notes in Why Incentive Plans Cannot Work

Rewards buy temporary compliance, so it looks like the problems are solved. It’s harder to spot the harm they cause over the long term.

And yet another potential reason they persist is perhaps they are propagated (unconsciously or overtly) by those who benefit most from them. We know that racial and gender wage gaps persist in the U.S.. We also know that performance appraisals suffer from bias. This leads to a set of conditions where at least certain groups benefit from the status quo at the expense of others.

Many folks counter that they don’t work because they’re simply implemented improperly. I contend that they cannot work. Alfie Kohn backs me up (emphasis mine)…

According to numerous studies in laboratories, workplaces, classrooms, and other settings, rewards typically undermine the very processes they are intended to enhance. The findings suggest that the failure of any given incentive program is due less to a glitch in that program than to the inadequacy of the psychological assumptions that ground all such plans.

Why it doesn’t work

First, we need to differentiate “works” with “has an effect.” Certainly rewards have an effect.

As the Kohn article notes,

Do rewards work? The answer depends on what we mean by “work.” Research suggests that, by and large, rewards succeed at securing one thing only: temporary compliance. When it comes to producing lasting change in attitudes and behavior, however, rewards, like punishment, are strikingly ineffective.

Not only that, rewards often have an outcome that seems positive but is overall a negative. An analogy from the world of sports might make this point clear.

Image of Leo Messi by Luis Salas via Wikimedia Commons cc-by-2.0

Lionel Messi is the best soccer player in the world today, if not all time (I know I’m inviting argument here, feel free to write your rebuttal on your own blog, but for now, bear with me). He is the leading scorer in La Liga (the top Spanish soccer league where he plays for FC Barcelona) with 17 goals this season so far. In fact, because I’ve sat upon this draft, I’ve had to change this figure already. The player in second place is far behind with 13 and happens to be his teammate.

Suppose Barcelona offers him $10 Million for every goal he scores. That would certainly have an effect. He would score more goals. Success! Right?

Not so fast Usain Bolt. In order for Lionel to score more goals, he’d need to take more chances. And this means taking more ill advised shots when he should have passed to a teammate. The incentive would lead to more goals but less assists. And Messi is currently in second place in La Liga in assists (he trails the leader by one). That’s how good he is. In this example, a reward for goals would have a negative overall effect on his team’s outcomes.

This is a classic case of an unintended consequence (aka be careful what you wish for).

Perhaps we can fix the rewards program. Imagine if his team changes the incentive to $10 Million per game his team wins. Would his team’s performance increase? Likely not! After all, he and his team are already doing everything in their power to win every game. Offering more pay won’t somehow magically make the team better.

Freakonomics seems to bear this out in a study on another professional sport, American Football…

That’s what Brian Burke of Advanced NFL Stats did for us, analyzing all multi-million-dollar contracts for NFL running backs since the 2000 season, a sample of 28 contracts. He found that in the year after signing their big deals, these running backs averaged .3 yards less per carry. That’s a pretty startling drop.

Chances are, these players already give their best effort. They play as well as possible. There’s no way to eke out more performance by showering them with more money.

The Kohn article lists other unexpected outcomes of rewards (really, just read the whole thing)…

  1. “Pay is not a motivator.”
  2. Rewards punish.
  3. Rewards rupture relationships.
  4. Rewards ignore reasons.
  5. Rewards discourage risk-taking.
  6. Rewards undermine interest.

Bringing it back to the tech industry

Ok, this won’t be a surprise, but most programmers are not elite athletes. What’s this got to do with us?

In practice, we’re not all that different. We have a unique skill that is very valuable. We try and make the most of our skill day in and day out at work. When we solve a problem, we think our hardest. It’s really hard to half-ass problem solving. For the most part, we’re motivated by intrinsic incentives such as purpose, mastery, and autonomy.

Waving more money in front of me won’t help me solve a problem or code up a solution any better. It won’t increase my performance.

At best, more money might coerce more hours out of a person. There might be a temporary increase in output. But that’s not a sustainable approach. The research is clear that long hours backfire for people and companies. This is such a Theory X manager move.

Instead, when you consider employees as intrinsically motivated to do their best work, you realize the way to improve their performance is through feedback and providing opportunities to learn and grow. In other words, help them work smarter, not harder.

Paying The Best

I anticipate some will point out that Messi is one of the highest paid players in La Liga. So isn’t that a form of incentive pay? Doesn’t it show that incentive pay does work?

Consider this, the incentives Messi earns today are available to all other players in the league. All they have to do is perform at the level he does day in and day out. Then, they’d receive a lot more pay. So why don’t they do so? Are they not as motivated as much as he is?

His team, Barcelona, is not paying him for performance. They’re paying him for his value. This is an important distinction. Because he performs as well as he does, he brings in a lot of value to Barcelona.

Not only that, many other teams are willing to pay a lot of money to have him join their team instead. So Barcelona has to pay him something close to his market value. This high pay isn’t to incentivize him to perform well, but to incentivize him to stay at Barcelona. The same is true for any creative employee. Any system of bonuses and merit increases are doomed to fail if they fall too far behind the pay the employee could get elsewhere, all other factors being equal.

And yet, despite all that, Messi still could make significantly more at another team. This makes it clear that pay isn’t the only motivation for him to continue to play at Barcelona.

Resources

personal career 4 comments suggest edit

There was once a time I regretted not attending a school with a more rigorous engineering program. I would tell myself, I should have gone to an institution like Stanford which has a strong CS program and ties to the bay area tech scene. I’d be further ahead in my career hobnobbing with VCs showering me with champagne and hundred dollar bills.

HAHA! YES! BUSINESS!

To use the technical term, I was a fool.

When I look back at 2017, I’m particularly grateful for the strong liberal arts education I received at Occidental College, affectionately known as Oxy. Hey, if it was good enough for Obama, it’s good enough for me (Ok, Obama did transfer out, but work with me here.).

2017 shows us the impact of companies run by engineers who perhaps don’t have a strong basis in the lessons of history, sociology, and psychology - whether it be the utter Travisty of Uber’s year, Facebook’s tone deafness, or Twitter’s continued love affair with white supremacy.

This education doesn’t mean I’m somehow immune to these failing. It just provides me a lens to use when I question my own actions.

What gives me hope is the growing interest in these topics. More people realize that to build successful teams and companies, you can’t just focus on business strategy and engineering.

In 2017, I hosted a track at QCon London with the title “Softskills - Essential skills for developers”. I’m quick to note that these are actually the hard skills.

This was the most successful track I’ve hosted. One of the talks by Alex Qin made QCon’s top five presentations of the year. Another talk by Meri Williams was the highest rated of the conference with a perfect score!

It’s clear to me that there’s a strong need and demand for the lessons these wonderful speakers continue to share.

As you start off 2018 with a bright eyed bushy tailed sense of hope, it’s fine to be excited about learning new technology. Everyone’s talking about κυβερνήτης. Why is everyone interested in greek helmsmen all of a sudden? Find out!

At the same time, don’t forget to focus on the human aspect of our work. Focus on empathy, communication, and inclusion. Consider your own unconscious biases and how they seep into the product of your work. Think about the social consequences of your work.

Let’s make 2018 the year we’re more conscious of the impact of our work on others. Happy New Year!

personal fitness exercise lifting 4 comments suggest edit

Not to stereotype tech folks, but, I’ll do it anyways. Most of us could stand to get in better physical shape. I know, that’s about as surprising as a cryptocurrency crash.

In particular, I highly recommend a weight training program. If you’re in the Bellevue, WA area, I have just the gym for you, Impact Strength and Performance.

But first, let me make the case by sharing my experiences for the past two years. As you can see from the photo, I’ve gotten quite swole (note: costume muscles will NOT help you lift more weights).

typical day at the gym

Ain’t Nobody Got Time for That

You’re a high achiever. You’re busy hustling to make a dent in the world. And the tiny morsels of time left over after work go to your family. I get it.

For me, it wasn’t just an issue of not having time. It was really hard to simply overcome inertia. This is where the motivational words of the leading philosopher of our time, Shia LeBeouf, really resonate - Just do it!

In my case, my wife signed us up for a painfully early fitness class (it really helps to have a partner!) two years ago. Rather than hem and haw, we just forced ourselves to show up. That’s often the hardest part. Get out of bed, and go. Once you’re there, it gets better.

Over time, it became a habit. That’s your goal really. Turn it from a chore to a habit.

I realized that working out wasn’t just for my own benefit, it’s for my family. I want to model healthy behavior to my kids so they too will be healthy. But more than that, I asked myself why am I working so hard in the first place? What benefit is all the money in the world if I’m unhealthy and weak? If I’m not strong enough to play with my kids or, down the road, my future grandkids? This is why I make time for the gym at the cost of a few less emails answered for work.

If you’re not convinced, here are 13 more reasons to start lifting weights.

It’s therapeutic

My last post was a bit heavy. I wrote about the challenges with mental health my family has been dealing with. At the end of the post, I noted,

And if you’re one who supports people with mental illness, you need support too.

Support can come in many forms. For me this summer, it came in the form of lifting. As I supported my family, I tended to my own mental and physical well being by increasing how often I went to the gym. I started to go every day of the week except Sunday (when it’s closed).

When I returned to work, I had to cut back a bit, though I’m trying hard to organize my schedule so I can get back to every day.

The progress I made in that time wasn’t just physical. My mental well being improved a lot too.

Getting results

Having a clear objective for working out and setting specific goals towards that objective is an important part of any fitness program. It provides focus and motivation.

At the beginning of the year, I set three specific and measurable fitness goals for myself to accomplish by the end of the year.

  1. Do a push-up with my son on my back.
  2. Do an unassisted pull-up.
  3. Touch my toes without bending my knees.

I’m happy to report that I accomplished two out of three of my goals. The first one was particularly challenging because my son is 10 and he’s growing fast. I didn’t anticipate how much heavier he’d be at the end of the year.

The goal I didn’t accomplish is touching my toes. I’m about as flexible as a gymnast in a full-body cast.

Tracking results

Impact also has an InBody scanning machine so I can track my quantitative progress. It’s important to not put too much stock in any individual measurement. Especially the ones you don’t like. It’s more important to look at the overall trend.

You can see there’s one measurement I’m skeptical of in the screenshot below. I’m pretty sure I took that one at night rather than in the morning like all the others.

Inbody

Perhaps for the first time in my life, I’m seeing steady gains.

But I’m not into that BRO culture.

When looking for a gym, it’s important to find one that you philosophically aligns with. For example, a lot of gyms I’ve been to feel “aggressive” for a lack of better word. I tried Crossfit and have nothing against it, but I remember seeing shirts with slogans like:

You can rest when you’re dead

And

If I pass out, please note my time

I know, they’re meant to be funny, but they do reflect in some tiny way the culture around Crossfit. It’s great for a lot of people, just not me.

Contrast that to Impact’s motto on one of my most cherished hoodies:

Work hard and be nice to people

Their newest hoodies tweak the slogan.

Work hard and love yourself.

I love it. It’s good advice to live by. Their gym rules also reflect their philosophy:

Impact Gym Rules

This just fits my own personal style very well.

The Coaches

In the show Cheers, the patrons show up every day because they love being in a place where everyone knows their name.

I feel a lot like this at Impact. I love going because I know I’m going to not only get a good workout, but I’ll see people I genuinely like and have great conversations.

Impact Coaches

Impact is a small private gym owned by Drew Ragan (the Turkey). I’ll admit, when I first met him, I thought he was another stereotype of a gym rat swole bro. I couldn’t have been more wrong.

He’s extremely knowledgeable, caring, and intelligent. I call him the “Philosopher Bro” as it’s just as easy to get into a conversation with him about eastern philosophy as a discussion about proprioception.

Riley (the photo bomber) is the other main coach and he’s inquisitive, hilarious, knowledgeable, and kind. Together, they’ve created an environment that’s friendly, fun, and just a bit wacky (as evidenced by the photos).

As kind and caring as they are, they will push you to give your best. You get out what you put in and their approach gets results.

And don’t worry, Drew doesn’t wear a costume to every workout. I just happened to have photos from Halloween and Thanksgiving when he did.

They Give back

Hapy faces at a go-giver

One of my favorite things about the gym is they contribute back to the local community. Every Saturday they have a “Go-Giver” workout that members and non-members can attend for $10. All proceeds go to a local charity chosen by the members of the month.

I even got my skinny friend Noah to come out one time.

Give it a try

If you don’t live in the area, I encourage you to find a gym like Impact. If you do live in the area, give Impact a try. Your first workout is free. Just tell them Phil sent you.

They’re located at: 1508 128th Pl NE, Bellevue, WA 98007

If you want to go when I’m there, DM me on Twitter and I’ll tell you when I’ll be there next.

This is a great way to start the new year on the right foot. You won’t regret it!

personal 17 comments suggest edit

This year felt a lot like living in the darkest timeline and an episode of Black Mirror at the same time.

The darkest timeline

When I look back at the year, the most significant event for me is also the hardest to write about because it’s deeply personal. Not just for me, but for members of my family. And I often don’t see how the benefit of exposing our private lives overcomes the risks.

But in talking to them and others, they encouraged me to share in the hopes it helps others in similar situations. Trigger warnings, discussion of depression and suicidal thoughts ahead.

For years, my wife has struggled with crippling suicidal depression. It’s something she’s written about on Medium in beautiful yet haunting posts. We approach it like an illness, not a character failing. Over time, it’s improved, but it’s always there. We struggle together, but we manage.

This year, it became more difficult to manage because we started to see signs of this with my son. He went through a period where he had a downright negative physical reaction to going to school. On top of that, he would talk about how he was worthless and wanted to die. It’s easy to dismiss such talk from a child. It may have been an idle fascination, but there was something there and we wanted to address it before it became something more serious.

At the same time, work was extremely stressful for me. My work suffered, and my ability to support my family suffered. In the span of a month both my manager and my manager’s manager left the company leaving me reporting directly to our CEO according to the org chart, but pretty much left to my own devices.

My wife had been improving, but our son’s issues were triggering for her and it was difficult for her to support him while focusing on her own healing. With all that, we were still scraping by because the kids were in school during the day. With the summer approaching, we were worried about the toll that would take on my wife.

It was then I asked GitHub for a leave of absence. Fortunately, our HR folks told me about the Family Medical Leave Act or FMLA.

The Family and Medical Leave Act (FMLA) provides certain employees with up to 12 weeks of unpaid, job-protected leave per year. It also requires that their group health benefits be maintained during the leave.

When you take a leave, there’s always the concern that your job (or equivalent) won’t be there when you return. If approved, the FMLA protects your job during your leave. Our son’s doctor signed the necessary paper-work and I took eight weeks off for the summer. In general, FMLA leave is unpaid, but on a case-by-case basis, Github provides eight weeks of paid leave for serious situations like this. I am very grateful to my employer.

Jamaica

We decided to start the leave by getting out of town. A change of scenery would do us a lot of good, so we flew to Jamaica! This was our first time staying in an all-inclusive resort. We really didn’t want to have to think about anything, but decompress and spend time together.

the resort

We had a magical time there. We really didn’t want to leave, but resorts aren’t cheap.

During this time, I started reading Learned Optimism: How to Change Your Mind and Your Life in the hopes it would provide guidance on how to help my son. When we got back from Jamaica, we also set up some counseling for him through our local Eastside Youth Services center.

For the rest of the summer, we spent a lot of time together. It was a gorgeous summer in Bellevue and we went on a ton of hikes and spent a lot of time swimming at the lake. And throughout all this, we really worked through our issues. I’ll always treasure this time.

Getting help

Perhaps in another post I’ll talk about some of the other things that happened in my life 2017 if you’re interested (say so in the comments).

But for this post, I leave you with this. Mental health issues are not a character flaw or a moral failing. It’s an illness. It can be treated. And if you’re one who supports people with mental illness, you need support too.

Here’s some useful resources to keep in mind:

The good news is all the time we spent this summer really paid off. We continue to have our challenges, but both my wife and son are in a much better place. I’m doing much better as well. I didn’t mention my daughter, but she’s made out of titanium. She’s well too.

Again, I write this not because I enjoy sharing such personal details. I’d rather keep it all quiet because it’s nobody else’s business. But I’ve heard many times from many people how hearing that someone else they know is going through a similar struggle was not only comforting, but spurred them to take action to address their own situation. If you’re in the same boat, I hope this post helps.

And if you are in such a boat and have nobody else to talk to, feel free to hit up my DMs on Twitter. I’ll be honest though, to maintain my own mental health, I’m protective of my time and may not respond in a timely fashion. After all, we’re on a holiday break right now and my kids are telling me to get off the computer. :)

git crypto humor oss bash shell unix 4 comments suggest edit

A recent wry tweet by @bcrypt really tickled my funny bone:

gitcoin: the author of the commit sha1 with the longest prefix of 0’s in your repository is now the project maintainer

The genius in the tweet is how it draws a comparison to Bitcoin’s approach to achieving distributed consensus with achieving consensus on choosing a project maintainer.

With Bitcoin, there’s a proof-of-work algorithm that relies on generating SHAs until you find one with a certain number of leading zeros. Git commit SHAs could perhaps serve a similar purpose.

Is this a good way to pick a project maintainer? Probably not. But then again, it’s not that far off from how I make most important life decisions. If your project wants to take a walk on the wild side, I’ve got just the command for you.

A simple solution

Run the following command in a Git repository and it’ll return the name of the author, the commit date, and the SHA of the commit that has the lowest SHA sorted lexicographically.

git log --pretty=format:"%H %ad %an" | sort | head -n1

Or, if you prefer a Git alias:

[alias]
  coin = !git log --pretty=format:'%H %ad %an' | sort | head -n1

The SHA that results will have the most leading zeros in the repository. There may be other commits with the same number of leading zeros, but for the sake of this thought exercise, I’ll just pick the one that’s sorted first.

For those not familiar with the git log command, there are a gaggle of options. I’ll break down this specific invocation.

The --pretty=format option takes a custom format string that specifies the contents of the output. %H is the commit SHA. %ad is the commit date and %an is the author name.

We pipe that to the sort command. Since no two SHAs can be the same, we don’t have to worry about sorting on just the first column. We can just sort using the entire line as the sort key. Then we use head -n1 to pluck the first item.

It’s possible that there won’t be any commits with leading 0s, but I ignore that for now. I figure the commit with the lowest SHA sorted alphabetically fits with the spirit of the idea.

Since github.com runs on Ruby on Rails, I thought it’d be fun to try it out on https://github.com/rails/rails. I cloned the repository to my machine and ran git coin on it. Here’s the output (SHA truncated for presentation purposes):

000121e8 Thu Nov 15 23:10:45 2012 +0200 Agis Anastasopoulos

Congratulations Agis! You are the new maintainer of Rails!

Not so fast!

I know what some of you are thinking, “You are ridiculous. This is a waste of time.” To those I say, hold my beer because I’m not done yet.

Others who are familiar with Bitcoin’s consensus protocol are thinking, “This is not how the protocol works. It’s not about choosing the lowest sorted SHA, it’s about reaching a target number of leading zeros.” To those I say, you’re taking this too seriously!

Even so, in anticipation of all the “Well, Actually” responses I’m sure to receive, I’ll address this fair point.

With Bitcoin, the first miner to generate a SHA with the target number of leading zeros is the one to add their block to the global blockchain.

I’m hand waving a bit here for the sake of brevity. The important point is that it’s not the block with the lowest SHA. It has nothing to do with the sorting of SHAs.

Over time, the protocol compensates for the global increase in computing power by increasing the number of leading zeros in the proof of work target. That way a block is added roughly every ten minutes no matter how fast computers get and no matter how many computers are mining.

If we translate this to the gitcoin idea, we probably want to look at the first commit to reach the most number of leading zeros.

For example, say that the current maintainer was chosen because of a commit with a SHA that has two leading zeros. The next maintainer is chosen by the commit that has three (or more) leading zeros. The next maintainer after that is chosen by the first commit with one more leading zero than the commit that chose the previous maintainer. And so on.

In other words, every time a new maintainer is chosen by this protocol, the target number of leading zeros increases by one. The implication is that over time, maintainers chosen by this project will spend more and more time maintaining the project. Not sure that’s necessarily a desirable trait or not.

The shell script to find the maintainer with these rules is considerably more complex than my previous script. This is why I originally wanted to stop with that script and call it a day. Also, I’m lazy.

Not to mention, my background is primarily with Windows so my Unix-fu is fairly weak. However, my time at GitHub working with Git has helped me exercise those muscles quite a bit more than I did before. So I thought it’d be fun to give it a shot. Here’s the script I came up with:

TZ=UTC git log --pretty=format:'%H%x09%ad%x09%an' --date=iso-local | grep ^0.* | sed -E 's/(0+)(.*)/\1\t\1\2/' | sort -k1,1 -k3,3r | tail -n1 | cut -f 2,3,4

And the award goes to…

When I run this against the Rails repository, it outputs (again, SHA truncated for presentation purposes):

00050dfe	2006-04-09 21:27:32 +0000	David Heinemeier Hansson

Sorry Agis, this David Heinemeier Hansson person is now the Rails maintainer! I hope David accepts this responsibility seriously.

Uh, still not there.

If you read an earlier version of this post, you’ll note I declared DHH the maintainer of Rails. But Jean-Jacques Lafay noted in the comments to this post that I need to look at the leading zeros of the SHA when written in binary form. Whoops!

This makes a lot of sense, when you think about it. Under my original implementation, every time we choose a new maintainer, we increased the difficulty in choosing the next maintainer by 16 times. When we look at leading zeros in binary form, we only double the time.

Fortunately, the correction to my script is pretty simple, I need to grab all the zeros (if any) and the first non-zero character when creating the sort key. Any characters after that won’t change the leading zeros.

For example, 001a and 001b have the same number of leading zeros when expressed as binary. But 00a and 00b do not have the same number of leading zeros.

So here’s the updated script:

TZ=UTC git log --pretty=format:'%H%x09%ad%x09%an' --date=iso-local | sed -E 's/^(0*[1-9a-f])(.*)/\1\t\1\2/' | sort -k1,1 -k3,3 | head -n1 | cut -f 2,3,4

And once again, Agis is the new maintainer for Rails!

The excrutiatingly detailed breakdown

Let’s break this down piece by piece for those of you like me who don’t eat and breath shell scripting.

The first thing we do is set the local timezone to UTC (TZ=UTC) so we can sort by date and compare apples to apples.

git log --pretty=format:'%H%x09%ad%x09%an' --date=iso-local

Just like before, we’re running a git log command. It looks ugly, but all I’m doing here is using tab character %x09 in place of spaces. That’ll come in handy later. I also specify that the date format should be iso-local. This provides a date that’s sortable lexicographically. We’ll need that later too.

sed -E 's/^(0*[1-9a-f])(.*)/\1\t\1\2/'

Sed is a powerful command used to perform text transformations on an input stream. In this case, we’re using the s/ command which is a regex replacement. The -E indicates that sed should use extended regular expressions. What I’m doing here is extracting the consecutive sequence of 0s that the SHA starts with as a new column in the output.

So if the git log command we ran earlier returned something like this (SHAs and name truncated for presentation purposes):

005371e1	2004-12-01 13:59:16 +0000	David
0daa29ec	2004-12-01 13:18:51 +0000	David
08a2249e	2004-11-26 02:16:05 +0000	David

Piping this output to this sed expression results in (name truncated for brevity):

005	005371e1	2004-12-01 13:59:16 +0000	David
0d	0daa29ec	2004-12-01 13:18:51 +0000	David
08	08a2249e	2004-11-26 02:16:05 +0000	David

That format is pretty handy because we can sort this by the first column. This sorts commits from those with the most leading zeros to the least.

This will also group all SHAs with the same number of leading zeros together. Then we can sort by the date column to find the first commit in any such group.

sort -k1,1 -k3,3

Does exactly that. One thing that tripped me up when I first worked on this is I thought I should be able to sort -k1 -k3. The -k option specifies a sort key. By default, when you specify a column, it takes that column and all columns after it as the sort key. Thus -k1 is pretty much equivalent to not specifying a sort key at all as it sorts by the whole line.

Fortunately, you can specify an end column for the sort key using the comma. So -k1,1 sorts just by the first column. Whereas -k1,3 would take the first three columns as a sort key.

head -n1

Now that we have the proper sort in play, we just need to take the first entry. this is the oldest commit with the most leading zeros.

cut -f 2,3,4

And finally, we don’t need the leading zeros column in the final output so I run the cut command and only keep columns 2, 3, and 4. This is where inserting the tabs before comes in handy. By default, cut uses the tab character as a delimiter.

leadership management 1 comments suggest edit

In Endless Immensity of the Sea I wrote about a leadership style that encourages intrinsic motivation. Many people I talk to don’t work in such an environment. Even those who work in places that promote the ideals of autonomy and intrinsic motivation often find that over time, things change for the worse. Why does this happen?

I believe it’s the result of management entropy. Over time, if an organization doesn’t actively work to fight it, their leaders start to lose touch with what really motivates people.

Theory X and Theory Y are two theories of human motivation and management devised by Douglas McGregor that serve to explain how managers view human motivation.

Theory X is an authoritarian style where the emphasis is on “productivity, on the concept of a fair day’s work, on the evils of feather-bedding and restriction of output, on rewards for performance … [it] reflects an underlying belief that management must counteract an inherent human tendency to avoid work”

Meanwhile,

Theory Y is a participative style of management which “assumes that people will exercise self-direction and self-control in the achievement of organisational objectives to the degree that they are committed to those objectives”. It is management’s main task in such a system to maximise that commitment.

There’s also a Theory Z style of management that came later.

One of the most important pieces of this theory is that management must have a high degree of confidence in its workers in order for this type of participative management to work. This theory assumes that workers will be participating in the decisions of the company to a great degree.

It’s pretty clear that in the tech industry, most companies aspire to have a management style that encourages intrinsic motivation and personal autonomy. As Dan Pink notes, there’s a lot of evidence that it’s more motivating and effective for the type of creative work we do than Theory X.

However, I have a theory that despite all this evidence and aspirations to be Theory Y or Z, many managers in the tech industry are really closet Theory X practitioners.

In many cases, it may not even be a conscious choice. Or, perhaps they didn’t start that way, but over time they drift. One scenario that could cause such a drift is when a company encounters a series of setbacks.

A good leader looks hard at the culture and system put in place and how they contribute to the setbacks. A good leader makes it a priority to improve those things. A bad leader blames individuals. This blame feeds into the Theory X narrative and causes leaders to lose trust in their people.

In a following post, I hope to cover some typical myths and incorrect beliefs that managers have that also contribute to managers drifting to the dark side of Theory X.

leadership management 6 comments suggest edit

There’s this quote about leadership that resonates with me.

If you want to build a ship, don’t drum up people together to collect wood and don’t assign them tasks and work, but rather teach them to long for the endless immensity of the sea.

Most attribute it to the French author Antoine de Saint-Exupéry, but it’s doubtful that he wrote these exact words. For one, he’s French, so the words he wrote probably had a lot of àccênts and “le”, “la”, and “et” words in them.

This English quote appears to be one of the rare cases where a paraphrase has more impact than the original. None of that diminishes the power of the quote.

Obligatory image of the sea

The quote encourages leaders to cultivate intrinsic motivation as a means of leading people rather than an approach built on authority and command. Surprisingly, Cartman, with his incessant requests to respect his authority, is not an exemplar of good leadership.

If you question the value of intrinsic motivation, take a moment to watch this Dan Pink video. I’ve referenced it in the past, and I’ll keep referencing it until every single one of you (or perhaps more than one of you) watch it!

It’s easy to read this quote as a laud to leadership and a rejection of management by contrast. As if management by necessity must be built on command and control. But I reject that line of thinking. Management and leadership address different needs and can be complementary.

To me, the quote contrasts leadership with a particular style of management built on hierarchy and control. This is a style that is antithetical to both building ships and shipping software.

The Valve handbook covers this well.

Hierarchy is great for maintaining predictability and repeatability. It simplifies planning and makes it easier to control a large group of people from the top down, which is why military organizations rely on it so heavily.

But when you’re an entertainment company that’s spent the last decade going out of its way to recruit the most intelligent, innovative, talented people on Earth, telling them to sit at a desk and do what they’re told obliterates 99 percent of their value. We want innovators, and that means maintaining an environment where they’ll flourish.

I anticipate some commenters will point out that, in practice, Valve might not live up to this ideal. I don’t know anything about the inner workings of Valve. I do know that with any human endeavor, there will be failures and successes. And they won’t be distributed evenly, even within a single company. Perhaps they do not live up to these ideals, but that doesn’t change the value of the ideals themselves.

The Valve handbook addresses entertainment companies, but the ideas apply to any company where the nature of the work is creative and intellectual in nature. Or put another way, it applies to any environment where you want your workers to be creative and intellectual.

Even the handbook makes the mistake of mischaracterizing the nature of the work our military does. It assumes that the military gets the best results when folks just do what they’re told.

Leaders such as David Marquet, a former nuclear submarine commander, challenge this idea. He notes that when he stopped giving orders, his crew performed better.

This is not a polemic against managers or management. Rather, this is an encouragement for a style of management that fosters intrinsic motivation.

It’s not easy. There’s a lot of factors that hinder attempts at this style of leadership. All too often companies conflate hierarchy with structure and management with leadership. It’s important to separate and understand these concepts and how to apply them. Especially when you’re a small company reaching the point where you feel the need for more structure and management.

In a follow-up post, I’ll write more about some of these points. I plan to cover what I mean when I say that leadership and management are complementary. I’ll also cover what it means to conflate all these distinct concepts.

In the meanwhile, as you build your next ship, I encourage you to focus on the longing that leads you to build it. What is endless immense sea in your work?

personal blogging 6 comments suggest edit

I started my first blog at haack.org some time in the year 2000. You can still see pieces of it in the Internet Archive Wayback machine.

My first blog

You have to love this part…

IE 4 Only yo!

Ah, the bad old days of the internet.

Back then I could probably count the number of folks who read my blog with the fingers of one hand. Perhaps not even counting the thumb. It was just an outlet for me to share inside jokes with other friends who had their own blogs.

I started this before I knew what a weblog or blog was. I wrote this with a bespoke artisanal classic ASP (Active Server Pages without the “.NET” part. We lived like savages back then.) site I built. It was terrible. No database. Just me writing HTML for every post. I let that blog die due to neglect and didn’t start blogging again until around 2004.

The new blog ran on Subtext, an open source ASP.NET blog engine I ported from an older .TEXT platform. It was a real labor of love. Four years ago, I switched to hosting by blog on GitHub Pages with Jekyll.

The point of this stroll down memory lane is to say that I’ve always felt it was important to host my blog on something under my control with my own domain name. My blog has always been primarily an outlet for me.

When I first started, my blog was more of an online diary. I’d write about my day, movie reviews, etc. When I restarted my blog, I tended to write more technical pieces in the hopes of helping others out.

My friends who weren’t programmers would ask what language my blog was written in. It was all gibberish to them. However, it was important to me that haacked.com represented the full me. One day I might write about playing soccer against Vinnie Jones or with Agent Coulson. On another day I might write about parenting. And yet another day I might write about auditing ASP.NET MVC actions.

The point is, I wrote what I wanted to write and didn’t worry about what others wanted to read too much.

But there are consequences. After a million posts about the intricacies of Git aliases, it’s inevitable that my friends who aren’t techies got bored. And I have to say, I missed their involvement with my writing. I enjoy the interactions and feedback that came of it and I was sad that they were excluded from the blogging community I had become a part of.

Enter Medium

When Medium first came on the scene, I ignored it. I’ve ignored it for a long while.

But not too long ago, my wife started a Medium blog. I may be biased, but I think she’s a beautiful writer who writes beautifully. And that got me more interested in the platform.

That lead me to learn that if you import a blog post into Medium, it sets the original post as the canonical source via a link tag. Here’s an example of the link tag for a post I imported into Medium from haacked.com. This ensures that search engines aren’t confused by multiple sources of content and sees your original blog as the ultimate authority.

<link rel="canonical"
  href="https://haacked.com/archive/2017/08/16/the-moment/">

This alleviates my concerns about being in control of my blog. The canonical source is still haacked.com which is in a Git repository that is hosted on GitHub, but is cloned to my machine. If Medium and GitHub were to go down, I’d be sad and unemployed, but I’d have the free time available to move my blog to another host and keep it up at haacked.com.

Importing into Medium is quick and easy. Visit https://medium.com/p/import and paste in the URL to the post you want to import. That’s it!

It plucks the contents of my post without of all the extra navigation and header/footer material like magic.

So now, I’m experimenting with Medium as my blog for my non-programmer friends. When I write something that isn’t deeply technical on haacked.com, I’ll cross-post it to Medium. But for my Git posts, I’ll keep those here only.

I’ll revisit this idea down the road to see if it works for me. I’m curious to hear your thoughts in the comments.

personal 4 comments suggest edit

Twin Falls lies around a forty minute drive east of Bellevue, Washington. From the trail head, the path leads to views of three separate waterfalls. Yes, three. “Twin Falls” has a nicer ring to it than “Triplet falls.”

Image of the river

Focus too much on the hike to the falls and you might miss the side trails down to the Snoqualmie River. The river is cold (or “refreshing” as they say around here) and full of boulders big and small. If you’re careful, you can hop from boulder to boulder to reach an island that splits the river. Or you can sit back and watch others attempt it and fall in. That’s always good for a chuckle.

On a recent trip, I took my kids and their friends to this island. There’s a trio of elephant size boulders in the middle of the river off the tip of the island. To reach them requires a bit of foolhardiness and a compunction to wade into the water and fight a strong current. I am such a foolhardy compulsive so I ventured into the water to climb a boulder with a flat, but angled, top. The vantage point gave me a fine view of the river valley and the kids skipping stones down below.

As I sat there, I contemplated a random thought. Scenes like this are often used to set up a blog post (or “Medium piece” if you’re fancy). An author takes a story from their life, or a historical anecdote, and uses it to start a post. The story seems unrelated at first. What’s the point?

This is before the author employs some rhetorical wizardry and by the end of the piece, an important life lesson is revealed! Like a fine rug, the story ties it all together. It’s a pattern so common I consider it the calling card of the Medium post.

The thought struck me then, would this very moment serve such a purpose? Would a major life lesson reveal itself to me right now? Something I could leverage as social media fodder for the consumption of others. I pondered. And pondered. Nothing.

No life hack or societal lesson or philosophical truth revealed itself to me. Nothing I could sell for increased follower counts or “likes” or ad revenue invaded my thoughts.

No, I would have to come to grips that I had nothing at all to learn from this moment. Nothing to share. There, with the sun shining overhead, the river flowing around me, a breeze on my face, I would have to enjoy it for what it is. A moment. My moment. And just be present.

At least until I reached my computer.

aspnetmvc security 12 comments suggest edit

Phil Haack is writing a blog post about ASP.NET MVC? What is this, 2011?

No, do not adjust your calendars. I am indeed writing about ASP.NET MVC in 2017.

It’s been a long time since I’ve had to write C# to put food on the table. My day job these days consists of asking people to put cover sheets on TPS reports. And only one of my teams even uses C# anymore, the rest moving to JavaScript and Electron. On top of that, I’m currently on an eight week leave (more on that another day).

But I’m not completely disconnected from ASP.NET MVC and C#. Every year I spend a little time on a side project I built for a friend. He uses the site to manage and run a yearly soccer tournament.

Every year, it’s the same rigmarole. It starts with updating all of the NuGet packages. Then fixing all the breaking changes from the update. Only then do I actually add any new features. At the moment, the project is on ASP.NET MVC 5.2.3.

I’m not ready to share the full code for that project, but I plan to share some interesting pieces of it. The first piece is a little something I wrote to help make sure I secure controller actions.

The Problem

You care about your users. If not, at least pretend to do so. With that in mind, you want to protect them from potential Cross Site Request Forgery attacks. ASP.NET MVC includes helpers for this purpose, but it’s up to you to apply them.

By way of review, there are two steps to this. The first step is to update the view and add the anti-forgery hidden input to your HTML form via the Html.AntiForgeryToken() method. The second step is to validate that token in the action that receives the form post. Do this by decorating that action method with the [ValidateAntiForgeryToken] attribute.

You also care about your data. If you have actions that modify that data, you may want to ensure that the user is authorized to make that change via the [Authorize] attribute.

This is a lot to track. Especially if you’re in a hurry to build out a site. On this project, I noticed I forgot to apply some of these attributes where they should be placed. When I fixed the few places I happened to notice, I wondered what places did I miss?

It would be tedious to check every action by hand. So I automated it. I wrote a simple controller action that reflects over every controller action. It then displays all the actions that might need one of these attributes.

Here’s a screenshot of it in action.

Screenshot of Site Checker in action

There’s a few important things to note.

Which actions are checked?

The checker looks for all actions that might modify an HTTP resource. In other words, any action that responds to the following HTTP verbs: POST, PUT, PATCH, DELETE. In code, these correspond to action methods decorated with the following attributes: [HttpPost], [HttpPut], [HttpPatch], [HttpDelete] respectively. The presence of these attributes are good indicators that the action method might modify data. Action methods that respond to GET requests should never modify data.

Do all these need to be secured?

No.

For example, it wouldn’t make sense to decorate your LogOn action with [Authorize] as that violates causality. You don’t want to require users to be already authenticated before the log in to your site. That’s just silly sauce.

There’s no way for the checker to understand the semantics of your action method code to determine whether an action should be authorized or not. So it just lists everything it finds. It’s up to you to figure out if there’s any action (no pun intended) required on your part.

How do I deploy it?

All you have to do is copy and paste this SystemController.cs file into your ASP.NET MVC project. It just makes it easier to compile this into the same assembly where your controller actions exist.

Next, make sure there’s a route that’ll hit the Index action of the SystemController. If you have the default route that ASP.NET MVC project templates include present, you would visit this at /system/index.

Be aware that if you accidentally deploy SiteController, it will only responds to local requests (requests from the hosting server itself) and not to public requests. You really don’t want to expose this information to the public. That would be an open invitation to be hacked. You may like being Haacked, it’s no fun to be hacked.

And that’s it.

How’s it work?

I kept all the code in a single file, so it’s a bit ugly, but should be easy to follow.

The key part of the code is how I obtain all the controllers.

var assembly = Assembly.GetExecutingAssembly();

var controllers = assembly.GetTypes()
    .Where(type => typeof(Controller).IsAssignableFrom(type)) //filter controllers
    .Select(type => new ReflectedControllerDescriptor(type));

The first part looks for all types in the currently executing assembly. But notice that I wrap each type with a ReflectedControllerDescriptor. That type contains the useful GetCanonicalActions() method to retrieve all the actions.

It would have been possible for me to get all the action methods without using GetCanonicalActions by calling type.GetMethods(...) and filtering the methods myself. But GetCanonicalActionsis a much better approach since it encapsulates the same logic ASP.NET MVC uses to locate actions.

As such, it handles cases such as when an action method is named differently from the underlying class method via the [ActionName("SomeOtherMethod")] attribute.

What’s Next?

There’s so many improvements we could make (notice how I’m using “we” in a bald attempt to pull you into this?) to this. For example, the code only looks at the HTTP* attributes. But to be completely correct, it should also check the [AcceptVerbs] attribute. I didn’t bother because I never use that attribute, but maybe you have some legacy code that does.

Also, there might be other things you want to check. For example, what about mass assignment attacks? I didn’t bother because I tend to use input models for my action methods. But if you use the [Bind] attribute, you might want this checker to look for issues there.

Well that’s great. I don’t plan to spend a lot of time on this, but I’d be happy to accept your contributions! The source is on GitHub.

Let me know if this is useful to you or if you use something better.

github 3 comments suggest edit

One of my goals at GitHub is to make GitHub more approachable to developers. If you use GitHub, I want you to have tools that complement the way you work and help you to be more effective. In some cases that’s integrating directly in your Editor or IDE of choice. In other cases, it’s offering tools that work side-by-side with your existing tools.

Today, we took one step towards that goal with the release of two major releases: Git and GitHub integration in Atom and the new Desktop Beta rebuilt on Electron.

For Desktop, our plan is to eventually replace the existing platform-specific clients with the new Electron based client. For now, you can run them side-by-side.

If you’re interested in more details about our efforts, we wrote a pair of posts in the GitHub Engineering blog.

And before I forget, all of this is open source.

I hope you get involved!

If you are attending GitHub Satellite next week (May 22-23) in London, I’ll be giving a talk that demonstrates some of the great work my teams are doing and how that fits into this grand vision. See you there!

github dotnet aspdotnet microsoft 25 comments suggest edit

Yesterday was the 15th anniversary of .NET’s debut to the world. And Visual Studio was first released twenty years ago! In a recent episode of On .NET, I went to the Channel 9 studios to talk a bit about the history of .NET, my work at GitHub, and challenges to .NET’s future success among other random diversions.

I hope you enjoy the interview!

On a personal note, I’ve found it hard to blog lately because every topic seems so trivial in light of what’s happening in our country. It’s easy to feel helpless and despair. If I could humbly recommend one thing that can help give you some semblance of power back, it’s to call your representatives. It’s more impactful than partaking in internet surveys, and way more useful than debating people on Facebook. I’ve been using 5calls.org to walk me through what to do. It only takes around five minutes of your time (I have a weekly appointment on my calendar).

If you want to understand why this is effective, check out www.indivisibleguide.com which talks about the motivations of your local representatives.

For my part, I will continue to RESIST. But I do think that continuing to live my life and write about topics that interest me can be part of that. So I hope to get back to writing about software and software leadership more. Stay tuned!

git 11 comments suggest edit

Happy New Year! I hope you make the most of this year. To help you out, I have a tiny little Git alias that might save you a few seconds here and there.

When I’m working with Git on the command line, I often want to navigate to the repository on GitHub. So I open my browser and type in the URL like a Neanderthal. Yes, a little known fact about Neanderthals is that they were such hipsters they were using browsers before computers were even invented. Look it up.

But I digress. Typing in all those characters is a lot of work and I’m lazy and I like to automate all the things. So I wrote the following Git alias.

[alias]
  open = "!f() { REPO_URL=$(git config remote.origin.url); explorer ${REPO_URL%%.git}; }; f"
  browse = !git open

So when I’m in a repository directory on the command line, I can just type git open and it’ll launch my default browser to the URL specified by the remote origin. In my case, this is typically a GitHub repository, but this’ll work for other hosts.

The second line in that snippet is an alias for the alias. I wrote that because I just know I’m going to forget one day and type git browse instead of git open. So future me, you’re welcome.

This alias makes a couple of assumptions.

  1. You’re running Windows
  2. You use https for your remote origin.

In the first case, if you’re running a Mac, you probably want to use open instead of explorer. For Linux, I have no idea, but I assume the same will work.

In the second case, if you’re not using https, I can’t help you. You might try this approach instead.

Update 2017-05-09 I updated the alias to truncate .git at the end.

social coding management 3 comments suggest edit

On Tuesday, November 8, 2016 I’ll be giving a talk entitled “Social Coding for Effective Teams and Products” at QCon SF as part of the “Soft Skills” track. If you happen to be in San Francisco at that time, come check it out.

In anticipation of this talk, I recorded a podcast for InfoQ where I pointed out the irony of using the term “soft skills” to describe the track as these are often the most challenging skills we deal with day to day. They are indeed the hard skills of being a software developer.

In the podcast, we also cover what it was like in the early days of ASP.NET MVC as we went from closed source to open source and how far Microsoft has come since then in the open source space.

Afterwards, we talked a bit about Atom and Electron and the community around those products. And to finish the podcast, we gabbed about my transition into management at GitHub, which is something I wrote about recently.

So if you don’t mind hearing my nasally voice, take a listen and let me know what you thought here.

github csharp dotnet scientist 0 comments suggest edit

In the beginning of the year I announced a .NET Port of GitHub’s Scientist library. Since then I and several contributors from the community (kudos to them all!) have been hard at work getting this library to 1.0 status. Ok, maybe not that hard considering how long it’s taken. This has been a side project labor of love for me and the others.

Today I released an official 1.0 version of Scientist.NET with a snazzy new logo from the GitHub creative team. It’s feature complete and used in production by some of the contributors.

Scientist logo with two test tubes slightly unbalanced

You can install it via NuGet.

Install-Package scientist

I transferred the repository to the github organization to make it all official and not just some side-project of mine. So if you want to get involved by logging issues, contributing code, whatever, it’s now located at https://github.com/github/scientist.net.

You’ll note that the actual package version is 1.0.1 and not 1.0.0. Why did I increment the patch version for the very first release? A while back I made a mistake and uploaded an early pre-release as 1.0.0 on accident. And NuGet doesn’t let you overwrite an existing version. Who’s fault is that? Well, partly mine. When we first built NuGet, we didn’t want people to be able to replace a known good package to help ensure repeatable builds. So while this decision bit me in the butt, I still stand by that decision.

Enjoy!