Code Name Velocity

4 June 2008 –

At TechEd 2008 (which unfortunately I was not able to attend, but a few colleagues are providing me continuous updates), Microsoft announced a lot of things that are really important to me. New breakthroughs in voice recognition are always cool, but I am a web guy at my core so that's what turns my crank.

I have a few side projects that need a distributed in-memory cache. These projects are all in .NET so my obvious choices were SharedCache, ScaleOut StateServer, NCache or memcached Win32 with one of several .NET clients. Memcached is a lot more free than the latter two and more well-regarded than the first, so last week I started a little personal project of porting memcached to .NET. My C is pretty rusty but relatively speaking memcached is pretty simple, and it seems like a managed version could perform quite well. Since I know c# better than English, it makes enhancements and customizations to my caching layer much easier.

Thankfully I didn't burn too much time on memcached.NET before Microsoft announced Velocity - a distributed cache written to natively support the .NET stack. After digging in to the CTP code, I came away very impressed. In the past I've viewed the caching layer of an application very simplistically from a usage perspective - a persistent dictionary of keys and frequently used objects. Distributing it across multiple machines adds complexity to the service but not the consumers. Velocity has some features with huge implications in the kind of value a cache can deliver:

  • Lookups by tag. This means one thing to me: multi-dimensional object keying. No more ugly pointers or multiple copies of an object per key. This increases the value of the caching layer by orders of magnitude over a simple key-value pair table.
  • In-process storage. With a typical cache service, our cache will store a serialized copy of User::Bob in memory. Bob is very popular in our application, so his user object is deserialized into the application process on almost every request. This is wasteful and contributes to memory pressure since we are essentially storing the same object at least twice - sometimes more. In-process storage allows heavily used items like User::Bob to stay in the application process space instead of being serialized to the cache service.
  • OOTB Session Provider. Velocity includes a SessionStateStoreProvider implementation out of the box. A high performance, high availability state server for free without putting any pressure on your SQL box (which is probably why you are considering Velocity in the first place).
  • Atomic operations & concurrency management. Optimistic locking with versioning opens the door to much more sophisticated functionality than would otherwise be practical with the typical pessimistic locking. I predict applications that are able to align themselves with actual usage patterns much more intelligently.

As I noted in the beginning, memcached is pretty simple. And as my short list of highlights suggests, Velocity is anything but. Although memcached and Velocity solve the same problem - offloading high-volume requests from the data tier to an in-memory intermediary - they serve surprisingly different purposes. Scott Watermasysk summarizes the distinction neatly:

On one hand you have Memcached which treats the cache as something you should never rely on. It is there to help but you should always assume it is going to fail on you and even more importantly (to Memcached) you should accept that as a fact. If you read the Memcached FAQ you can almost here the author laughing when talking about fault tolerance. On the other side of the fence you have features like replication and high availability.

The practical implications are significant. What kind of service are you running? What kind of data are you moving? Who is your audience? These are very high level architectural questions that help shape whether to go with a memcached-like solution or a Velocity-like solution. Jim Benedetto, in an interview with Baseline Magazine, described MySpace's answer to these questions:

100% reliability is not necessarily [the] top priority. "That's one of the benefits of not being a bank, of being a free service"...on MySpace the occasional glitch might mean the Web site loses track of someone's latest profile update, but it doesn't mean the site has lost track of that person's money. "That's one of the keys to the Web site's performance, knowing that we can accept some loss of data"

Usually my default reaction such an idea is "no way!" Loosely coupling system components to the point where data in one layer might not make it to the next layer every time makes me feel very uncomfortable. Embracing discomfort is necessary for growth though, so let's give it a big bear hug and dive in. The original purpose of memcached was to support LiveJournal. In this environment, a failure rate of the caching layer might just mean an extra few round trips to the database. As long as the caching layer works some of the time, we still see a benefit. But then issues start to get sticky. What if the failure comes when we try to invalidate a cache item because a journal post was updated? The old version will be exposed to the public longer than intended. Is this acceptable behavior? Obviously I don't know the answer to that for LiveJournal's case. But the point is significant - how does reliability affect the business value of your application? For MySpace, responding promptly to a hundred million requests and failing a percentage of those delivers greater value than rolling service brownouts or throttling everyone.

Ultimately, the Velocity announcement has brought these questions to the forefront of my mind. I'll be relaxing in Ireland for the next week and a half, but I'm sure I'll be thinking about how to answer these questions for my apps. Make sure to do the same for yours.

Procrastinate Whenever Possible

8 May 2008 –

Wil Shipley has a lot of wisdom in the arena of software development. And he regularly backs up his advice with results that prove him right. There is one particular theme of his, however, that really sticks with me:

START WITH BREVITY. Increase the other dimensions AS REQUIRED BY TESTING.

He actually takes his time to elaborate on the justifications and implications of this advice, culminating in an oft-linked-to post that is really worth reading. The first time I read it I thought it sounded nice, but it didn't quite *click*. It took about 6 more months of fumbling through base classes that I haven't implemented and interfaces that only get used in one place before I punted.

Class design checklist - bad

