Sunday, March 30, 2008

My (current) favorite picture in the world

I was walking through downtown Manchester a couple of weeks ago, and this sign called out to me with its beautiful, terrible siren cry.

(click to blow it up)

If you're going to ask me what's so beautiful about it, you may as well ask me where it all went wrong and where you lost your soul from childhood up to here. It's really the final admonition ("NO ESCORTS") that puts it over the top for me - it displays a remarkable economy of language that I obviously have no facility for. At the very least, it tells the passer-by "we've been asked that goddamned question so many times we have to put it out in front so people don't ask again (and they probably will anyway)."

I love this picture in an inappropriate way. Or appropriate, I don't know.

Friday, March 28, 2008

Taking your lumps like an enterprise

Obie Fernandez posted recently about SAP, enterprise software peddlers par excellance, getting their asses sued by Waste Management, a behemoth of a company, for a clusterfuck of a deployment.

This reminds me why I want to keep working for small companies - I want to know when other people are making absurd promises that they'll then expect me to uphold as soon as possible and if at all possible, I want to be able to correct them or speak directly to the client and say "Sorry, they fucked up when they said that. Not gonna happen in that amount of time, but let's see how many items on that checklist we can realistically get done in the time and cost constraints you've set forth for us." Scrum has embarrassingly juvenile terms, but I think they really nailed it with the pigs and chickens metaphor.

It also reminds me of a talk I had with my COO a few years back, back in the heady days when I thought software could solve all ills and had no interest in moving any further up the food chain than architect. We were talking about some other clusterfuck that was in the news - a huge enterprise software vendor, a huge client, tens of millions of dollars and... nothing to show for it.

The developer in me was all righteous indignation - "How can they get away with that? Isn't that kind of thing embezzlement or something? If that were me, I would sue the bastards."

His response (and I'm paraphrasing) was a thunderously mighty zenslap.

"There's no point in suing them."

"How can there be no point? It'll serve notice to the next vendor in line that they're not to be trifled with."

"No, there's really no point. Even if they win, they'll never recoup their costs. They'll scare away other vendors and they still won't have what need. It's over."

I couldn't argue with that. I can't.

The contracts are dozens of miles long, filled with all manner of Cover Your Ass wording and dense, vague terminology that likely provide a Get Out of Jail free card to both sides. It'll be tied up in the courts for years, but it doesn't change the essential problem - you've already slipped what you thought was your deadline and run over-budget.

Do you spend time, money and focus trying to chase what you already know is a dead-end or do you effectively shrug your shoulders and focus on what will make you money? Were you completely up-front with all your needs? Were they all clearly outlined (and signed in blood in the contract)? Really?

And remember - if you do go with suing them, your chances of getting that software you swore you needed probably just evaporated. That's money that's probably coming out of your implementation budget (which is, again, already exhausted). If you could have done it in-house, you would have (right?) but you couldn't, so it means you need to find a new vendor. Who is going to be very wary of signing on with you because of the lawsuit, which means even more time and cost to get to the point where you can convince them to start building for you (which is going to take even more time and cost more because they know about your lawsuit and need to double-cover their asses). Knowing that it'll be a pyrrhic victory at best, do you still sue?

So I'm surprised that Waste Management is nutting up and suing the holy bejeesus out of SAP. I am, make no mistake about it, cheering for SAP to lose in the most majestic manner possible. I hope other large companies sue other large, shitty, enterprise software vendors.

And I am hoping that when they're eradicated, I'll figure out a way to become the next SAP. Money isn't the be-all and end-all, but I'm not too much of an asshole to say no to obscene amounts of money for nothing more than putting on a suit and having a nice little dog-and-pony show.

The difference between a shoplifter and a very successful enterprise software firm is that you're scared as fuck to prosecute the enterprise vendor when they rob you blind.

Tuesday, March 25, 2008

So, about that Microsoft-Yahoo Merger

So it was a slow day and I was reading about the Microsoft-Yahoo merger. How developers at Yahoo are fleeing in droves because Microsoft doesn't get the 'net and will ruin Yahoo.

And this isn't so say that they're wrong, but how about fleeing Yahoo for a better reason? Like, say, because of this embarrassment puddle parked out on the street in front of my shonky whip? I mean, come on Yahoo. I've never seen a Googlemobile, but I suspect that they're not quite as... butch as this one is.

(click to engorge this shameful display)

I've got no eye for color or detail, but... fuscia with the cheesy flame job? Really?

Then again, it did bring a smile to my face. For all the wrong reasons, but I was smiling. Way to go, Yahoo. Good luck keeping the corrupting influence of Microsoft far away from your pristine shores.

Sunday, March 23, 2008

It's official - I'm a Python hacker!

Lately, it hasn't been building the application that's captured my imagination so much as figuring out a way to validate the correctness of the application. When you're dealing with a sprawling behemoth of an application of varying levels of quality (this isn't a dig at co-workers - I've got more than my share of turds baked in there) that's so absurdly data-driven that... well. I've come to grips with the fact that chunk by chunk, we've built a borderline unmanageable enterprise application.

There's blocks of the application that I'm flat-out scared to touch because of their fragility. There's a reason that Jenga never took off as an application platform.

There's so many tables (I'll ballpark it at 300, but it could be more than that) that I have to walk through stored procedures and table definitions to figure out why many of them exist. Thankfully, at least they're well-normalized even if, again, some are really, really arcane.

