Monthly Archives: June 2012

Make a Dent

Warning: motivational-speech blog post to follow.

Summary: Follow your passion, don’t waste time on stuff that doesn’t matter, accept and embrace death as a positive force.

Fear

There’s not enough time in life for you to be understood 100% of the time. You will be misjudged. On the other side of the coin you’ll also be judged accurately and it will sting. The alternative is to never make an attempt and be forgotten.

Focus

When you get offered a ton of money to do something that doesn’t align with your passion, will you take it? If pressured to go against your principles, will you rock the boat, potentially at the expense of your short term stability? Perhaps less dramatically, will you know what to say no to in order to focus on what really matters?

You’ve got to be able to say no. It’s not easy, but saying no is the best way to minimize the number of things you’ll regret later on.

Inevitability

You have to know that someday you will die, and everyone else will too. If we all die, what makes us special? The artifacts that we produce are the only way for us to leave a mark. We live for an insignificant blip of time, and so far there’s no escaping that. Given that, there’s no reason to settle. In fact it’s quite dangerous to settle because you’ll run out of time before you know it. The most precious resource on earth is not gold, silver, or diamonds; It’s time. There’s a good quote from Carl Sagan that’s applicable:

“The universe seems neither benign nor hostile, merely indifferent.”

So death isn’t a bad thing; it’s a reminder and a driver for you to get focused and do what you love to do, right now, and not waste a second doing things that don’t matter.

“We’re here to put a dent in the universe. Otherwise why else even be here?” —Steve Jobs

Respect Among Software Developers

Software Developers are really smart people, and that’s good. Unfortunately, there’s a subset of software developers who have a bit too much pride in their abilities, and compete with others as a way to convince others (and themselves) that they’re the smartest. It’s important for them to prove their superior abilities to you.

It’s too easy to view someone else’s code as being of poor quality, and convince yourself that you’d know better. It’s a lot harder to understand what circumstances caused the code to be in the condition that it’s in. It’s a lot harder to recognize intelligence in others.

Don’t Suffer Jerks

This is really important.

Gifted developers who have accomplished a great deal can sometimes be very difficult to deal with. You don’t have to look far to see examples of this:

Often this type of person is in a position of control. Sometimes this can be referred to JDD (Jackass Driven Development).

I’m sure you’ve seen it before. Usually this person is the one making all the big decisions, and who can break the rules because of his status. Usually this person has job security, because they are the only one who knows about thing X in the system, or is the only one who can fix thing Y when it has a problem. He’s the first one to point out problems, but never the first to point out a better solution. He’s the one everyone has to tip-toe around because of his superior status in the eyes of upper management. It seems like most organizations have one of these.

Don’t suffer this kind of person.

They aren’t as necessary as they might seem. Remove your dependency on this single-point-of-failure earlier rather than later. If you don’t, the organization will get slower over time as the paralysis of the dependency set in. I’ve said it before but it’s worth repeating: One gifted ‘hero’ programmer is not as important as having an entire team of average-to-good developers who can work together.

Alan Turing

Today is the birthday of Alan Turing (1912 – 1954), who is considered to be the father of computer science. He was the first to define the idea of a stored program that an imaginary computer could calculate (this was 1936).

During World War II he developed the code breaking scheme that cracked the German Enigma machine.

He developed the Turing machine, which is a state machine that:

  1. Has a finite set of states, including a start state and current state.
  2. Reusable storage for reading/writing.
  3. A defined way to change state.

A language is said to be ‘Turing complete‘ if it can meet the above criteria, and therefor produce the result of any calculation.

He was chemically castrated in 1952, because at that time homosexuality was illegal in the United Kingdom. He died 2 years later by ingesting a cyanide-laced apple.

Just Throw More Bodies at the Problem

Fred Brooks authored a book in 1975 called ‘The Mythical Man Month‘. In it, he argued that adding manpower to a late software project makes it later. The core of this belief has been captured in Brooks’s Law:

It takes some time for the people added to a project to become productive. This is known as ‘ramp up’ time. Software projects are complex engineering endeavors, and new workers on the project must first become educated about the work that has preceded them; this education requires diverting resources already working on the project, temporarily diminishing their productivity while the new workers are not yet contributing meaningfully.

Communication overheads increase as the number of people increases. The number of different communication channels increases along with the square of the number of people; doubling the number of people results in four times as many different conversations. Everyone working on the same task needs to keep in sync, so as more people are added they spend more time trying to find out what everyone else is doing.
(Source)

Why do these death marches happen in the first place? These are some common reasons:

  1. Unrealistic expectations or timelines.
  2. Poor communication between developers and stakeholders.
  3. Overly optomistic feature scope.
  4. Lack of understanding about the problem being solved for.
  5. Inappropriate resources for the job.

The effects of this on the developers can lead to burnout, and a higher rate of bugs introduced into the system. Particularly challenging for the developers are when new ones are added to the project, because they’ve got to split their time between standard development and helping newcomers ramp-up.

There are some tactics that can be implemented to mitigate the impacts, but preventing the problem from being introduced in the first place is a management challenge. Some tactics that can be taken:

Iterative Development

Developing features iteratively and hitting smaller milestones works better than trying to hit a deadline far in the distance. The cone of uncertainty grows the farther out the deadline is. Shorter bodies of work are easier to estimate, and demonstrate progress towards a goal. In some places, this model of not necessarily having a hard deadline, and just developing iteratively/continuously can be a hard culture change to make.

Separation of Concerns

Separation of concerns is important to developing maintainable loosely-coupled software, but it’s also a valuable management technique. Having small teams with a focused ownership area can reduce the ramp up time and reduce the overhead involved with many developers. It’s important to remember however that the segmentation should not impeded cross communication between teams. The segmentation is only intended as an abstraction tool to limit the amount of information any one developer needs to hold on to. All developers should feel free to deal with any area of the code base.

