Distributed Version Control and Other Religions

Lately it seems there’s been a lot of talk about distributed version control systems — especially git and Mercurial — and how they’re the bee’s knees or possibly even the cat’s pajamas.

But at the risk of having my programmer’s license revoked, I have to confess I don’t really care about version control systems. I mean, I think it’s important to use version control, but I don’t get all excited about the latest ideas in version control technology or the newest VCS on the block. It’s just a tool. It keeps versions of all my code, and allows me to revert to previous versions, see when and how things changed, and collaborate with other programmers working in the same codebase. Beyond that I don’t much care.

The tools don’t make the programmer.

What’s new with DVCS is the proponents seem to think they need to evangelize their system. Unfortunately they rather suck at it, and their arguments usually leave me feeling that I don’t want to use software used by such jerks, on account that it might make me into a jerk. Or at least a bigger one.

However, I do think that a DVCS can be a really useful tool so I’ve come up with some suggestions for those wanting to effectively evangelize their favorite version control system, or at least annoy me less when they talk.

  1. Don’t be condescending or insulting

    I think it’s part of human nature — or at least programmer nature — to assume you’re the smartest guy in the room, and think that anyone who disagrees with you is a real buffon. Programmers seem to take great pleasure in showing that the other person is an idiot, or didn’t know something they did, or is at least not as clever as they are. A lot of arguments for git or Mercurial seem to revolve around explaining how git or Mercurial are so clearly superior that only morons would use something else.

    While this works great for rallying the troops, it’s counterproductive when trying to win someone over to your side.

    Think of it this way: suppose someone comes to your door to tell you about their religion. During the discussion they are self righteous and condescending; they don’t listen to your arguments, but are only interested in proving that they’re right. Are you likely to be swayed to believe in their religion? If you’re like the other hairless bipedal mammals inhabiting this planet you won’t be, even if they had some valid points.

    As soon as you become insulting or condescending, your arguments will be rejected out of hand. I know this will upset some programmers because they believe if you show your argument is superior, everyone will accept it. But that’s not the way people work.

  2. Try to be helpful

    The best way to introduce someone to your DVCS is by trying to help them. Not in the “I have all the answers” way, but in the “I’ve dealt with that before, and here’s what I did” kind of way. People will run into the kinds of problems that DVCS are good at solving. When they do, you can helpfully suggest a solution.

    However, some care should be taken so the suggestion doesn’t come off the wrong way.

    Wrong Right
    Dude, why are you using subversion? I’ve run into that problem before. I solved it by using feature X of git/hg in this way.
    Dude, just use git/hg. You smell nice.

    Be aware that people may not know where their pain points are. I’ve seen customers jump through some excruciating hoops to get a piece of software to do something when there was an easier way. People get used to pain and begin to assume it’s normal. If you notice something like that, even if they’re not complaining about it, you can politely suggest a better way.

    Instead of a list of features that a DVCS provides or abstract arguments as to why they should be using it, people respond better to concrete examples of how a piece of software can make their lives better. People are also more responsive when they know you’re on their side, trying to help them, even if they don’t — or currently can’t — take your suggestion. Keep in mind switching VCS in the middle of product cycle is likely something most people can’t do.

    The right attitude is that of trying to help a friend, not conquer an enemy.

  3. Be willing to answer questions, even dumb ones

    Distributed version control works differently from centralized version control, and it does require a different way of thinking. I know I was confused by it when I first started looking into it. A lot of tutorials jump into the mechanics of how to perform certain tasks, but rarely talk about the philosophy of the system or why things are the way they are. If you want to successfully persuade people that your DVCS is the best then you need to be willing to do a lot of patient education.

    I say “patient” because after using centralized version control they might have difficulty switching over to a new mental model. Or they might have heard a lot of FUD about your DVCS that you need to put to rest. It’s important to do this patiently, respectfully, and not insultingly because they’ve picked up misinformation or don’t immediately “get it” like you do. Otherwise they might ignore your DVCS so they don’t have to deal with people who look down on them because they don’t “get it.”

  4. Make it trivial to install and use

    This seems like a no brainer, but it is an important part of any software. If it’s hard to try out and use your DVCS, it simply won’t get used. I think that for the most part both git and Mercurial succeed in this respect. My only complaint is neither has a good Mac GUI client. Contrast that with Subversion which has both Versions and Cornerstone on the Mac. You shouldn’t underestimate the draw of an easy to use, beautiful GUI.

I think Joel Spolsky has given the best example of how to properly promote and evangelize a DVCS. He wrote a blog post — Distributed Version Control is here to stay, baby — about how he came to learn and use DVCS. It’s well written, and instead of condescending, he’s actually humble and admits he was wrong about DVCS to begin with. Joel also created a site called HgInit that does an amazing job of explaining the philosophy behind Mercurial and gives a solid introduction to right way to use it. It’s actually the site that convinced me to start using Mercurial for real.

Redesigning a Software Contractor's Website

It’s been about eight years since our company website has had a major redesign. But that changed today.

