Monday, March 15, 2010

Strange Days

These are strange days.

The pundits and economists claim that the economy is on the rebound. But for those of us down here in the trenches, those of us whore are jobless, with bills to pay and families to feed, there's no economic recovery in sight. The bills are piling up, the job offers aren't materializing, and money is getting harder and harder to come by. All the while, the fat cats in Washington bicker over health care reform while getting nothing done aside from playing the blame game, trying to decide who was responsible for the economic disaster in the first place.

My dad, dead now ten years or more, used to say that the more things changed, the more they stayed the same. He was right. Things are no different today than they were ten, twenty, fifty years ago. Politicians, in their luxurious offices, with their limos and travel budgets and vastly superior health care plans, have no real idea what those of us in the trenches are going through on a day by day basis. We have very basic needs. We have to be able to pay the rent. We have to be able to clothe our kids. We have to be able to pay for things like gas, electricity, and hot water. We have to be able to pay for public transportation or gas to get to work every day. We have to be able to afford decent medical care and prescriptions when we need them—which isn't always a planned thing.

But if you're rich, you likely don't even have to think about those things. They're just taken care of. Someone handles all that stuff for you. It's inconsequential, beneath your notice. You might stand there on television and claim to be a man of the people, but after a little while in office with that big salary and all those incredible benefits, your memories of what it was like to be one of us will quickly fade.

But we are your constituents. We're the ones you're supposed to be helping. We're the ones having to decide, day in and day out, what we're going to have to cut out of our lives to be able to afford food or rent. Not because we want to, but because we have to. We make little choices, and lots of them.

We turn off our cell phones because it's not necessary, and the phone service that anchors us to the house through our cable service is cheaper. Sure, we're screwed if we get stuck on the side of the road, but we have to make that choice because we can't afford it.

We choose to give our pets up for adoption, because we can't afford to feed or care for them anymore. Sure, they'll likely be euthanized, because no one else can care for them either. But we do it, because we can't afford it.

We choose to cut our automobile insurance, because we can't afford the egregious rates we're being charged. Sure, we're out a vehicle if something really bad happens. But we do it. And you know why.

We choose to endure pain and suffering without visiting a doctor, or to try alternative therapies which are either ineffective or potentially dangerous, because we can't afford the copays.

We choose to buy cheap, processed foods to feed our families, rather than fresh meat and produce. Sure, it'll have a longer term impact on our overall health. But the price difference makes you wonder if they're trying to discourage you from eating healthy. And we simply can't afford to eat well.

We use up our savings, dive into college funds, remortgage our homes, do anything to survive. We sell our cherished belongings. We move into smaller apartments, crammed with multiple roommates trying to pool their resources against the financial crush. And even then, we struggle.

Those of us who have jobs hold onto them for dear life, afraid of what might happen to us if we lost them. It doesn't matter if we hate the work we're doing, who we're working with, the hours we keep. The world outside that job is far, far worse.

And yet, to hear the news, the economy is in a rebound, and things are looking up. Consumer spending is on the rise. You wouldn't know it at my house, or the homes of any of the people I know. We're all feeling the pinch. And this pinch leaves major bruises that aren't going to heal any time soon.

Washington, and all the local politicians, need to take off their blinders and remember that the world does not live like they do. In the real world, the vast majority of the population is poor, and struggling to survive from one day to the next. Sure, the rich line your pockets. We all know that. But the poor cast the votes. Step out of that bright light that blinds you to the realities of life that every day people face, and look at it with an unfettered vision for once. And then, without just dismissing what you've seen and heard, do something about it.

Stop bickering. Party lines should be irrelevant in this crisis. And it doesn't matter who started it. What matters is what we're going to do about it.

Wednesday, March 3, 2010

Farewell to Software Development

So here I am, staring at this screen, thinking about what to say. It's been a long time since I blogged. It's been funny, in a way, that my blog was never really very technical. I always blogged about the esoteric aspects of software development. About personal improvement, about striving to become a better software developer, about questioning the status quo, about reevaluating yourself at every step of the way. And now, I find that those words come back to haunt me. But not in any way that I would ever have expected.

