Monday, June 30, 2008

Flexibility Is Bad Design

Ground Rules
Since this is the Internet, the land of mistranslation, I'm going to get a few things out of the way at the beginning.

Design has many meanings and contexts. For this post, I'm going to use the following definition of design:



design
noun
The purposeful or inventive arrangement of parts or details: the aerodynamic design
of an automobile; furniture of simple but elegant design.




That is, I'm going to talk about the particular design that represents a piece of application/service software.

Also, this post refers only to application/service software. Libraries have entirely different goals.

Get On With It Already
Alright, now that we're on the same page, I'm going to tell you that flexibility in application code is bad design.

The job of a programmer is to make a realization of some type of specification. There are good and bad specifications to be sure. However, the end result of all application programming should be a piece of software that does its intended job. This sounds completely logical, and many developers will pay lip service to it. But time and time again I will have a conversation with a developer who will start going on and on about flexibility for situations that might possibly happen in the future.

STOP IT!

What these developers mean by "flexibility" is that the code allows you to do something that currently has no plan to be used. Where is the flexibility in code that has every path and possible use covered by the application? That's just code that solves the problem. For these developers, true flexibility comes from solving problems that do not need to be solved.

An Analogy
In my opinion, good design is whatever results in a shipping product, using the least amount of code, in the least amount of time. This definition won't allow you to say what the best design is, but it does give you a rubric to pit two actual designs against each other. Less code is always better than more code because it will always be more readable, easier to digest, and easier to maintain. Note for the dense, I'm not talking about deliberately obtuse or obfuscated code. Least amount of time is obvious. If you aren't interested in shipping, then fiddle with your code all you want, be my guest. Most of us want this software out the door yesterday.

This definition of good design also lends itself well to a grocery shopping analogy. Everyone knows you're supposed to buy based on the lowest per unit price of an item right? If you can buy 30 apples for 10 cents a piece, and 10 apples for 20 cents apiece, then the 30 apples is the way to go right? Obviously this isn't always correct. If you are only going to eat 1 apple a day, and the apples go bad after 10 days, you're now overpaid $1 if you bought the 30 pack.

The same is true of "flexibility" in code. Since this "flexibility" in code is related to the future, that means you're only going to receive value out of it if it eventually gets used. Until then, it is dead weight. It is more code that must be read, understood, and maintained. It is a minus on the overall design because it is work spent for no gain. You could mark it as a plus to possibly be received at a later date, but then you would be building the Enron of code.

The Most Flexible Code Ever
So maybe I haven't convinced you to stop trying to write flexible code that will also make toast in the morning. I have a little secret to let you in on.

The most flexible code already exists!

Seriously, go look it up. The amazing thing about it, is we all use it everyday. That's right, it's called a Turing complete programming language. If your goal is to create the ultimate in flexible code, then I think Alan Turing, and everyone who has written a programming language has got you beat.

These guys have written code that allows you to make operating systems, databases, windowing toolkits, financial software, even the software that you are working on right now. I guess it's easy to forget that programming languages are software too.

If you think you can make a better programming language, then I would love to try it out. But please, all you architecture astronauts, let's stop worrying about the undefined future and start shipping great software.

Friday, June 27, 2008

14 Bazaar Howtos

Howto 1 - Tell Bazaar Who You Are

Bazaar will add your identifier information to your commits.

$ bzr whoami "Phil Larson <phil.larson@gmail.com>"


Howto 2 - Create Local Project Folder

This step is not technically necessary for Bazaar, but I think it is helpful. First you should create a project folder on your machine that should probably match the name of the project on the server. So I'll do something like this:

$ mkdir ~/Code/projectfoo


Howto 3 - Checkout The Trunk

Bazaar has two ways of making a "working copy." The most general way is making a branch of another branch, I will show that later. For the trunk, I find it useful to have an in sync copy of the server. Bazaar calls this a checkout, and it works similarly to a Subversion checkout. Any commits made on the working copy automatically get copied to the published branch on the server.

$ bzr checkout sftp://bzr@mysourceserver.com/var/bzr/projectfoo/trunk/ ~/Code/projectfoo/trunk


Howto 4 - Make A Feature Branch

When you want to start working on a new feature, make a branch off the trunk and give it a descriptive name. This name is local and private to your machine so you don't have to worry about conflicts or a specific naming convention.

$ bzr branch ~/Code/projectfoo/trunk ~/Code/projectfoo/featureA


Howto 5 - Make Changes On Feature Branch As Needed

Now you can make changes as usual to get your feature working.

Howto 6 - Tell Bazaar To Add, Rename, or Move

When you do anything that changes the path of the file, you should let Bazaar do it for you:
Add
This lets you add specific files to version control.
$ bzr add README.txt

Add All
This lets you add all non-versioned files to version control.
$ bzr add

Create a folder and add it
This allows you to create a folder and add it at the same time
$ bzr mkdir docs

Move/Rename
Moving and renaming is the same command, just like a Unix shell.
$ bzr mv README.txt docs/README.txt


