Zen of Code Review Series

Tree trunk with mushroomsI stumbled (thanks John!) on this post about the right way to review code. This is a key skill for working in a team and one that is underappreciated. A solid code review makes sure the code changes can be understood.

If code can’t be understood, it can’t be changed. If code can’t be changed, business processes can’t be changed (code is, after all, just business process made digital). If business processes can’t be changed, the organization can’t adapt to new opportunities or threats. Have you ever seen a tree grow around a fence? The fence constrains the tree, but the tree keeps trying its best to work around the fence. Neither end up serving their inner purposes. That’s what I think of when I see code that can’t be changed.

Here is a brief excerpt to give you a flavor of the post.

Your goal, then, is clear: question, probe, analyze, poke, and prod to make sure that you, the reviewer, could support the code presented to you for review. From an overall perspective, there are several questions to keep in mind as you begin your task…

It seems like this is a series, where the author discusses code reviews from a variety of different perspectives. Recommended.


“Choose boring technology”

Reading a boring bookThis article on choosing boring technology is so good. It’s from 2015 so some of the tech it references is more mature, but the thesis is that the technology underlying a business should be well known and boring to implement. It also discusses how important cohesive technology can be (I love the final footnote).

I think this is an interesting contrast to microservices, which is essentially solving repeatedly for local optimizations and then relying on the API or message boundary to allow scaling. Microservices, in my experience, often get a bit hand wavey when it comes to operationalization (“just put it on Kubernetes, it’ll be fine”).

I have definitely dealt with this in previous companies where I had to put the kibosh on new technologies being introduced (“nope, we’re going to do it in java”). This meant that as a small team we had a standard deployment stack and process and could leverage our logging knowledge and debugging tools.

Here are some arguments I hear for using the latest and greatest technologies:

  • “Our developers will get bored and we’ll have a hard time recruiting”
    • This is a great reason to have regular hackfests and or support developers working on open source or side projects.
  • “New tech will help us do things faster”
    • It’s definitely worth evaluating new technology periodically and adding it to your stack (especially if it is outsourced, a la RDS, or boring, a la memcached). As the original post mentions, if you get substantial benefits from the new technology, then use it full bore and plan for a migration. Don’t end up in a state where you are half in/half out. Also consider tooling and processes to get things done faster–these may have quicker iteration times with lower operational risk.
  • “Choose the right tool for the job”
    • Most turing complete languages can be used for any purpose. And you shouldn’t be optimizing for the right tool for the job, but rather the right tool for the business for the job.

Really, you should just go read the post. It’s good.

 


“Run less software”

RunningThis post from the folks at Intercom makes some really good points about the benefits you can get from leveraging other software solutions. It’s an interesting article, but the source works at a company that offers a SaaS solution to help you help your customers (I’m a fan). You can read some interesting discussion at HN. An interesting quote from the post:

Choosing standard technologies is very similar to this, only in software. You need to constrain yourself to solving problems mostly, but not exclusively, with a small, specific set of standard tools. By doing this over time we become experts in them. Then, we are able to build better and faster solutions from them.

From my experience with small teams, having a standard software stack is a big win. It lets you reuse business logic and skills across your business. (The spread of microservices may mean this matters less in the future, though with a small team and product microservices may be overkill.)

However, I wish Rich had titled it “write less software” because that is really what he is advocating for. When I use AWS or Intercom or Gmail, I’m not really running less software. In fact, I may be running more. Since I don’t have insight into those applications, I really don’t know. But I’m not concerned about writing, reading and maintaining as much software, and that is the true win.


Book Review: Working With Coders

Woman with 1s and 0sSoftware is so integral to business processes and relatively inexpensive compared to labor that I believe every company is going to be a custom software company, in the same way that every company is an accounting company or every company uses paper. I happened on an interesting blog post and saw the author had written a book, “Working With Coders”. How non technical folks interact with coders is a topic of perennial interest to me, so I picked it up after reading the first few pages on Amazon. The book is written for clients, CEOs or project managers who are going to be working with developers to deliver applications that will provide business value.

