I love UML.
No, I mean I really LOVE UML. The first thing I put on a new laptop is ArgoUML. I first learned it when I was picking up Plone, but since then have found it invaluable for gathering requirements. Give me some ideas about your site, I will eventually be throwing diagrams at you.
When you put UML in front of a customer and a developer, you finally have one thing that not only speaks to both of them, but is useful for both of them. The customer can see how a site might fit together, and the developer can see how to build it without having to sift through the cruft of a design document.
Before you go out and start looking at UML specs, know that for most things you ever want to do, you only ever need to use about 10% of what the standard UML library offers. Actually, 10% might be high. I only ever use one box, three arrows, and the comment box.
There is one problem, however. You have to teach the customer, and sometimes the developer, about how to read UML. The customer often wants to turn UML into a site arch, which will only lead to dozens of duplicate objects. The develop might waste time trying to guess as to what you mean rather than ask what the funny arrows mean. So I resort to my favorite teaching method: the analogy.
To explain UML, I use cups.In the above UML, you can see that I've made a cup object. It's just your generic cup, the kind the receptionist buys when she's feeling cheap that disintegrates if you leave it with any liquid in it over the weekend. It might even have a Dixie-esque logo, so we make sure we note that on the cup object. We also want to be able to call it something ("Crap-ass cups that Stacy bought, saving a grand total of ten bucks"), so we give it somewhere to hold a title.
We know that this cup is only really good for holding cold liquids, because the last time we tried to make tea in it, we ended up with a burned lap, scorched fingers, and a ruined weekend. Knowing that, we know to very specifically make sure that only cold liquids can go into the cup. The black diamond? If you want to get technical, you say the cup can be comprised of cold liquid. However, I don't usually break out my two dollar words when talking about stuff being in other stuff, so I just say contains. The cup can contain cold liquids.
But what if we want something that holds hot liquids? Do we make a new object? Nah. We're lazy developers, so we'll just use something that's laying around, like our good old cup object. We make a new object called mug, and set it to inherit from the cup class with a white arrow. Now, mug can do everything that cup can: have a logo, and hold cold liquids. It's not very useful to just have an identical class, though, so we need to start modifying mug.
I gave it a handle, since I hate picking up hot cups (I'm a delicate flower, after all). I also made sure to indicate that mugs can contain hot liquids. Now, mugs can hold hot or cold liquids, which pretty much covers the office gambit. Thinking about mugs and hot liquids, I started thinking about my favorite drink: cocoa. Well, marshmallows can go in cocoa, but marshmallows aren't a hot or cold liquid: they're solid awesome. So I use a different arrow: a white diamond. This means that the marshmallows can be contained in anything, but really, the best place for them is probably here. That way, I can have a cup of marshmallows in my generic cup sans cocoa, should that please me.
Thinking about marshmallows, I start thinking about s'mores. It's possible, now that I'm adding all this foodstuffs to my UML that I could think about a recipe database (something any food lover who gets hit with SQL tries to make at some point). Well, I don't need a recipe to contain food. I just need it to be able to point at existing food. So I draw a line, and that shows that these two objects now can be associated somehow.
It's silly, but it usually gets the idea across, and is a hell of a lot cheaper than most UML manuals out there.