Howto 7 - Automatically Detect Deletes

Bazaar will automatically find missing files and mark them as deleted when you commit.

Howto 8 - Commit Changes Often And Early

As you make units of changes, you can commit them on the branch with a message. This gives you a history of what you did, and the chance to roll back.

You can set up your EDITOR environment variable to have your editor launch and let you edit the commit message.

Or you can specify the message inline like this:

$ bzr commit -m 'My commit message'


Howto 9 - Merge Changes From The Trunk

As changes happen on the trunk they won't be pulled into the feature branch. To get the changes into the feature branch:

$ cd ~/Code/projectfoo/trunk
$ bzr update
$ cd ../featureA
$ bzr pull ../trunk


Howto 10 - Prepare To Merge Changes To The Trunk

First thing to do is make sure there are no outstanding changes on the trunk:

$ cd ~/Code/projectfoo/trunk
$ bzr status


Then you want to make sure you have the latest version of the trunk

$ cd ~/Code/projectfoo/trunk
$ bzr update


Howto 11 - Merge Changes Into The Trunk

When you get your feature branch how you want it, then it's time to merge into the trunk.

$ cd ~/Code/projectfoo/trunk
$ bzr merge ../featureA

This will apply the changes from the feature branch to your trunk working copy. Then you should compile and run tests on the trunk to make sure there are no conflicting changes. When you are satisfied that the merge completed successfully, commit like normal. Since the trunk is a checkout, not a branch, it will send the changes to the server so other people can access them.

Howto 12 - Publish A Branch

If you want your branch to exist on the server for whatever reason, you can push it to the server.

$ cd ~/Code/projectfoo/events
$ bzr push ssftp://bzr@mysourceserver.com/var/bzr/projectfoo/events/

From now on the url will be recorded as a push location. So in the future you can just run the shorter command to update the published branch.

$ bzr push

This branch is the same as the trunk branch, so you can make a checkout style working copy as well if you want.

Howto 13 - View Changes

If you're on a Mac and you have the Developer Tools installed, you can ask bzr to open up a FileMerge window with the current changes that haven't been committed:
$ bzr diff --using opendiff


You can also view the diff between different revisions:
$ bzr diff -r1..10 --using opendiff


Or for specific files:
$ bzr diff -r1..10 --using opendiff README.txt


For the other combinations read:
$ bzr help diff


Also there are other tools that are valid for the 'using' parameter. Some examples of supported diff tools include 'kdiff3', 'kompare', 'meld', 'vimdiff', and 'xxdiff'.

Howto 14 - Use The Docs

Bookmark the Bazaar Reference Guide

Why Bazaar?

Bazaar is an open source, distributed version control system. It's similar to git, mercurial, svk, etc. There is a lot of info on it at the Bazaar site. Plus more reasons to use it on their Wiki.

I choose Bazaar because in my opinion it has the simplest/friendliest interface of the distributed version control systems. It also has the most powerful renaming support that I am aware of, including true directory renaming. The other version control systems, distributed or not, all have major problems with renaming directories. Hopefully this means we can be a little more experimental with project organization, and if we come up with a different approach we aren't dead in the water.

Other than that, it is similar to the other distributed version control systems. If any of you are unfamiliar with the benefits of distributed version control:



From my perspective there are three major advantages of distributed version control over a centralized system like cvs, svn, sourcesafe, clearcase, etc.

Work Without The Network
The first is distributed version control allows you to work when you're disconnected. I personally got into distributed version control when I used to ride the train for an hour and a half each way to work everyday, and I wanted to work on the train. You don't have to save up one huge commit for when you get a network connection, you can commit early and commit often whenever you want. Along with full rollback, diff, and branching support. When you want to share your changes, you push them to a server.

Private Branches
The second major benefit in my opinion is that you can create personal and private branches. I always think it's better to explain programming concepts using actual code. Being able to make a private branch of a project AND still be able to do commits, merges, diffs, etc., allows me to test my ideas before involving other people or muddying up a central source repository. With a centralized system, you would have to make a branch that everyone can see, and you have to worry about naming conflicts, muddying up the source history, and explaining why you're trying some approach. Or you can choose not to commit at all, which has it's share of problems and anxiety because you can't make major changes with a safety net anymore.

Real Branching/Merging Support
The third benefit is that you can't have distributed version control without first class branching support and being able to branch at will has plenty of benefits. The way I work with bazaar is I make a branch for every new feature or set of features I'm working on. Especially in a small group environment, you can never really work on only one feature at a time. I could be working on the networking code with a broken build, and alex asks me to make a quick UI change so they can have something new to demo to a potential investor. All I need to do in that case is make a new branch of the clean/working branch and make the change. And since it's all handled by the version control system, i can then merge that change into all the in progress branches without having to think. Centralized version control systems typically leave branch and merge support as an afterthought. In your typical centralized version control system, making a branch is a big event that must be recorded and managed and has all the issues that I mentioned about private branches.