More interesting to me than anything else lately is testing the application. When it comes to a giant database-driven web application, there are no easy answers to "how do you prove it is working correctly?". Well, at least none that The Google is willing to impart on me.

As I've mentioned before and will be talking about again soon (I'm busy hacking, d00dz!), I heart the hell out of Watir. You run WatirMaker, you walk through your application, you're 80% or more of your way to a test case. But... it runs slow. It takes over 3 hours to run 130-ish test cases of varying complexity on the old desktop I snuck the regression automation environment on to. I love it, but I worry about its scalability.

Over on programming.reddit, I saw a new tool announced that tickled me in all the right spots - Pylot. It was designed as a web load-testing tool (I've seen the QA folks at work use Quick Test Pro, but it's a fragile piece of shit if I've ever seen (and built) one) and has lightweight validation features built into it. On that end, it's not as fully-featured as Watir (I've updated WatirMaker to do 31337 things like generate automagic tests when you click on text in table cells/spans/the body) but... speed! Free replacement for Quick Test Pro (maybe)!

I saw it and immediately got to wondering about writing tests for it - is there anything that will get me 80% there? Not yet. Could I take WatirMaker and update it so that it emits Pylot-friendly XML? Sure, but doesn't that feel just a lot unholy?

So I downloaded Python and got to work doing the crappiest, stripped-down-est translation of a useful Ruby meta-script to Python that you've ever seen. A few hours of grunting and banging my head later, I've got something to show for it, thanks in part to the duders over in #python on EFNet.

Does anyone have any experience working with buffer objects? I'm getting one handed back to me and I'm completely lost as to how to coax it back to a string.

um, str(yourbuffer)

that's what makes python so difficult to pick up -- its simplicity

If I were them, I'd clown on me too. In my defense, The Google wasn't all that helpful when it came to working with buffers in Python and I'm a complete new jack and calling yourbuffer.tostring() wasn't getting me anywhere useful and enough ball-aching.

So here's my first stab at It requires the Win32 extensions for Python to run and you run it the same way as WatirMaker - pop open a command prompt and " > test.xml", browse around the Internet Explorer window that opens up, close IE when you're done and test.xml is set up for you. Minus tests.

Did I really spend 5 hours knocking out 44 lines of Python instead of playing Team Fortress 2? There's something way wrong with me.

Wednesday, March 19, 2008

A Few Binary Propositions I'm Comfortable Making

By the time I got to high school, I was ready to get serious about programming. OK, not get serious, but at least take some classes in it because that's how you meet ladies (note: that's not how you meet ladies).

I learned some lessons that I regarded as stupid then and quaint now (pseudocode your program completely before you sit down at a keyboard (read: hi UML or we pay for cycles on the VAX cluster)), but I also learned some rules which have honest to god stood the test of time.

When it comes to programming, I'm pretty uncomfortable making binary propositions - there's a time and a place for a lot of things. That time isn't the future because in hindsight, you can count on recognizing just how wrong you were to think that you could get away with that.

But fret not! Here are a (very) few rules that you will never kick yourself for following. These are laws. These are immutable.

Use clear, concise, self-descriptive variable names

Our task was to write a function to calculate the area of a rectangle. After laboriously pseudocoding it out, I sat down in Turbo Pascal and banged out some gorgeously hand-crafted code, using x1 and x2 as parameters for the length and width because they were easy to type. It worked. Flawlessly.

My teacher took a look at the print-out of my code and asked "Why not call them length and width instead?" I started to argue because that's how I roll, but then it hit me like a Zen slap - code is words, structured a bit differently and with a bunch of funny-looking symbols interrupting it, but you should try to make it as readable as possible. This starts with meaningful variable names and grows from there.

Thankfully, this is one rule that I don't break. Ever.

You should be able to describe what any function does in one sentence (and the word "and" should not be part of that sentence)

I try to decompose my functions, but I'm not nearly merciless enough in my pursuit of it. I don't set out to get there, but big gnarly if blocks in my business logic can spiral methods out of control, leaving me at the point where I'm afraid to extract out blocks because things might break.

This is probably reason enough to extract out blocks, but I'm bullshitting myself into not doing it for any number of reasons - I tell myself things like "the code is complex because it's modeling a complex process" but I know just how much of a cop-out that is. It's lame and embarrassing and if only that code weren't working and I wasn't so afraid of it, I'd do something about it.

Honest. Probably.

Thanks to playing around in Haskell, I'm rediscovering just how powerful decomposition can be. You can, like, build big things out of little things and stuff. It's easier than the God Functions because you're just building ever-bigger functions out of ever-smaller, easy-to-test functions.

Next time I'll get it right. I hope.

A cat should be able to walk across the keyboard without interrupting your program

Does this sound like "validate client input"? Because it is. If you want to be fancy about it, you could say "don't trust client data any more than you absolutely have to." Either way, this is rock-solid advice.

You should not be building software where you're afraid to enter a number for a name, a letter in a date or (god help you because I've used garbage like this) click in a form while it's processing because something disastrous will happen.

