Do it with style

Writing code that follows established style guides, using programming idioms and heeding established best practices as part of the development process can significantly improve the developer workflow and the quality of the resulting software.


Odds are that much much more time will be spent by your colleagues reading your code than time spent by you writing that code.

Consider that not only must your code be reviewed and tested by your colleagues, it will almost certainly be modified, multiple times, in the future by other developers, possibly long after you have stopped working on it.

Furthermore, as new developers join the team, they will likely read your code just to become familiar with its operation.

If you write a library that gets open sourced, your code may be read by hundreds or even thousands of other developers.

When you write code, you can save your company many more man hours by making your code easy to read and understand, than you can by writing code as fast as possible.

You can make your code easy to read and understand by following the company style, using common idioms in the programming language, and following established best practices.

Do it with style

Programming style is a set of rules established and agreed upon by a team of developers that serves to constrain the syntax of the code that is developed by that team.

When the entire team follows the style set out in an agreed upon style guide, developers immediately know how to write code, and can more easily read that code.

Good style, in some cases, can be subjective. In other cases, good style has been determined over time through experience.

What is important is that a team chooses a single style and follows that style.

Use idioms

A programming idiom is a commonly used way to write a simple block of code that accomplishes a single function.

These recurring patterns in code can be easily recognized and reused.

When idioms are used as building blocks of more complex functionality, the complexity is more easily understood.

Some languages like Ruby support diversity and flexibility as an explicit goal, whereas other languages such as JavaScript are under constant evolution and as a result support many ways to achieve the same goal.

Although this flexibility can be powerful in some circumstances, to make your code more easy to understand, it is best to stick with standard idioms unless required to do otherwise.

Learning to recognize and use idioms in a language requires that you spend as much time reading and analyzing code written by other developers as you do writing your own code.

If you take the time to learn these idioms, you will find that your code is not only more easy to understand, but you will more easily write code using these patterns.

Follow best practices

Best practices are a set of guidelines that have been developed over time and justified based on experience that aim to improve the quality, enhance maintainability, minimize complexity and improve extensibility of code.

Best practices set out the best way to develop software among many possible ways, and often only become obvious when the complexity of the code reaches a certain level.

In some cases, following best practices requires writing more code and taking more time to develop software than might otherwise be required.

Because of this, it is easy to fall into the trap of writing code in way that ignores these best practices, especially when writing code under time pressure.

However, your efforts to follow these best practices, even in the early stages of development or when implementing simple functionality will become automatic and no longer slow you down.

Put it into practice

As developers we have too many things to remember and writing functional code is already challenging as it is.

Thus it is not always easy for any of us to keep good style, common idioms and best practices in mind when writing code.

So, when you review code in pull requests, please take the time to think about these factors and make helpful suggestions based on them to the author.

Adapted from a blog post of mine on the Square Root internal engineering blog

Buy or Build: Third-party code evaluation

When tasked with implementing a new feature of any significant size, you are often faced with the decision of whether to use a library from a third party, or write your own solution. Here are a few factors that you should consider when making your choice.

The State of Development

  • How long has the library existed?
  • Is the library actively developed?
  • How often are new versions of the library released?
  • Has the library had a stable release?
  • Are breaking changes made to the library frequently?
  • Does the project follow semantic versioning?
  • Is there a published road map for future work with dates?
  • Are there pull requests that are frequently merged, or left unmerged?
  • Are there outstanding Github issues?

Library Dependencies

  • How many dependencies does the library have?
  • Are the dependencies up to date?
  • Are the required libraries of equal quality?

Quality

  • How well written is the library?
  • Does the library follow an established style guide?
  • Are code quality metrics available?
  • What is the level of test coverage?
  • Does the library have any known bugs?
  • Does the library follow industry standards?

Technology

  • Is the library based on a sound algorithmic approach?
  • What are the CPU, memory and network demands?
  • Is the approach novel, untested or well established?
  • Are there any potential security risks that could be introduced by the library?

Documentation / Ease of Use

  • Does the library have documentation, or will you be required to read the code to use it?
  • Are there learning resources such as books, training videos, or blog posts that can help you learn to use the library?
  • How long will it take you to learn the library's API?
  • Are there people on your team already familiar with the library?