I've been unemployed since December 1st. I've been seeking employment since then, and the experience has been eye-opening. In the past, getting work was never difficult. I like to consider myself both a competent developer and a proficient interviewer. In the past, it's never been difficult to find work. Within the first three or four interviews I had an offer on the table--usually several, and I could take my pick from them. But this time, I'm finding myself faced by rejections for reasons that escape me. One company refused to hire me because I hesitated when asked to describe the difference between natural and left joins. They thought a senior level developer should have provided an immediate response, without hesitation. I thought a senior level developer would have thought his answer through, worded his response carefully, and not just blurted out the first thing that leapt to mind. Apparently, it was irrelevant that my answer was correct.

I'm also faced by the prospect that technology is passing me by. This has been a growing concern of mine for years. There's a conundrum we all face when we seek long-term employment with any company. You see, companies seek candidates who want to stay with them for years. The problem is, companies tend to be entrenched in a particular technology stack. They have a vested interest in maintaining whatever software they've developed with that stack, and once you've invested yourself in the maintenance of that software, you're pretty much mired in it for the long haul. Whatever tools and technology were used in its initial development tend to become a ball and chain that anchor you where you are for years at a shot. Technology moves forward, but the product likely does not. And you, as the maintenance developer, stay tethered to that product and its associated technologies as everyone else moves forward.

New technologies emerge all the time. There are so many technologies out there right now that no one could possibly grasp them all, let alone consider himself an expert in them all. And yet, interviewers expect you to have this commanding expertise in such a wide variety of technologies that their expectations can be considered unreasonable. A jack of all trades is master of none. The truth of the matter is that most of us will never learn a new technology until a particular project demands exposure to it. Only then will we learn it. And then, we'll only learn enough of it to get by. Few companies have the budget to send their development staff to seminars or their ilk to receive formal training. Few developers make enough money to seek out and pay for formal training out of pocket. And few companies that provide that training are motivated to lower their prices to make it accessible to dirt-poor developers hungry for the knowledge.

And so it's a vicious cycle. Technology moves forward. Developers are stuck with the old technology, and cling to their jobs because, in this economy, they know it could be really difficult to find new work. Further, they know any new work they find could be worse than the work they're doing now. It's a buyer's market. Wages have declined, benefits are being cut, and the work still has to get done.

Over the last few years, I've been stuck in this vicious cycle. But since December, as I've been interviewing, one thing has started to become increasingly clear to me: software development is leaving me behind.

It doesn't matter how much I love it. It doesn't matter how good I am at it. It doesn't matter how passionate I am about quality, good design, team cohesion, self improvement, or any of those things. What matters is that I am tired of playing this catch-up game, of trying to appease people with unreasonable expectations, of being expected to know everything about everything, and being held accountable when I don't.

I know my limitations. It's time to get out. It's time to leave an industry behind that is full of falsified estimates, rushed deliveries, power grinds to meet deadlines, badly defined requirements, insane amounts of finger pointing, and unreasonable expectations. The days when developing software was fun are long gone. Somewhere along the road, it became work. And for me, that's the day it died.

So I'll turn from that path, now, and find a new path. I'm not sure what it is yet, but with any luck, it will be far less stressful.

To all of you still in the quagmire, I wish you well and good luck. Software can be tons of fun, if you keep it in the proper perspective. Somewhere along the way, I suppose I just lost mine. Try to keep yours. But for me, this is farewell to software development.

Friday, October 30, 2009

Oracle SQL Coding Standards, Or the Dearth of Them

So here I am, laboring furiously to get my refactoring tools polished up for Insight, and the one feature that I would really like to get implemented is a spiffy coding-standards compliance tool for SQL. One would think that it would be a simple matter of digging up the most widely accepted standard, allowing the user to modify that standard to suit their firm’s needs, and then applying it to the script in question. And that isn’t really rocket science. Except for one thing.

There isn’t really one widely-accepted PL-SQL coding standard.

Now, I’m not going to just come out and say that Oracle is horrible at documentation. No, wait, I am going to say that Oracle is horrible at documentation. Aside from the fact that the vast majority of it is nearly incomprehensible, incomplete, and badly formatted, they tend to gloss over things that concern the really important folks: those who have to use the damned thing.