I also manage to not break this (most of the time). That said, when I do things like, say, set maximum lengths on input boxes on my pages and don't test the form data on the server side, I have a pang of guilt that I'm not really solving this properly (and I ignore it and move on).

When the dam breaks, work on the first problem first

The blogosphere will tell you that this is Tilton's law. When our programs would invariably break, I'd look at the jumble of garbage on the screen and start inventing ever more elaborate explanations for what just happened. Maybe I overwrote the video buffer with a whoosiwhatsit and flargened the backplane with a sympatasultic bitmask!

My teacher sat down and asked me what went wrong. I started to spout some nonsense about this and that. He listened to me for a minute, then stopped me and said "Why don't we start from the beginning and see where it leads us?" Surprise surprise, I'd made some bonehead mistake or other (but 17 years later, I couldn't tell you what).

This came back to haunt me just today. A hot issue that must be fixed now got dropped in my lap yesterday in an application that's kind of sort of orthogonal to the one that I develop and support. So I start looking into it, but I can't get it to run out of the box. I fight with it more and more and more and a day and a half gets burned making just about no progress as I'm trying to chase the downstream effects, waiting for them to lead me back to the cause.

We get on a conference call to talk about the status and I hear people say what they were trying to do (it had been e-mailed to me before) and it clicks - check the data setup.

I'd taken for granted that someone else had done this already, but lo and behold - it's wrong. 12 hours of wasted time could have been saved by 5 minutes of fact-checking.

It's easy to get caught up in Rube Goldberg contraptions to explain what could have gone wrong and on some perverse level kind of fun, but on another, it's more fun to start simple and fix the root problem rather than chasing a symptom.

I'm batting .500 or so. It's enough to get me to the big leagues, right?