Don’t Rely on Hero Programming

Sometimes an organization will find itself with a few developers who carry most of the weight, and become almost a sort of single-point-of-failure. Fostering this behavior will result in a dangerous situation in which you depend on a small number of individuals, as well as cause chafing between them and the ordinary body of developers. It’s not as important to have superstar programmers as it is a large pool of developers who can work together efficiently.

Summary

Even though this has been proven time and time again, death marches are still common in software development. They often involve a ‘home stretch’ of unsustainable work, in which poor management practices lead to the belief that throwing more bodies at the problem will allow the software to be shipped sooner. Obviously, if we assume Brooks Law is valid, this is false.

Maintainable Software and Premature Optimization

Software should be maintainable. Software should also be performant. Which is more important? Well, as it turns out, in order to optimize software for performance, it must be maintainable. Ease of change can easily be the most important factor in making something run well.

Premature Optimization

“In which everything is possible but nothing of interest is easy.”
– Alan J Perlis

Optimization up front often hinders evolution, because it’s designed to address a very specific concern without regard for future concerns. This is not to say that optimization is not important, it’s just something that should be done in such a way as to not hinder the ability to respond to change. Also, today’s compilers are a lot smarter than you are and can perform lots of optimizations themselves. Sometimes you simply aren’t smart enough to know where the bottlenecks occur, so it’s important to not optimize until you’ve actually proven via measurement where and why a performance issue occurs.

Programmers are really smart people, but unfortunately many programmers take pride in their ability to develop and understand complicated code. This is a danger that must be understood and avoided; particularly when it results in less maintainable code, or code in which only that single developer is capable of understanding and maintaining.

YAGNI

You Ain’t Gonna Need It. Resist the urge to optimize or implement functionality until it’s needed. This simple idea is actually the basis for much of agile software development. 90% of the functionality developed and shipped quickly is better than 100% of it shipped late or never. Why should you hold off on optimizing or implementing until it’s needed? The simple truth is that you don’t know what will be needed down the road, and so developing for it now will be a waste of time. Often times it turns out the code you prematurely wrote isn’t even needed, or your assumptions were wrong. So not only will you not need it, but even if you do, it won’t be in the right form that you are anticipating today.

 

Clarity and Explicitness

Writing code that’s clear and explicit is better than writing code that’s clever. Programmers are really expensive, so it’s to your benefit to write code that optimizes for their time, and the way to do that is to write code that communicates to people, not the machine. Write the code so that it can be understood now and in the future with little or no additional explanation needed about how it works.

Delete Code

Everyone has probably seen Andy Hertzfeld’s story of Bill Atkinson during the development of MacPaint:

In early 1982, the Lisa software team was trying to buckle down for the big push to ship the software within the next six months. Some of the managers decided that it would be a good idea to track the progress of each individual engineer in terms of the amount of code that they wrote from week to week. They devised a form that each engineer was required to submit every Friday, which included a field for the number of lines of code that were written that week.

Bill Atkinson, the author of Quickdraw and the main user interface designer, who was by far the most important Lisa implementor, thought that lines of code was a silly measure of software productivity. He thought his goal was to write as small and fast a program as possible, and that the lines of code metric only encouraged writing sloppy, bloated, broken code.

He recently was working on optimizing Quickdraw’s region calculation machinery, and had completely rewritten the region engine using a simpler, more general algorithm which, after some tweaking, made region operations almost six times faster. As a by-product, the rewrite also saved around 2,000 lines of code.

He was just putting the finishing touches on the optimization when it was time to fill out the management form for the first time. When he got to the lines of code part, he thought about it for a second, and then wrote in the number: -2000.

I’m not sure how the managers reacted to that, but I do know that after a couple more weeks, they stopped asking Bill to fill out the form, and he gladly complied.

This is a great example to follow when considering YAGNI. Not only should you resist the urge to prematurely optimize or develop, you should also aggressively remove unused or unneeded code.

Solutions?

How do you protect your code base from complexity and premature optimization?

The only real solutions here are as follows:

  1. Hire developers who understand YAGNI
  2. Hire developers who understand that a primary goal of their job is to use their code to communicate to other developers instead of the computer.
  3. Encourage a culture that understands that simplicity is better than complexity.

I’ll end with the same quote everyone slathers around the web, because even though it’s repetition is common, it’s still true.

“Premature optimization is the root of all evil.” –Donald Knuth

Technical Debt

In software development, there is a concept of ‘Technical Debt‘. The original term was coined by Ward Cunningham, and the idea is that if you cut corners in the short term, you’re borrowing against the future maintainability of the software and that at some point, not unlike a credit card, you’ll pay down that debt by going back and fixing the hacky solutions that were put in place.

“Just do it quickly, we’ll refactor it later”

The problem is that the likelihood that a team will go back and actually keep their promise to refactor it later, is slim. When the realities of development pressures and deadlines come in to play, the time (and ability to remember) to go back and refactor is destroyed.

The eventual consequence of not paying down the technical debt is that the software will become harder to maintain, the architecture (or lack of) won’t evolve easily, and it makes it a lot harder to add new features and resolve bugs. If you take on too much technical debt and max out your borrowing limit, the software will rot.

Now, I think there is a balance to be drawn; Sometimes you do want to put a solution in place with the intent to refactor it later. Business pressures and management decisions can cause you to focus on the short term wins of getting a solution out quickly, and that’s a reality that you’ve got to be prepared to deal with. The difficulty lays with being disciplined enough to go back and keep your promise to improve and iterate. In my experience though, taking on technical debt will almost always make you lose time in the long run. This is not something specific to software development, and there are parallels to cutting corners in other lines of work.

Be disciplined about paying down your technical debt.