When you are handed a problem, if your first thought is "I will need a base class that does x and probably an interface for y" you are creating extra work for yourself. Writing abstract classes first is, very literally, solving problems that don't exist. When you're writing code, you don't have a problem until you are calling a method that doesn't exist, or doesn't do what you need. No programmer, no matter how good, can accurately predict what calls he will be making from hypothetical classes before they are written. Even if you have a complete class diagram for your entire application (and if you do, why didn't you spend that time writing the code?), it will be wrong. You will have to make changes as your ideas break on the rocky reality of implementation.

Many programmers, when they create a new class, add a ton of features to that class to make it "complete" -- that is, they try to anticipate everyone who may ever use this class, and they add methods that those hypothetical users may want...you may be saying to yourself, "What's wrong with flexibility?" Strangely, I was about to tell you. The problem is YOU ARE NOT A LIBRARY PROGRAMMER.

Class design checklist - good

What Would Wil Do? "Start with brevity." Break the tasks into easily defined units of functionality, and take the first item off the list and code it concretely. Only build what you need to make that functionality work. After you encounter code that can be shared, write your base class. After you hit a problem that can only be solved with an interface, stub it out.

If you just wrote public abstract and you don't already have a class written that will be inheriting from it, stop right there. Backspace over that abstract keyword and start building your concrete implementation first. Put off best practice 'till tomorrow for what you can get working today. I guarantee you will have a more stable, maintainable product in the longest run, and you'll ship sooner.

This all is not to say that you should not have good design to your software. A good architecture is invaluable and irreplaceable. In a later post, I'll elaborate on design approaches that can be built in as your code takes shape, without burning time creating a base library instead of getting things done.

Finding the Right Domain Name

10 April 2008 –

Recently Jeff Atwood wrote about his startup's struggle to come up with a good name:

I've been brainstorming names for the web site we're building. I've surveyed some of the finest minds in the software developer community (for very small values of "fine"), and we've come to a collective realization: naming a website is hard. Really, really hard.

No kidding. This isn't just true of websites, or even of companies, but of ventures in general. That's why there are firms that charge tens of thousands of dollars to do it for you. And it's hard to blame them - would BlackBerries be quite as popular if they were called LeapFrogs instead?

But Jeff shoots himself in the foot from the beginning by (almost) eliminating any name that isn't available as a .com. Anyone reading this has some inkling of the sheer volume of domains that have already been registered, and no guess at what percentage of those are squatted would be too cynical. When practically every common and obvious .com name is already taken, companies have to resort to more and more contrived names just so they can say they have theirname.com. But is it really worth it?

In their book Getting Real, 37signals discusses their emphasis on names that make sense:

Give your app a name that's easy to remember. A big mistake a lot of people make is thinking their app's name needs to be ultradescriptive. Don't worry about picking a name that vividly describes your tool's purpose; That usually just leads to a generic, forgettable name. Basecamp is a better name than something like Project Management Center or ProjectExpress.

The name should be simple, with a blend of familiarity and uniqueness - Basecamp, Campfire, Backpack, etc. are all familiar word-phrases to English speakers, but are unique enough as product names to stick. Here's the really interesting part - they don't have the .com for any of those products. Basecamp is basecamphq.com; Campfire is campfirenow.com; Backpack is backpackit.com. 37signals doesn't exactly need publicity by now, but they weren't always known. How did they violate the common domain name wisdom and still succeed?

Jason et al recognized something that most of us just can't seem to get past: the precise domain name really isn't that important:

[D]on't sweat it if you can't get the exact domain name you want. You can always be creative and get close with a couple of extra letters

They looked past appearances and went straight for use. How do people use domain names? If you have a great service, people are going to

  • Bookmark it
  • E-mail it
  • Twitter it
  • IM it

What people will almost never do is try to remember the service by name and retype the address from scratch. At worst, they will Google it, which should be easy because it's an easy, short, memorable name. In every case, it doesn't even matter what the domain name is. Your users will never have to remember it or type it. People love or hate 37signals for one reason or another, but I've never heard of anyone begrudging them or their services because their domain names are slightly off. If a service is delivering value, the particular domain name just falls into the background.

Ultimately, I think people get too caught up in selecting "the right" domain name because they are insecure about the website behind that name, and they feel like they need every bit of help they can get, like agonizing over SEO and having "the right" name. If there's one thing 37signals is not, it's insecure. And although their word is thrown down as gospel way too much among bloggers, a bank statement is hard to argue with.

Be confident with your service and your name, and success will follow. Your .com is only as central to your business as you make it.

Getting What You Want

24 March 2008 –

Over the past year or so, I've really started paying closer attention to the people aspect of software development. Reading Jeff Atwood has been a significant part of that evolution for me. Jeff noted how very important interpersonal interaction is to a successful programmer:

How can you possibly learn the craft without being exposed to other programmers with different ideas, different approaches, and different skillsets? Who will review your code and tell you when there's an easier approach you didn't see? If you're serious about programming, you should demand to work with your peers.

image

One of the more unfortunate traits common to the programmer demographic is our remarkable ability to be off-putting. It's certainly more true for some than for others, but even when a programmer is considered "quite personable", he's probably a lot closer to ISTP than to ENFP.