A coding standard is a really important thing. Without it, you end up with ten-year-old databases that have passed through a plethora of hands and no two sets of hands agree about how the code should be laid out, how the variables and objects should be named, how things should be cased, and where commas should be placed. Sounds trivial, I know. But when you have to come in ten years later and try to reconcile all those competing non-standards into a single, cohesive “product” that makes sense so that you can maintain it, it’s a nightmare.

We need a driving vision for a SQL coding standard. And we need it from a single source, with some authority behind it. But it can’t just establish a standard that comes down with some heavy-handed practice that isn’t thought out. As much as I hate to admit it, Oracle has been doing this a long time, and they’re the logical choice to start this movement, with lots of input from the community.

On the other hand, this could be an entirely community-driven thing, a grass-roots effort to establish a common SQL coding standard. On this blog, Lewis Cunningham discusses such a project, but it doesn’t appear to have taken off. It’s a pity, because I think it’d be well worth the effort.

Who knows, maybe I’ll slide on over to Google Apps and see what I can do to start such a grassroots effort myself. I’m tired of sitting around waiting for a consensus to just pop up out of thin air. You’ve got to start somewhere, right?

Wednesday, October 21, 2009

Smug Bastards, Toy Databases, and Ease of Use

Alarmingly, I cannot find anything in this post that I disagree with. I don't know whether that makes me proud, smug, or ashamed. Either way, I laughed my ass off.

Wednesday, October 14, 2009

The Cost of a Quick Second

So, here I am, cleaning up a rather large code base, and I find myself in the throes of retrofitting properties with attributes. Now, when I wrote these properties, the prevalent thought at the time was that I just had a crap-load of properties to write, and tons of business code that needed them. So, in a bug hurry, I slapped together some C# code that spit them out. You know, kind of like this:

public string Owner { get; protected set; }

Now, at the time, that’s all well and good, because at some point, the work just has to get done. But then, I realized that the software I’ve been working on is actually very useful and that I want to polish it up and get it ready to release it to the masses. But I discover, to my utter horror, that the source code is an absolute disaster because, well, I didn’t write it with the intention that anyone else was going to actually look at the source code.


Sure, the thing looks beautiful from the outside. And it does what it’s supposed to do (by and large). And it’s fast. Very fast. But please, please do not look at the plumbing. Or the wiring. The vinyl siding is Fabulous. But don’t look underneath it.


Hence, the retrofitting.


I’m sure you’ve been there. Don’t look at me like that. I know we’ve all written crap code slapped together in a hurry because we needed something just this second and it will only take a second to do.


Which leads me to my point: A quick second now will cost you hours later.


This particular project involves two separate assemblies. A Class Library DLL, which houses all the logic, and a Windows Forms Application which references the Class Library. The problem is that the class library is missing the bulk of its XML documentation comments, and the properties aren’t properly marked with attributes. Silly me.


So now, I have to go back through the code, one file at a time, and mark up my source code. Trust me, this is no picnic. Fortunately, I believe in good, clean names, so the code is largely self-documenting. But there have been a few surprises here and there. But going back through any source file and adding the comments after-the-fact is slow and tedious work. You shouldn’t put yourself in a position to do it in the first place. Comment up front when the purpose of the property or method is fresh in your mind.


When it comes to property attributes, you’d be amazed at how many there are:



  • DefaultProperty. This attribute doesn’t go on a property, but marks up the class to indicate the name of the property that should be treated as the default.
  • ReadOnly. Use this attribute to specify that a property is read-only in the property grid.
  • Description. Use this attribute to specify the description that appears in the property grid, or in the tooltip that appears when the user hovers over the property in the editor.
  • Category. Use this attribute to specify the category that the property is grouped under when the property appears in the property grid.

These are the few that I’m primarily interested in. So, for each property, I have to move along as follows:

/// <sumary>
/// Gets the owner of the view.
/// </sumary>

[ReadOnly(true), Description("Gets the owner of the view."), Category("Schema")]
string Owner { get; protected set; }

