Slow is Smooth, Smooth is Fast

I think it originally comes from the military, probably the US Navy SEALs, but it’s a popular trope in the racing world, and equally applicable to software development: “slow is smooth, smooth is fast”. It’s intentionally conflicting, but it succinctly states the idea that taking the time to do something well allows you to accomplish the end goal faster overall. 

In autocross, it’s often the run that looks or feels slow that turns out to be fast. There are a few reasons why, and the allegory to development is not hard to see. A lack of excitement or surprises may seem slow, but it’s a sign of tight control and keeping within limits. Smooth, gentle, practiced driver inputs can appear almost casual in their ease. 

On the other hand, the very active driver, who is constantly manipulating the controls and struggling to maintain control and riding the very razor’s edge of traction (or past it) appears to be fast. There’s a lot going on, a lot of action, some squealing and sliding and tire smoke. But the timer doesn’t lie: these runs are not fast. They only appear fast. 

The key is separating being busy from being productive. Not only are they not the same, they’re often in direct opposition to one another. But it may be the busy team that appears productive on the surface. 

The team that fills calendars with meetings and holds war room sessions and works late nights and fixes critical bugs at the last minute looks fast. They can’t waste time on careful thought or refactoring or automation, they’ve got features to ship! But it’s the team that works their eight hours each day with no fuss and no panic, that spends time on automating everything they can, that takes steps to detect and mitigate problems early, that thinks through problems and solutions before writing code, that will accomplish the most at the end of the week. 

Urgency is not a requirement of productivity. Remember: slow is smooth, smooth is fast. 

Go for Dev & Ops

Go (or golang, as it is often called, because “Go” is a bit vague when typed into a search engine), if you haven’t heard of it, is a relatively new language for cross-platform development. It is a modern, C-style, statically-typed language that produces platform-native binaries, but still includes memory management and garbage collection.

Go is open-source, stable (currently at version 1.6, with its first stable release dating back to 2011), and it’s not going anywhere. Written by a couple of Google’s brilliant engineers, and used internally at Google at the levels of scale and reliability you would expect from a tech giant, it is an entirely different beast from something like Ruby or NodeJS. It encourages the kind of development and deployment pipeline that we should all strive for.

Software development has been moving more and more toward interpreted, dynamically-typed, single-threaded languages like Ruby and Node. It’s been moving more toward mountains of external dependencies – I’ve seen projects where more than 90% of the code was in third-party libraries. That’s a lot of other people’s technical debt and generalized implementations to absorb into your project.

Go encourages the exact opposite. It’s statically-typed, though it offers the convenience of type inference. It’s compiled, and not just to bytecode, but to native binary. It’s innately and intuitively concurrent. Its dependency management, like everything else about it, is intentionally minimalist, implicitly discouraging overuse of external libraries and frameworks.

Go, by design, at the language level, encourages a lot of really good programming practices:

  • Because the language and standard library aim for “exactly enough and no more”, developers are more likely to follow that lead with their own code. Go is the embodiment of KISS.
  • Go makes it easy and intuitive to handle concurrency through “communication instead of sharing”, keeping code cleaner and reducing the rate of defects. It also has a built-in race condition detector that can be activated when running tests or benchmarks.
  • The core Go tool chain includes support for unit tests and benchmarks, and will even include example code from your documentation to ensure it compiles and works.
  • Go has a language-level style guide, and included in the core Go tool chain is a tool (gofmt) that reformats files to fit the standard style.
  • Go omits many facets of OOP, including inheritance (though it has mix-ins), abstract classes, method overloading, operator overloading, and multi-level access control. Though useful tools in some cases, these are most frequently used to vastly over-complicate implementations. Go really wants you to just write the simplest thing that will work.

After the code is written, Go makes it very easy to set up continuous integration, including unit tests, benchmarks, linting, and test coverage. It’s trivial to have a build go on to cross-compile for every platform and architecture you might want to deploy to.

How do you deploy a Go app? Drop the executable on a server and execute it. There is no interpreter or virtual machine to install. In fact, there are no external dependencies at all unless you create them in code. Performance is excellent and resource usage is minimal – unlike, for example, Java or Ruby. The deployment footprint is about as small as it gets, and deployments are highly reliable. You suffer none of the fragility brought on by differences between versions of Java, Ruby, Python, or NodeJS – your binary runs the same regardless of the system it’s deployed to.