Frankly, I couldn’t put it down.

The author, Patrick, is an engaging, opinionated writer. He breaks down complicated concepts into easily digestible pieces. Where there’s more to the story, there’s a footnote with a snarky comment or a link to more information. Patrick also provides nuts and bolts examples to show why something that seems simple to change is not (scaling text in a browser, for example). He also covers how big decisions like language, frameworks and library choices at the beginning of a project constrain freedom and choices further down.

Patrick covers what developers do, how they think, and why projects often fail. I thought his explanation of the benefits of agile development was darn good, and his explanation that even agile projects fail more often then they succeed was pretty depressing. He also discusses how the house construction metaphor for building software is just a big fat untruth.

I also enjoyed the section about testing in general, the various types of testing, and where they make sense. There’s also a section on finding coders, including a good explanation of why not to hire them as employees (you might be better off just hiring a development shop, depending on your needs). The chapter on how to deal with common issues (“the team hates each other”, “we’re behind schedule”) was worthwhile. His solutions won’t work for everyone. Maybe you’ll want to deal with these issues differently, but considering them before they happen will only help you prepare.

Of course, I also enjoyed the chapter on how to keep coders happy (continuous learning, quiet, a fast computer). In general the author is careful to avoid stereotypes, but does do a good job of covering common themes. I haven’t met too many developers who love working in bullpen environments.

I am definitely not the target audience. Neither is someone who is an experienced manager of developers. However, I am a subject of the book, so it resonated with me and I definitely found myself nodding along. There aren’t too many books I have wanted to distribute copies of (the two others are “The Hard Thing About Hard Things” and “Climate Wars”), but this is one.

If you work in a consulting practice with inexperienced clients or if you work in a product company with an owner or higher up that isn’t technical, reading this book will give you insights into their questions and thought processes. And if you can find a way to give them this book without being condescending (“hey, I found this book fascinating for helping facilitate conversation, maybe you will too”), both they and you will benefit.


Fun with golang

Prairie Dog

Yes, it’s not a gopher, but they are related.

I’m writing a small piece of work in golang. It’s been fun to learn a new language. Initial thoughts:

  • I love the strict compiler. It saved me from making some dumb mistakes. It’s annoying at times (when you are cleaning up after println debugging you have to remove the log import statement).
  • I love that go fmt is built right into the language. No more formatting wars.
  • The standard library has some testing support but it’s pretty primitive.
  • It was weird that you have way to mark methods as private.
  • I did a small bit of concurrency work and go seems like a great fit for that.
  • The docs are great. I spent a lot of time on the Tour and the API docs.
  • The name is too general, but when googling, I was able to search for ‘golang’ and retrieve good results.

I have a few friends that rave about go. I can see why.


The joy of removing code

I am working on a project right now where my main task is to remove code. “What? I thought developers were supposed to add code, not remove it?” Well in some cases removing code actually can help a project. Some reasons to remove code: if the code doesn’t serve any purpose, if it isn’t executed, if it is for an edge case that never happens, if it has been superseded.

Removing code is easier with automated tests, but I still find myself using a combination of automated tests, manual testing, and the find command. (This codebase is ruby, if I was using java I’d use the type system.) It’s painstaking work, but will be good in the end.

My steps for removing code:

  • Start with a plan and and end goal in mind. Otherwise it can get overwhelming if you are dealing with a system of any size.
  • Create a feature branch
  • Identify one piece of code you’re going to either remove or keep
  • Make sure you know where it is called. If it isn’t called anywhere, remove it.
  • Remove any tests and associated functionality (views, helpers, etc).
  • Examine any state managed by the code for removal (database tables, etc)
    • Oftentimes I’ll just note that this should be removed in a few months, and focus on hiding the UX. It’s a lot easier to resurrect UX if you make a mistake than it is a dropped database table.
  • Commit the changes with a good commit message.
  • Fan out from there and see if you need to add anything to your list.