This gets a lot more complicated if I’m documenting a method, as you can imagine. Then we’re dealing with parameters, return values, and all that other hooplah because the consumer isn’t familiar with the code like I am.


Refactoring tools can simplify some of this stuff. Some software tools boast the ability to generate documentation comments for you, but my experience with them have been less than rosy.


So take some advice. Spare yourself a little effort down the road. Document and mark up your code as you go along. It’s worth the time to do it up front. I have to go through this code base and get this stuff cleaned up now. The only good thing I can say about it is that it’s giving me a really good chance to go through the code with a fine-toothed comb and clean it up, remove dead code (oh, for an open-source tool for that!), and eliminate some redundancies. Aside from that, I’ll be kicking myself in the future for taking hasty shortcuts like these.


You should be too.

Saturday, August 1, 2009

The Perfect Villain

I play City of Heroes quite a bit. Okay, so that's an understatement. I play it a lot. After five years in the game, my addiction runs so deep it's threaded its way through my genetic makeup. You'd be hard-pressed to separate me from it.

I've always had a love of comic books. What's not to love? Sure, they're the domain of geeks, nerds, and all their ilk. But let's face it: who wouldn't love to fly? To have virtually god-like power at their disposal? To have a body so ripped you wouldn't think twice about showing up in public in a spandex body suit?

But one thing has started to really bug me about the villains in my game of choice. Now, I laud the writers for COH. As the game has aged, the stories have grown more compelling, more twisted, more convoluted. Sure, we have some dangling plot threats, gaping plot holes, and all that jazz, but they've fleshed out some of the characters quite nicely. In a world full of super-powered beings, that's frequently no mean feat. It's not easy fleshing out characters in a story about normal humans; try fleshing out a character who can incinerate you with a look, or teleport across vast distances, or summon the dead--and justify their reasons for doing what they do. That's a lot easier said than done.

The budding writer in me understands their desire to do just that. I think that the armchair psychiatrist in all of us would tend to agree that any villain who embarks on a life of crime does so for a reason. Greed, revenge, betrayal, power, lust, all the standard reasons are there.

But I've watched those foundation villains in City of Heroes for some time now, and I've discovered something about them that disturbs me.

They are all too distracted.

Give me any villain from the COH Universe and I can likely show you how that villain is too distracted. They all lack focus. A clear vision of what it is that motivates them. What Paragon City, indeed the COH Universe, needs is a villain who is so absolutely single-minded that he (or she) is utterly unstoppable and incapable of being distracted.

Imagine, if you will, a villain whom you never see. He is adept at keeping his identity and location concealed from everyone, including those with psychic and magical abilities. He does not want money, power, fame, or legions of followers. What he does want is to watch people suffer. He does not care, particularly, how he does it. He just cares that the world is filled with pain, anguish, misery, and death, and that it was his hand that brought it to pass.

He is not a god. He is not inhuman. He is not even super-powered. He is simply intelligent, and possessed of a single-minded determination to bring mass chaos to the world around him. He loathes the other villains because they are weakened by the petty squabbles they engage in between themselves. He will kill heroes, villains and civilians with merciless abandon.

While he has no followers of his own, there are those who have heard of him, and rally to his cause. These copy-cats seek to emulate him. They spread his anarchist agenda with a ruthlessness on par with his own. They could be anyone: civilians, members of known factions, heroes teetering on the brink of villainy. But none of them knows who he is or has ever seen him.

The only reason that anyone knows he exists is because he occasionally forewarns people of upcoming tragedies he will inflict, only to incite more terror. His mastery of indirection will sometimes lead heroes to one site in an attempt to avert disaster, only to realize that his real target was some other heavily populated target.

His targets of choice are always large population centers: hospitals, police departments, large office buildings, schools, and so on. Given any choice where he can inflict damage, he will inflict as much damage as is humanly possible.

Yes, this is the kind of villain that the COH Universe needs. A Black Mask, completely unpredictable, untraceable, never brought to justice, enemy to both hero and villain, and incapable of being distracted from the one thing that he seeks the most: the pain and suffering of others.