I won’t say that Go is perfect, or universally applicable. There are certainly use cases it is not well-suited to. For starters, Go produces console applications, not GUIs. It is not intended for building desktop applications – though there are libraries for doing so. Go also has a focus on simplicity and minimalism, and it could get difficult to manage very large code bases in Go unless you’re very careful and very smart about it.

Where Go really shines is in producing small, self-contained, single-purpose command-line tools and microservices. The Go standard library includes a multi-threaded HTTP server perfect for building a REST API server in a hurry, while still being able to stand up to production use.

What sort of things are built in Go? Let’s see:

 

A Good Case for Third Party Libraries

Developers have a tendency to over use third party libraries. They bring them in because they want some new technical advance that’s in the spotlight – ORM or IOC or AOP. They don’t stop to consider that they’re importing all that library’s technical debt and defects, along with a black box they won’t understand when it fails.

However, there are some excellent cases for third party libraries. Unfortunately, these are the same cases w where developers tend not to reach for an outside solution; cases where developers think, hey, this is easy, I’ve got this.

The best case I can think of for a third party library is functionality that is simple, well understood, and stable, but with a lot of edge cases. The canonical example is date and time handling.

Date and time handling is easy, right? You’ve understood clocks and calendars since grade school. You even grok Unix timestamps. You could do date and time handling in your sleep, with your hands tied behind your back – if you can manage to sleep with your hands tied behind your back in the first place, but that’s neither here nor there.

But wait – you wrote this software to use the user’s local time zone with no offset. Interoperability issues ensue. OK, no big deal, time zones are tricky but they’re not rocket science. You make a fix a move on.

Damn. Daylight savings time. No one hates daylight savings time more than developers. Another patch. But wait, some places don’t do daylight savings time. Another patch. Leap years. Forgot about leap years. Another patch. But they aren’t every four years – the year 2000, for example, was not a leap year. Another patch. Wait, leap seconds? That’s a thing? OK, another patch. What do you mean different people put the day, month, and year in a different order? Alright, alright, another patch. 24-hour time? No problem, patch. Wait, is midnight 00:00 or 24:00? What if someone inputs 24:05? What if someone increments a time by 10 minutes at five till midnight? Or at 1:55 the day daylight savings starts or ends? Or before a leap second is applied? What if a user is mobile and their time zone changes while they’re using the application?

Time and date are simple, every day parts of our lives. We take them for granted. We haven’t changed the way clocks and calendars work in any significant way in our lifetimes. But they’re absolutely rife with details and complexities and edge cases that are very difficult to enumerate off the top of your head – you’re bound to miss some of them. A library is perfect for this: because the functionality doesn’t need to change, a good library will be stable, with very infrequent updates, and few defects. Why kill yourself with patch after patch when there’s bound to be a solid solution waiting out there for you to use?

These are the sorts of cases where libraries are the right answer. Not for adding new bells and whistles, but for using an existing solution to a thoroughly solved problem. Character encoding is a good case. Handling any common file format is definitely a good case – XML, JSON, YAML, CSV. If I never see another hand-written CSV parser it’ll be too soon. Sorting – for Petes sake, if your language doesn’t have sorting built in, find a library. I don’t care if you learned to write a bubble sort in college. Don’t write one at work. Ever.

Anything even remotely related to cryptography you should absolutely solve with a library. Hashing, random number generation, and encryption are solved, hard problems. Even when security isn’t critical, you may as well lean on the work of other smart people.

Solved problems are where you want a library. Solutions in search of a problem may be more exciting, and come with more interesting acronyms and blog posts and conference keynotes, but they often create at least as many problems as they solve. Don’t get sucked in.

Code Reviews

“Code reviews are the worst! All the code I have to review is terrible, and people always take offense when I point out problems. And being reviewed is even worse – people always think they know better than I, can you believe it? And it’s all such a waste of time!”

It can be difficult to get a team started on code reviews, especially an established team without an established culture of reviews. Developers can be very defensive about their code, and often don’t see the value in code reviews. But the value is undeniable, and good developers will come to appreciate code reviews once they get used to them. Why?
  • Reviews reduce defects. This is the primary purpose of reviews, and they’re very effective.
  • Reviewing code builds familiarity for the reviewer. The reviewer is exposed to code they might not have worked with before, giving them a broader base of knowledge in their own development work.
  • Reviewing code improves developers ability to self-review. The more code you review, the better you get at reviewing code. The better you are at reviewing code, the better you can review your own code before you commit it. The better reviewed code is before it’s committed, the fewer defects are found in peer review, and the faster peer reviews are.
  • Expecting code to be reviewed encourages developers to self-review. Knowing that someone else is going to go over your changes after you submit them encourages you to self-review to save yourself the embarrassment, however slight, of a failed peer review.
  • Peer review improves consistency. When developers submit code without anyone else looking at it, they tend to follow their own styles and practices. As they review more of each others’ code, they will naturally tend to converge on a fairly similar set of styles and practices.
  • Peer review helps to breed a sense of collective ownership. After peer review, code is no longer “his code” or “her code” or “their code” it’s “our code”.
  • In situations where everyone is an architect – which I strongly support – peer review is even more critical. Collective design is only collective if everyone is looking over each other’s shoulders, seeing how problems are being solved, and suggesting possible alternative solutions. It really helps close the gap between a group of individuals and a true development team.