Sunday, March 2, 2008

Working Hard to Get You Fired

When we first started porting from ASP 3.0 to C#, I'd never heard of test-driven design (why hast thou forsaken me (in 2000), blogosphere?!??!).

When we had a second round of developer hires, the two guys were gung-ho to get us on the Path Of Continuous Integration and get us all test driven and stuff. Were it not for the fact that we already had 200-odd KLoCs of legacy code of varying quality that would need to be refactored to be testable (in retrospect, I'm aware of just how big of a cop-out that is) and deadlines looming, we might have gotten on board the TDD train. But had the blinders on, so that never happened.

I've done some refactoring to bake in poor man's testability (objects that audit themselves and throw exceptions for as many offenses as possible) but the fact remains that building new functionality and fixing old issues often feels like sticking thumbs in the dam - I can feel when something's going to break, I just can't tell what or where.

About a year ago, the QA department hired someone to do automation for them. I was pretty pumped about it the application that we've built is that it's so big (400 KLoCs of C#, some ASP.Net controls, another 75-100KLoCs of T-SQL, bits and pieces of BizTalk) and so data-driven, at this point it would take something just short of an act of god to get it to a point where it's testable. I have little to no desire to be part of that and have never pushed for that sort of intra-object testing. I remain unsold on the promise of TDD, but I'm not so arrogant as to completely discount it; it's more that, like security, it's not something that can be bolted on. Maybe.

Simulated end-user QA automation - that's the testing that I can get on board with. I've been using the super-hella-sweet Watir for a while now and have handed it out to developers, product development, QA, even customer service reps when I want to replicate problems; it's been a godsend. I've built smoke tests that I can run on each deployment build that have saved my bacon more than once. I don't know how much you can tell about how the application's working or not working from inside of an object, but it's pretty easy to tell when things aren't working with it when your scripts break while being run.

The QA automation guy? Nice enough chap. He's personable, seems to know what he's doing and all, but... a year in and I've got no test suite to run. Enterprise-grade tools mean awkward enterprise licenses (we actually run a fucking license server somewhere or other- what the shit is that?) and all the user-friendly quality you'd expect from anything enterprisey. Plus I suspect that the goals were too lofty, that they were intent on building something beautiful and perfect and settling for nothing less. Which is great and all, but daddy wants his application tested already.

We've hit one of our cyclical lull periods at work. This isn't to say that there aren't issues cropping up all the time, patches being sloppily built and hurriedly and incompletely tested (business as usual!), just that the volume of issues is decreasing and management's hemming and hawing about what new features to build out. I've been sitting on my hands, getting micromanaged on what issues need fixing and what can be left to slide, so I took a look in my Watir folder - hey look, 100-odd scripts testing and regressing issues that we've logged for the past year or so. Most of them broken at this point because of genuine application changes, but whatever.

I set out to fulfilling the promise I saw in testing when I first brought it up - that not only were we saving time with each test, but that we were organically building up a test suite, testing the things we needed to. Getting all of my test scripts working was step one. Step two, the uglier step, was taking the user out of it. Before, I was relying on the end user (the QA person it was aimed at) to push a button in an internal GUI here, look at a piece of data there. But with a few Ruby system() calls and poking at the content of spans and tables (time-consuming as that is), that's fallen by the wayside.

The next hurdle was the database side of things - there's some pieces of data that don't make themselves evident in the application to the end user, so how the hell am I supposed to test for those? Oh - you can pass variables (like the auto-generated user's ID) in to SQLCMD.

So a week and change of me ignoring this and that piddly little issue later, and I've got 3 dozen or so scripts built out and checking things. Another couple of weeks or so and I'm going to have an honest-to-god test suite and, if anyone's paying attention, a QA automation pro's going to have some explaining to do when I've come correct with a reasonably not-too-shitty regression suite in what amounts to my free time and he's over a year in and still hasn't produced smoke tests. And if no one's paying attention and nobody gets canned for it, I'm not losing any sleep over it because I'll have scratched one hell of a big itch.

If only my solution was enterprise-grade, we'd be able to use it too.