I highly doubt that this sort of a villain could be brought to pass and maintain the T for Teen rating that the game enjoys in its current incarnation. But one could dream. And if you're going to dream, dream big.

Technorati Tags:

Thursday, July 16, 2009

InternalsVisibleTo and Chasing Down Public Keys

Sometimes, just getting assemblies to cooperate the way you want them to is a real pain in the neck.

Today, I wanted to make one assembly (which we’ll call Foo) to be able to access the internal (Friend for all us VB geeks) members of another assembly (which we’ll call Bar). Now, the documented way to achieve this is by adding the InternalsVisibleTo attribute to your project. The code sample on MSDN looks like this:

[assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")]

For a Visual Basic application, that statement goes into the AssemblyInfo.vb file, and looks like this:

<Assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")>

No big deal. It’s not rocket science. You just need a strong name. To generate a strong name, you fire up the Visual Studio Command Prompt, and execute the Strong Name tool (sn.exe) and execute it as follows:


C:\Program Files\Microsoft Visual Studio 9.0\VC>sn.exe -k bar.snk

Microsoft (R) .NET Framework Strong Name Utility  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Key pair written to bar.snk

As you can see, this creates a .SNK file, which contains a public and a private key. However, its contents are not human readable. Further, the InternalsVisibleTo attribute requires that you provide the public key in the constructor. (Don’t even think about trying it without it.)


Here’s where things get tricky: The code samples on MSDN do not provide a public key to the constructor; they provide a public key token. There’s a huge difference between the two, and it’s very misleading. A strong name token is much shorter than a public key; the former is only about 16 characters long, the other well in excess of 140 characters. If you rely on the code sample from MSDN to get you where you want to be, you’ll be pulling your hair out in no time.


But how do you get the public key token?


You can retrieve the public key token as follows:


sn –p foo.snk barpublic.snk


This creates a new file that contains only the public key. It removes the private key information from the file.


sn –tp > barkey.txt


This creates a text file that contains the full dump of the key information, including the public key. We redirect it to a text file so that you can open it in the editor of your choice (because you’ll have to do some cleanup to get the key onto one line). You’ll want to select the public key and paste it into the PublicKey portion of the constructor for the InternalsVisible attribute.


So here’s everything we did at the command prompt:


C:\Program Files\Microsoft Visual Studio 9.0\VC>sn -k bar.snk

Microsoft (R) .NET Framework Strong Name Utility  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Key pair written to bar.snk

C:\Program Files\Microsoft Visual Studio 9.0\VC>sn -p bar.snk barpublic.snk

Microsoft (R) .NET Framework Strong Name Utility  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Public key written to barpublic.snk

C:\Program Files\Microsoft Visual Studio 9.0\VC>sn -tp barpublic.snk > bar.txt

C:\Program Files\Microsoft Visual Studio 9.0\VC>

And here’s the contents of our text file:


Microsoft (R) .NET Framework Strong Name Utility  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

Public key is
0024000004800000940000000602000000240000525341310004000001000100e13cb392af5437279736fc3c33fe237242d0f6301fafb01c5cbc719d84102c2d8b30a148600997ed53d99624b5d0eab37fd6b24cca3ce7f7b62ae99f961e148d5421576bade0ac8ab1187a3eee318ca20026ffe9b56b8a63156f817cef49998633867ae547684e8e59c0fe0b68ab29dffa749340dc6cfdd18071f1b69c6772ac

Public key token is db218359dd8997df

So, when we finally add that attribute to our AssemblyInfo.vb file, it looks like this:


<Assembly:InternalsVisibleTo("Bar, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e13cb392af5437279736fc3c33fe237242d0f6301fafb01c5cbc719d84102c2d8b30a148600997ed53d99624b5d0eab37fd6b24cca3ce7f7b62ae99f961e148d5421576bade0ac8ab1187a3eee318ca20026ffe9b56b8a63156f817cef49998633867ae547684e8e59c0fe0b68ab29dffa749340dc6cfdd18071f1b69c6772ac")>

Once this stuff is in place, Bar should be able to access any members in Foo that are marked internal/Friend. It should be smooth sailing from there.

Good luck!