Take your time, don’t rush it.

Code that never runs can’t have any bugs, and is super fast. Think about removing some code today.


CircleCI shutting down version 1.0

I’ve been a happy user of CircleCI at multiple companies. Right now we pay them at The Food Corridor and they handle almost all our deployments. (I still deploy to production manually.)

We just got a note that they are shutting down their 1.0 offering and will not support it as of Aug 2018. The 2.0 offering was announced in 2016 and generally available in 2017. So, there will be about one year of overlap. Not too long.

I understand that desire to move forward.Trust me, I do.

I don’t know how much engineering effort it takes to support the two versions, but my guess is that they’ll see some significant customer loss from this. Why? CI is something that you just want to work. You don’t want to think about it. Which is why a SaaS solution makes so much sense. I am happy to just keep paying them month after month for their excellent product.

But, if I have to take some cycles to move from CircleCI 1.0 to CircleCI 2.0, why wouldn’t I take some time and evaluate other solutions too? I assume they’ve run the numbers and the amount of money it takes to support 1.0 must be more than the amount they will lose via churn.

AWS does a good job of this–they never deprecate anything (you can still set up SimpleDB if you want). They just hide it, make other offerings better, and make older offerings more expensive.

In fact, if I were CircleCI, I might offer a ‘legacy’ CircleCI 1.0 plan, where people with significant investments in the older infrastructure can pay more for access to that old codebase. Depending on the amount of support required, that might be some significant free money.

Relatedly, Amy Hoy has a great post on how to get your customers to pay you more money.


Coding tests for interviews

Ahmed Fasih posted his proposed alternative to a HackerRank pre-interview test. This sparked comments in the HN discussion.

I think it is worth approaching these kinds of tests from both sides, as this topic has come up a lot in some email lists of which I am a member.

As an employee, you want to be assured of the best chance of finding a job that is a good fit, and of minimizing the time spent to apply to each job. You also want to maximize the number of jobs you get offered, so you have optionality (“well, I’d love to work for you, company XYZ, but I’m considering other offers and was wondering if you could give me more XXX” where XXX is whatever you desire, money, time off, health care, etc).

As so many employees say in the discussion, if you are a senior person, these kinds of tests can be a bit insulting and disconnected from the actual work. Who is going to transform a 2D array in their regular job? I’d reach for a library or stack overflow answer.

On the other hand, if you are at the point where you need to fill out an online test rather than talking directly to the hiring manager about how you can solve her pain points, maybe that’s a problem? LinkedIn is pretty magical in terms of finding this info out, though of course there may be corporate protocols that make this circumvention impossible.

As an employer you want to find the best person for the price in the shortest amount of time. Where best depends on the position, but is some mix of skills, culture fit, desire for the job, and perceived amount of time they’ll stay. You also want to be fair to all applicants and have some kind of apples to apples means of comparison.

As so many managers say in the discussion, these tests weed out folks who can’t code their way out of a paper bag. If you’re a senior engineer, you’ve probably worked with some folks like that, so you can see the need. They also do so relatively quickly and in a way that scales and is equitable across different candidates.

So, as a senior engineer, I’d:

  • seek employment where I could circumvent these types of tests through my network
  • avoid these types of employers unless it was a great job
  • if I had to take the test, try to have sympathy with the employer and take it as an opportunity to brush up on my algorithms

And if I were the employer, I’d think about these tests are a filter. Just like a GitHub profile, they’ll give you some information. Whether that information is relevant to the current candidate search, and is worth filtering out good candidates who don’t bother filling out tests, is an exercise left for the reader.


How Trello Wowed Me By Handling An Edge Case

We are using Trello for our product development planning at The Food Corridor. Previously we were using Pivotal Tracker, which I chose, but a new team came on to help us and they were more comfortable with Trello. I may do a compare and contrast of these tools in the future, but for now I wanted to celebrate the beauty of a well designed piece of software.