The old design simply wasn’t meeting our needs. Specifically:

  • It didn’t communicate clearly what exactly we do here.
  • It had a search box which, as far as I can tell, didn’t, and has never, worked.
  • It had several pages describing services we don’t perform, at least not when a cop is around. Some of these pages just had boilerplate text in them. e.g. “Item 1″, “Item 2″, etc
  • The visual design was really old and unprofessional. The new is at least not old.
  • The old feedback form demanded a lot of extraneous information like title, company, telephone number, home address, when you shower, etc.
  • It had a copyright date at the bottom of 2002, which caused people to ask: “Are you guys still in business?” This was apparently a barrier to them sending us money.

Fortunately, we mainly rely on word of mouth to get clients, but a bad website certainly doesn’t help our business. We could be missing out on clients who find our website, but don’t contact us for any of the reasons listed above.

I’ve recently had some time between contracts, which I used to think about how a software contractor’s website should be structured and what kind of information it should present. Also, I slept in late a lot. I came to some conclusions:

  • It should immediately obvious to a visitor what the company does, no matter what page they land on.
  • It should have a portfolio so the visitor can see what kind of work we have done in the past, and see if that matches up with what they want done at the quality level they want.
  • A brief description of services that we do provide, explained in layman’s terms.
  • It should be obvious and easy to get in touch with us. The form for submitting a message should have as few requirements as possible.
  • It should contain a brief overview of the company, and the people in it. It should put a human face to the company.
  • Noon really is not a bad time to wake up.

I also decided to add a page for products, mainly for future use.

Overall the project was a fun — and hopefully financially rewarding — exercise. It was interesting to think about what would induce a visitor to stick around on our site, and then actually contact us. I’m not sure if I got it completely right, but it’s at least a step in the right direction.

Compiling OpenCL Kernels with Xcode

The talk I’m working on for NSConference 2010 involves a decent amount of OpenCL kernel code. Originally, I thought I would develop the kernel code the same way I develop Core Image kernel code: build the kernel in Quartz Composer and then copy paste the code into Xcode when I got it working.

Unfortunately, I’ve not had much luck with Quartz Composer in way of meaningful compiler errors. Sometimes it returns good errors, sometimes inscrutable ones.

Quartz Composer

Composer: Wait, wait, I remember this… it’s COBOL, right?

 

However, I’ve found debugging OpenCL kernels to be much easier thanks to the invention of a function I like to call “printf.” If you run your kernel on the CPU, then you can print out values just like in C. With debugging solved, I just needed to figure out how to find compiler errors without having to run my code.

Unlike Core Image, OpenCL actually requires you to compile your kernel code explicitly before using it. The API’s required to do this will return nice compiler error messages and everything. The obvious thing to do would be wrap up these API’s in a command line tool and invoke the tool from Xcode, which is what I did.

The Code

You can download the Xcode project for clc, the OpenCL Compiler here. It requires Mac OS X 10.6 Snow Leopard and the associated Xcode tools. To install, just build the project and copy the resulting binary into your path somewhere. I used ~/bin.

Most of the code is self explanatory, with the possible exception of the output. Unlike most compilers, clc doesn’t output object code because the host and runtime CPU/GPU’s could easily be different. It could simply copy the source code as is for the output, but that was a little too obvious for my tastes. Instead clc compresses the source code and stuffs it into a binary plist. It has the slight benefit of potentially being smaller on disk, and making your source code negligibly less accessible to prying eyes, if you’re into that sort of thing.

There are definite possibilities for improvement. For example, there could be an option to encrypt the source code to be more “secure.” Or it could store the binary code generated by the host machine in the output on the chance that the host and runtime machines have the same hardware.

Setting up Xcode

To use clc, you’ll need to set up a build rule in your app’s target settings to run all OpenCL source files through it. Selecting the menu item Project > Edit Active Target, and then selecting the Rules tab, should land you here:

TargetSettings.png

Add another rule, set it to process OpenCL source files using a Custom script. For the custom script enter:

~/bin/clc ${INPUT_FILE_PATH} -o ${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Contents/Resources/${INPUT_FILE_BASE}.clar

Finally, you’ll need to tell Xcode where you’re putting the output file, which is:

${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Contents/Resources/${INPUT_FILE_BASE}.clar

By default, Xcode won’t put OpenCL source files (.cl) into the target, meaning they won’t get compiled. For each of your OpenCL source files
you’ll need to explicitly add them to your target. There are several ways to do this, but the easiest is probably selecting all of them, and doing a Get Info (File > Get Info). Switch to the Targets tab and check the target they should be compiled into.

Runtime Code

At runtime, it’s pretty easy to retrieve the original OpenCL source code using the + (NSString *) openCLSourceWithData:(NSData *)data error:(NSError **)error; method on ONOpenCLArchive. However, there are a couple of convenience methods on NSBundle that makes retrieving the kernel easier. For example:

#import "ONOpenCLArchive.h"

NSString *kernelSource = [[NSBundle mainBundle] openCLResource:@"MyKernel"];

That’s pretty much all there is to it.

Conclusion

Although not ground breaking, this little tool has certainly been helpful to me by finding compiler errors at compile time instead of runtime. Hopefully it will be useful to other people as well.