Popularity / Community

  • What is the reputation of the authors for writing software?
  • How many contributors are there on the project?
  • What is the leadership model of the development team?
  • If the library is hosted on Github, how many stars and forks does it have?
  • Is the project company sponsored or are contributors paid to work on the library?
  • Is this library used in production by a companies?

Your Use Case

  • Does the library meet all the requirements?
  • Does the library provide more functionality than you will need?
  • Is the implementation efficient enough to handle your needs now, and into the future?
  • Can the library support extension in the future?
  • Are there switching costs that would prohibit moving to another library if needed?
  • Is there a license that enables reuse?
  • Does the library have licensing fees?

Adapted from a blog post of mine on the Square Root internal engineering blog

The code is only one half of a commit

Taking the time to add meaningful commit messages along with your code can create a lot of value for your team. These commit messages will help other developers review, understand and extend your code.


While either debugging existing code or adding new features that must integrate with existing code, I have often found it useful to review the Git history. Git blame gives us the commit SHA and author for each line of code in a file. Selecting the commit SHA of a relevant line of code, and then using Git log to show the related commit history can provide very useful context for the code by way of the commit messages. Ideally, the history is full of descriptive and relevant commit messages that help you to understand the motivation for the changes made to the code.

A clean commit history and concise commit messages can help other developers understand, debug and extend code.

Achieving this benefit requires an extra step in your workflow. Because it makes sense to focus on getting the code right first, I suggest that the final step in your workflow before opening a pull request is to update your commit history by rewriting your commit messages and squashing unnecessary commits.

To revise commit history there are a number of Git tools which can be useful. Git commit with the --amend flag will allow you to revise the files and commit message included in the last commit. Git rebase with the --interactive flag will, among other things, allow you to choose individual commit messages to update, as well as allow you to combine (squash) or split existing commits.

Because these tools recreate the commit history of your branch, if you have already shared the branch with a shared repository such as Github, you will need to use Git push with the --force-with-lease flag. This will overwrite your previous history on the shared repository making it available for other developers to review and use. The --force-with-lease flag helps to assure you don't accidentally overwrite someone else's commits on a shared branch. It is a best practice to only push with force to a branch that you alone are working on.

Using Git intentionally with the goal of creating clear and meaningful commit messages can be extremely useful for any developers working with your code in the future. While, like any form of code documentation, crafting it can take time, neglecting to do so will build up technical debt. Accruing this debt will gain time savings now, but will make working with your code harder and slower in the future.

The de facto standard for formatting Git commit messages is given by Tim Pope:

Capitalized, short (50 chars or less) summary

More detailed explanatory text, if necessary. Wrap it to about 72 characters or so. In some contexts, the first line is treated as the subject of an email and the rest of the text as the body. The blank line separating the summary from the body is critical (unless you omit the body entirely); tools like rebase can get confused if you run the two together.

Write your commit message in the imperative: "Fix bug" and not "Fixed bug" or "Fixes bug." This convention matches up with commit messages generated by commands like git merge and git revert.

It is important to not only explain the changes being made to the code but also the motivation for these particular changes. This is your opportunity as the code author to explain why you chose to solve the problem the way you did to all future developers. If you answer the following questions for each of your commits, your code will be easier understand, debug and extend in the future.

  • Why is this change necessary?
  • How does this change address the issue?
  • What are the side effects of this change?

Adapted from a blog post of mine on the Square Root internal engineering blog

Enterprise Failure

Developing enterprise software is a complicated and error prone activity. Expect failures to occur. As developers, the single most important thing we can do to minimize failure it to always be reducing the complexity of our software.


Being an enterprise software developer is hard. Sometimes it feels like we are placing each new feature on a leaning Jenga tower that is about to tip over and fall to the ground.

Weekly, we are tasked with adding new features to a complex system built by other people, of various skill levels, over a period of many years, always under a time constraint.

Paralyzed in our fear of breaking something, we submit the smallest possible code update that will get that feature working.

The problem with this approach is that just like in Jenga, it gets harder and harder and at some point impossible to add new features without something breaking.

Why do we do it anyway? Because, if we break something now, we know full well that accusatory eyes from around the company are on us as the responsible party.

This is wrong thinking.

Enterprise software is complex. Failures will occur. This is expected.

It is no single person's fault when something breaks; it is an Enterprise failure.

Every person in the company is responsible - developers, testers, architects, managers, vice presidents and chief executives.