So I'm trying to improve. The single best resource I've found for this is Dale Carnegie's How to Win Friends & Influence People. It's an immersive read - Carnegie is an excellent storyteller and uses clear, concise examples to communicate his "Fundamental Techniques". It's practically written for a programmer, removing all fluff and assumptions about interpersonal interactions - a literal API reference for people:

  • "Give people a feeling of importance by praising the good parts of them"
  • "Become genuinely interested in other people"
  • "Encourage others to talk about themselves"
  • "Start with questions the person will answer yes to"
  • "Let the other person feel the idea is his/hers."

The brief sampling above evidences the paradox of effectively dealing with people - we have to give what we want to the person we want things from. On the surface, the advice sounds so simple - "be nice to people and you're more likely to get what you want." But how often do we do it in practice? How often do you really give up all the credit for a job well done, even if you did most of the work - or it was even your idea? Not often enough.

Carnegie's thin paperback is so full of behaviors to change that it's overwhelming, so it's good to start with a select few and make them habitual. I've been developing a few habits of my own, slowly but surely. These things will seem like Life 101 to some, and far-fetched to others:

  • Being very direct and task-oriented (a major programmer trait), when I need something from someone my first action is to start a new e-mail and politely ask for what I need. New habit: before I hit send, I backtrack to the beginning of the e-mail and write a sentence or two complimenting something they've done recently, or asking about something that is important to them.
  • I am trying to remember to append the person's name every time I say "hello", "thanks", or "goodbye" to them.
  • When someone compliments me directly, I try to think of someone who contributed, even indirectly, to whom I can credit some of the success.

Hopefully the pattern here is pretty obvious: make other people feel important. People like feeling like other people are interested in them and their issues; people like hearing their name; people like receiving credit. At first it feels a little shallow, maybe even a little sociopathic - having to consciously fish for nice things to say to or about people. But I can say from experience that it doesn't take long to become habitual, and then become natural. When you think about these things all the time, you actually do start to become interested in other people's issues. You become invested in the success other people get to enjoy when you give them credit for a job well done. And that's the real trick - not faking pleasantness to manipulate people into doing what you want, but genuinely being the kind of person other people like getting along with. That kind of person naturally gets what they want, which is really where we all want to be.

Never Be a Five

14 March 2008 –

Roughly once a month we have a group meeting. It's really the only time where the entire web platform team is in the same room, so we cover big topics at a high level. One of the major discussion points yesterday centered around an unsolicited, unscheduled review of our group by our corporate masters. It rated our performance in key areas on a scale of 1-5 (5 being perfect, 1 being "why haven't you been fired yet?"):

  • Hosting & infrastructure
  • Quality of developers
  • Project management & delivery
  • Etc.

The rating "quality of developers" got a 4. For a minute, I was a little shocked and offended. If there is one thing our group is known for and prides itself on, it is the quality of our development team. I work on one of the best development teams I've ever known, and my opinion is not atypical. I hear on a weekly basis how above-par we are as a group. The web platform team is "leet", as they say.

Four is good - great, even. Three being "average-competitive", it's highly desirable to be a 4. That being the case, why do I care so badly about being a 5? Is it realistic to want to be a 5? Is it that much of a shock to be told you're only really good when you thought you were the best?

Like I said, my reaction lasted for a minute. But then I asked myself, "is it possible to be a 4 and also be the best?" I think it is. When I say best, I definitely don't mean best in the world. There's always someone better. But "best" in a very localized sense can be different for everyone and still be useful. Like my track coach told me so many times, you're only racing against yourself. The other people out there on the track with you are just useful tools to help benchmark your progress, but the competition is internal.

Anyone who has done any kind of race, especially track, knows that you get your best times when you consistently run with people a little bit better than yourself. The person ahead of you is an attainable goal. If you're alone, you have no baseline with which to construct the bounds of potential achievement. If you're half a mile behind the nearest competitor, any effort would be wasted. If I'm a 5, I've peaked. Any improvement from there on is sheer luck. Personally, I don't want to peak yet.

Never be comfortable. If you think you're on top of the world, it's impossible to go any higher. You've established a mental model of your profession that prevents you from truly aspiring to improve. Instead, if you think you're a 5, make yourself a 4. Keep besting yourself. Spend some time and effort identifying some aspect of development you don't fully understand. Actively seek to work with people who make you feel a little stupid. It's only as uncomfortable as you make it. Be a 4, forever.

A Brief (re)Introduction

11 March 2008 –

A long-overdue restart of my weblog, this time on my long-unused domain. Please explore and let me know if you find a bug or seven. This blog platform is home-grown and a work in progress. There are a number of projects I'm actively working on, and I really needed a way to try out some new technologies in a non-threatening, small-scale playground setting. The timing happened to coincide with my desire to resume blogging and my frustration with many existing blogging platforms. So, finding them all to be too difficult or flaky, I threw this together instead. The design is something I've been incubating for awhile. It's nothing special, but it gets the job done.

© 2002-2008 Rex Morgan.
Content available under a Creative Commons license.
Site code and design may not be reproduced.