Countless tools exist for performing code reviews; the review handling built into pull requests in Atlassian’s Bitbucket and Stash is excellent, though there are many solutions, from simple things like adding a review step to your ticket workflow and putting review comments in the ticket, to using a dedicated review tool like Crucible or Reviewboard.

Never Be More Precise Than Accurate

User experience design is a tricky thing, full of tiny, seemingly insignificant pitfalls that can end up causing major frustration for users. One common pitfall is being more precise than you are accurate. The typical example uses pi: 3 is accurate, but not precise, while 3.6789 is more precise, but less accurate. Accuracy in a system is controlled by a wide array of factors, but generally you’re aware of the limitations in place and you have a general idea of your accuracy. Precision you can control directly through interface design, so you should always have it match your accuracy, never exceed it. Any estimation, extrapolation, aggregation, or rounding can introduce a loss of precision. Digital floating point math is inherently imprecise.

Users naturally presume that any number they’re looking at is as accurate as it is precise. If you show four decimal places, they assume that number is accurate to four decimal places, and rightly so. If you show numbers in millions (37M), users will assume this is accurate to the nearest million. They naturally trust you to present them with accurate information, so they assume that whatever information they’re given is accurate. This is exactly why you should ensure that you don’t present information that you don’t know to be accurate.

A Wrinkle in Time

You’ve built a prototype, everything is going great. All your dates and times look great, they load and store correctly, everything is spiffy. You have your buddy give it a whirl, and it works great for them too. Then you have a friend in Curaçao test it, and they complain that all the times are wrong – time zones strike again!

But, you’ve got this covered. You just add an offset to every stored date/time, so you know the origin time zone, and then you get the user’s time zone, and voila! You can correct for time zones! Everything is going great, summer turns to fall, the leaves change, the clocks change, and it all falls apart again. Now you’re storing dates in various time zones, without DST information, you’re adjusting them to the user’s time zone, trying to account for DST, trying to find a spot here or there where you forgot to account for offsets…

Don’t fall into this trap. UTC is always the answer. It is effectively time-zone-less, as it has an offset of zero and does not observe daylight savings time. It’s reliable, it’s universal, it’s always there when you need it, and you can always convert it to any time you need. Storing a date/time with time zone information is like telling someone your age by giving your birthday and today’s date – you’re dealing with additional data and additional processing with zero benefit.

When starting a project, you’re going to be better off storing all dates as UTC from the get-go; it’ll save you innumerable headaches later on. I think it is atrocious that .NET defaults to system-local time for dates; one of the few areas where I think Java has a clearly better design. .NET’s date handling in general is a mess, but simply defaulting to local time when you call DateTime.Now encourages developers to exercise bad practices; the exact opposite of the stated goals of the platform, which is to make sure that the easy thing and the correct thing are, in fact, the same thing.

On a vaguely related note, I’ve found a (in my opinion) rather elegant solution for providing localized date/time data on a website, and it’s all wrapped up in a tiny Gist for your use: https://gist.github.com/aprice/7846212

This simple jQuery script goes through elements with a data attribute providing a timestamp in UTC, and replaces the contents (which can be the formatted date in UTC, as a placeholder) with the date/time information in the user’s local time zone and localized date/time format. You don’t have to ask the user their time zone or date format.

Unfortunately it looks like most browsers don’t take into account customized date/time formatting settings; for example, on my computer, I have the date format as yyyy-mm-dd, but Chrome still renders the standard US format of mm/dd/YYYY. However, I think this is a relatively small downside, especially considering that getting around this requires allowing users to customize the date format, complete with UI and storage mechanism for doing so.

On Code Comments