However, every person has a role in preventing failure. Our role, as developers, is not simply to add new features. Our role is also to build failure resistant software.

The single most valuable thing we can do to make our software resist failure is to reduce complexity. Complex software is hard to understand, modify, extend, debug and test.

Each and every time you submit code, the overall code base should be less complex, not more complex. This is not easy to achieve. It is a constant battle. It is the crux of our job.

Through constant refactoring, conscientious design, and the application of established best practices, we can reduce complexity to do our part to reduce failures.

Don't fear failures, fear the complexity that leads to failure.

Adapted from a blog post of mine on the Square Root internal engineering blog

What did you learn today?

Being a good software developer requires you to continuously learn new languages, skills, techniques and tools. Here are a few tips to get you started and keep you learning.


Branch out beyond your existing core skills

You most certainly know how to do some things very well.

You have a programming language that you know by heart. There is a framework you always use to build websites. You have your environment and tools setup exactly the way you like.

You are productive. Being productive makes you happy. It provides a sense of accomplishment. It pays the bills.

As humans, we are naturally biased to use the tools that we know well in order to solve a problem at hand. We do this because it is immediately rewarding.

On the other hand, learning is often hard, confusing and time consuming. If anything, we are naturally discouraged from learning.

Because technology rapidly changes, the value of your existing knowledge rapidly declines.

The only way to deal with this fact is to always be putting yourself in a position that requires you to learn and use new skills.

If you do this enough, you will soon find that the act of mastering a new skill and the accompanying new found productivity will become a preferable reward.

Learn everything you can through deep immersion

The fastest way to learn a new spoken language is to go to a country where that language is spoken and learn while immersed within every aspect of the culture.

The same holds true for learning a new programming language. The fastest way to learn is to immerse yourself in the relevant programming community.

You can do that by:

* reading blog posts and books
* watching videos and listening to podcasts
* attending or speaking at user groups and conferences,
* connecting with other developers over Twitter and IRC
* reading and writing code for open sources projects
* joining a team at work already using the language on an existing project

It can be counter-intuitive and even scary to jump right into the deep end of a pool, but it really is the quickest way to learn to swim.

Copy code that other developers have written

Copy-and-Paste programmers are often derided, but every good developer has well worn copy and paste keys.

It can be really challenging to write code from scratch when using a new technology.

Instead, it is better to copy working code written by other developers, even if you do not fully understand the code.

Having a working example will allow you to tinker, test, and deconstruct the code until you can understand each piece.

While you should not copy and paste code directly for production use, it is a great way to write prototype code and learn new programming patterns.

Read, write, read, write, read, write

When you begin to learn a new language, you will most likely spend most of your time reading code.

When you begin to become proficient in using the language, you will most likely spend most of your time writing code.

Both of these situations are common anti-patterns.

You can greatly accelerate your learning by writing code that utilizes the patterns and techniques that you read about, right after reading about them.

In order to continue learning after becoming proficient, you need to read code other people have written in order to find new patterns and techniques to use in your own code.

You should always be reading as much code as you write and vice versa.

Show off your code, get feedback, revise

It is a well known psychological bias that when we are faced with a decision, we more strongly believe one choice is correct, after we have made that choice, simply because we made the choice.

Writing code involves a lot of small decisions. These facts together represents a significant obstacle to improving the code we write.

With each decision you make, you become more and more confident in the outcome, and can often come to the point of being unable to see any other way to write the code.

Because we can so easily become blind to our own code, we must get other developers to review our code and suggest alternative approaches and improvements that might be hard for us to otherwise see.

Authors never write books without editors and rewrites. Developers never write code without reviewers and revisions.

Teach in order to master

The best way to master a new technology is to find an opportunity to teach someone that technology.

There are many ways to do this, some easy, and some more involved:

* telling a colleague
* giving a demonstration
* writing a blog post
* writing documentation
* giving a presentation
* organizing a workshop
* pair programming
* code reviews

Because each of these activities will require you to spend as much time organizing your own thoughts as time spent actually teaching, you are sure to benefit as much as your pupils.

Adapted from a blog post of mine on the Square Root internal engineering blog

The Hard Part of Software Development is not the Software

Talk presented at the February 2014 Austin on Rails Meeting

I am programmer but in the tradition of Michael Weston I am a total hack. I have been programming for 25 years and in that time I have learned how to get things done, but the one thing I know is that I am awful software developer. However, I want to get better.