I don’t mean how Trello looks, though it certainly looks pretty. I mean how they handle UX edge cases. I ran into one the other day, and it blew my mind that Trello acted as I had hoped.

Here’s the situation. We use the Trello numeric card ID along with this git hook:

#!/bin/sh

# from http://stackoverflow.com/a/16061192/203619

if story_id=`git branch |grep '*'|sed 's/.*-//'`
then
    echo "[#$story_id]" >> "$1"
fi

To help tie commits to stories. If someone is working on a story with the id 123, they work on a feature branch called add-new-feature-123. When committing, they may write a message like: “Updated the message to the end user when they save”, and this hook will automatically add “[#123]” onto that commit message.

When someone is looking at the code six months or two years from now, they will be able to look up that story and get context about why the message was changed beyond what was in the commit log.

We were cleaning up old releases in Trello and had moved all the released stories to another board. However, I noticed that the cards were renumbered when they were moved to that board. Whoops! That meant that the commit messages wouldn’t be useful in looking up the cards. I had discussions with the product manager and we decided to keep all future releases on the same board to maintain the numbers–we’d just archive them (it’s worth noting that when you search for 123 and the card is archived, the search won’t return the card unless you add the is:archived search operator to your query).

However, I was ready to write off the cards that had been moved to the other board. What were the chances that if I moved the cards back to the original board, the card numbers would be maintained? I gave it a try just to see.

Trello did the right thing! The cards, when moved back to the original board, assumed their original numeric ID.

I am very impressed, as I imagine there are a very small portion of Trello users who care about this behavior. As someone who doesn’t really care about design but does care about user experience, that is an example of attention to detail that I wanted to call out and praise.


All the ways usernames can go wrong, or a story about why you favor third party solutions

This post on usernames is hitting the top of Hacker News right now. It’s worth a read for an in depth examination of how many ways something that seems fairly simple, usernames, can go wrong. Whether that is allowing impersonation due to unicode code points (see a related XKCD), how to handle email addresses, or what usernames should be prohibited, the simple idea of having someone use a text string as part of their authentication scheme is not so simple.

Here’s a great quote from the post talking about the right way to do it:

So if you’re building an account system from scratch today in 2018, I would suggest reading up on [the tripartite identity] pattern and using it as the basis of your implementation. The flexibility it will give you in the future is worth a little bit of work, and one of these days someone might even build a good generic reusable implementation of it (I’ve certainly given thought to doing this for Django, and may still do it one day).

What I took away from this is that usernames are hard. And that, paradoxically, the amount of business value that I create by doing usernames correct is minimal, until it’s a vector for attack. That means that I’m far better off choosing a third party library or service that focuses on authentication than rolling my own. That third party service is much more likely to have read, understood and implemented the tripartite identity pattern (in addition to any other benefits) than I will. (If I build many systems which require authentication, then maybe I can write my own library of username checks. But then I’d be better off open sourcing it, unless it was a competitive advantage.)

Now, this doesn’t mean I should blindly use any open source authentication library. I still need to examine it, see if it is used and maintained, and determine if it meets my requirements. This is not an “open source good, roll my own bad” post.

But the default should be to find an open source or third party system when I’m working on this type of software plumbing. (For rails and authentication, devise is where I’d start.) If I look around for an hour or two and can’t find anything that meets the needs of the project (either directly, with configuration or with minor code modification), then, and only then, should I start to think about rolling my own. Yes, it’s less fun to configure a third party library than it is to roll your own, but the kind of edge cases that a third party library or service will handle make it a better choice.

This has been an issue for a long time. I still remember walking into a contracting engagement a decade ago and seeing that they had their own database pooling solution. For Java. In 2004. When Apache DBCP had been around for a few years. I’ve been guilty of this myself, often at the beginning of a project when it feels like I need to get up to speed quickly, the problem space seems simpler and sometimes I’m not as familiar with the ecosystem. So this issue isn’t going away, but this post is my plea to my future self to default to third party solutions.



© Moore Consulting, 2003-2017 +