I’ve been seeing a lot of posts lately on code comments; it’s a debate that’s raged on for ages and will continue to do so, but for some reason it’s been popping up in my feeds more than usual the last few days. What I find odd is that all of the posts generally take on the same basic format: “on the gradient of too many to too few comments, you should aim for this balance, in this way, don’t use this type of comments, make your code self-documenting.” The reasoning is fairly consistent as well: comments get stale, or don’t add value, or may lead developers astray if they don’t accurately represent the code.

And therein lies the rub: they shouldn’t be representing the code at all. Code – clean, self-documenting code – represents itself. It doesn’t need a plain-text representative to speak on its behalf unless it’s poorly written in the first place.

It may sound like I’m simply suggesting aiming for the “fewer comments” end of the spectrum, but I’m not; there’s still an entity that may occasionally need representation in plain text: the developer. Comments are an excellent way to describe intent, which just so happens to take a lot longer to go stale, and is often the missing piece of the puzzle when trying to grok some obscure or obtuse section of code. The code is the content; the comments are the author’s footnotes, the director’s commentary.

Well-written code doesn’t need comments to say what it’s doing – which is just as well since, as so many others have pointed out, those comments are highly likely to wind up out-of-sync with what the code is actually doing. However, sometimes – not always, maybe even not often, but sometimes – code needs comments to explain why it’s doing whatever it’s doing. Sure, you’re incrementing Frobulator.Foo, and everybody is familiar with the Frobulator and everybody knows why Foo is important and anyone looking at the code can plainly see you’re trying to increment it. But why are you incrementing it? Why are you incrementing it the way you’re doing it in this case? What is the intent, separate from its execution? That’s where comments can provide value.

As a side note (no pun intended), I hope we can all agree that doc comments are a separate beast entirely here. Doc comments provide meta data that can be used by source code analyzers, prediction/suggestion/auto-completion engines, API documentation generators, and the like; they provide value through some technical mechanism and are generally intended for reading somewhere else, not for reading them in the source code itself. Because of this I consider doc comments to be a completely separate entity, that just happen to be encoded in comment syntax.

My feelings on doc comments are mixed; generally speaking, I think they’re an excellent tool and should be widely used to document any public API. However, there are few things in the world more frustrating that looking up the documentation for a method you don’t understand, only to find that the doc comments are there but blank (probably generated or templated), or are there but so out of date that they’re missing parameters or the types are wrong. This is the kind of thing that can have developers flipping desks at two in the morning when they’re trying to get something done.

Engineers, Hours, Perks, and Pride

This started as a Google+ post about an article on getting top engineering talent and got way too long, so I’m posting here instead.

I wholeheartedly agree that 18-hour days are just not sustainable. It might work for a brand-new startup cranking out an initial release, understaffed and desperate to be first to market. But, at that stage, you can expect the kind of passion and dedication from a small team to put in those hours and give up their lives to build something new.

Once you’ve built it, though, the hours become an issue, and the playpen becomes a nuisance. You can’t expect people to work 18-hour days forever, or even 12-hour days. People far smarter than I have posited that the most productive time an intellectual worker can put in on a regular basis is 4 to 6 hours per day; after that, productivity and effectiveness plummet, and it only gets worse the longer it goes on.

Foosball isn’t a magical sigil protecting engineers from burn-out. Paintball with your coworkers isn’t a substitute for drinks with your friends or a night in with your family. An in-house chef sounds great on paper, until you realize that the only reason they’d need to provide breakfast and dinner is if you’re expected to be there basically every waking moment of your day.

Burn-out isn’t the only concern, either. Engineering is both an art and a science, and like any art, it requires inspiration. Inspiration, in turn, requires experience. The same experience, day-in, day-out – interacting with the same people, in the same place, doing the same things – leaves one’s mind stale, devoid of inspiration. Developers get tunnel-vision, and stop bringing new ideas to the table, because they have no source for them. Thinking outside the box isn’t possible if you haven’t been outside the box in months.

Give your people free coffee. Give them lunch. Give them great benefits. Pay them well. Treat them with dignity and respect. Let them go home and have lives. Let them get the most out of their day, both at work and at home. You’ll keep people longer, and those people will be more productive while they’re there. And you’ll attract more mature engineers, who are more likely to stick around rather than hopping to the next hip startup as soon as the mood strikes them.

There’s a certain pride in being up until sunrise cranking out code. There’s a certain macho attitude, a one-upmanship, a competition to see who worked the longest and got the least sleep and still came back the next morning. I worked from 8am until 4am yesterday, and I’m here, see how tough I am? It’s the geek’s equivalent to fitness nuts talking about their morning 10-mile run. The human ego balloons when given the opportunity to endure self-inflicted tortures.