There are a lot of ways that I have tried to get better over the years. I learned to use new languages, new frameworks, new APIs, new patterns, new libraries, new tools. All of these things helped me get stuff done.

Unfortunately, none of these things have really made me a better software developer. The one thing I haven't done much of is develop software as part of a large team. I think we all can understand that there are a lot of benefits to working with a team on software including:

  • Accomplish big and complex projects
  • Opportunities to learn from each other
  • Camaraderie is motivating
  • Someone to help you out when you make a mistake

So about 6 months ago I joined PeopleAdmin as a Ruby Developer. PeopleAdmin is a company that provides HR solutions to Universities using Software as a Service Model. We have a very large and complex Rails codebase that is 7+ years old and we host terabytes worth of data. The Engineering team consists of about 25 people. It is a top notch team and I'm honored to be part of it.

Based on all of your experiences, you probably roughly already know what takes to makes a good team; knowledgable and reliable people, good communication, trust and respect, and ownership. It's probably an uncontroversial statement that being a good team member is a very important part of being a good software developer, but working with other people can be hard and sometimes things go wrong, very wrong.

There are many reasons for this including:

  • Some people seek individual recognition / gain
  • Being polite is hard, it takes extra effort
  • All you really care about is the software
  • That person you just naturally do not get along with

So I want to tell you two stories from my experiences at PeopleAdmin that demonstrate lessons that I have learned from the mistakes that I made working with the team. They center on these two themes, recognition of excellence and empathy for failure.

Recognition of excellence

So when I first joined peopleadmin, one of the other developers was wrapping up a project getting it into production. He had used a new language Go and a SOA approach to solve a problem that had been a sore spot in the product for a long while. It improved our throughput and added additional functionality to our application which was a big win.

The one thing I noticed was the heaping helping of praise he received over and over from the team. At the time I did not think, "oh he did great work". I thought "I would love that to be me receiving the praise". I took a cursory look at the work and thought "I can do that". And honestly I do not even think that I complemented him on what was actually really excellent work.

Since starting at PeopleAdmin I've been working on a large project that is nearing completion now. At a recent demonstration of the project, I received a heaping helping of praise. That was a really good feeling. However, a new junior developer made an offhand comment in passing that made me think he didn't appreciate the complexity of the problem or value the hard work I had put into creating a solution.

And it clicked. It was only then that I realized the mistake I had made in judging the value my colleagues work from before. I underestimated the amount of work and complexity of the problem from the outside looking in. It looked simple. One take away is that we are naturally biased to think simple things are simple to create.

Another take away from the story is that recognition of excellence is not a zero sum game. This has always been a hard one for me to wrap my head around and I think it's a natural bias to believe that recognizing someone else's excellence and your own excellence are mutually incompatible. I think that is partly because the competitive nature of our society so that bias is built into the DNA of a lot of us.

Although it might be natural to compete with your team mates, it is actually counter productive. One of the great benefits of being on a team is their support and praise. You need to do the same.

Empathy for failure

Second story. Early on in my time at PeopleAdmin, one of the developers committed code that broke the build. They sheepishly admitted to it and went about fixing it. And I thought "that was a silly mistake, they should have been more careful" and I may have downgraded my perception of the developer's skills. I was new, trying to get a feel the skill levels of the various developers on the team.

Shortly thereafter, I am 90% sure that by messing around with something I knew little to nothing about, I corrupted our staging environment. This caused a mountain of extra work for the team and a delay to all our QA work in progress. I was thinking through all the things that set me up to fail, excuses and such.

What I realized was that I exhibited the fundamental attribution error. It is a well known and pervasive psychological fact where we tend to attribute the cause of the failure to the actor's shortcomings more frequently than the situational factors that lead to the failure.

However this only hold true for judging others, not yourself. We overwhelmingly attribute our own failures to situational factors. This is the actor/observer bias.

For example when you see someone trip, you think they are clumsy, but when you trip, you ask who put that in my way?

A more relevant example, when you see a bug, it is easy to say, "who's the moron?" rather than "oh man, this is a really complex system we're working on".

Take aways

  • Recognize excellence freely because creating simple things is hard
  • Have empathy for failure because failure is, more often than not, due the circumstances surrounding the failure

Internalize these and you will be a better team member and thus a better software developer!