But I’m inclined to prefer an engineer who takes pride in the output, not the struggle to achieve it. I want someone who is stoked that they achieved so much progress, and still left the office at four in the afternoon. Are they slackers, compared to the guy who stayed another twelve hours, glued to his desk? Not if the output is there. It’s the product that matters, and if the product is good, and gets done in time, then I’d rather have the engineer that can get it done without killing themselves in the process.

“I did this really cool thing! I had to work late into the night, but caffeine is all I need to keep me going. I kept having to put in hacks and work-arounds, but the important thing is that it’s done and it works. I’m a coding GOD!” Your typical young, proud engineer. They’re proud of the battle, not the victory; they’re proud of how difficult it was.

“I did this really cool thing! Because I had set myself up well with past code, it was a breeze. I was amazed how little time it took. I’m a coding GOD!” That’s my kind of developer. That’s pride I can agree with. They’re proud because of how easy it was.

This might sound like an unfair comparison at first, but think about it. When you’re on a 20-hour coding bender, you aren’t writing your best code. You’re frantically trying to write working code, because you’re trying to get it done as fast as you can. Every cut corner, every hack, every workaround makes the next task take that much longer. Long hours breed technical debt, and technical debt slows development, and slow development demands longer hours. It’s a vicious cycle that can be extremely difficult to escape, especially once it’s been institutionalized and turned into a badge of honor.

My Personal Project Workflow/Toolset

I do a lot of side projects, and my personal workflow and tooling is something that’s constantly evolving. Right now, it looks something like this:

  • Prognosticator for tracking features/improvements, measuring the iceberg, and tracking progress
  • WorkFlowy for tracking non-development tasks (the most recent addition to the toolset)
  • Trac for project documentation, and theoretically for defect tracking, though I’ve not been good about entering defects in Trac recently; it doesn’t seem worth the effort on a one-person project, though with multiple people I think it would be a must
  • Trello for cross-cutting all the above and indicating what’s next/in progress/recently completed, and for quickly jotting down ideas/defects. Most of the defect tracking actually goes in here on one-man projects right now. This is a lot of duplication and the main source of waste in my current process.
  • Bitbucket for source control (I also use Atlassian’s excellent SourceTree as a Git/Hg client.)
It’s been working well for me, the only issue I have is duplication between the tools, and failing to consistently use Trac for defect tracking. What keeps me in Trello is how quick and easy it is to add items to it, and the fact that I’m using it as a catch-all – I can put a defect or an idea or a task into it in a couple of seconds; I just have to replicate it to the appropriate place later, which is the problem.
I think the issue boils down to being torn between having a centralized repository for “stuff to be done” (Trello) and having dedicated repositories catered to each type of thing to be done (Prognosticator, Trac, and WorkFlowy); and convenience. Trello is excellent for jotting something down quickly, but lacks the additional specific utility of the other tools for specific purposes.
I think what I’ll end up doing is creating a “whiteboard” list in WorkFlowy, and using that instead of Trello to jot down quick notes when I don’t have the time to use the individual tools; then I can copy from there to the other tools when I need to. That will allow me to cut Trello down to basically being a Kanban board.

Pragmatic Prioritization

The typical release scheduling process works something like this:

  1. Stakeholders build a backlog of features they’d like to see in the product eventually.
  2. The stakeholders decide among themselves the relative priority of the features in the backlog.
  3. The development team estimates the development time for each feature.
  4. The stakeholders set a target feature list and ship date based on the priorities and estimates.
The problem here is primarily in step 2; this step tends to involve a lot of discussion bordering on arguing bordering on in-fighting. Priorities are set at best based on a sense of relative importance, at worst based on emotional attachment. Business value is a vague and nebulous consideration at most.
I propose a new way of looking at feature priorities:

  1. Stakeholders build a backlog of features they’d like to see in the product eventually.
  2. The stakeholders estimate the business value of each feature in the backlog.
  3. The development team estimates the development time for each feature.
  4. The stakeholders set a target feature list and ship date based on the projected return of each feature – i.e., the estimated business value divided by the estimated development time.
This turns a subjective assessment of relative priorities into an objective estimate of business value, which is used to determine a projected return on investment for each feature. This can then be used to objectively prioritize features and schedule releases.
I’ve been using this workflow recently for one of my upcoming projects, and I feel like it’s helped me to more objectively determine feature priorities, and takes a lot of the fuzziness and hand-waving out of the equation.

Shameless self-promotion: Pragmatic prioritization is a feature of my project scheduling and estimation tool, Rogue Prognosticator