December 2005 Blog Posts
I’ll try not to bore you with the typical reflections of the past year. Yesterday it pretty much rained all day, ruining our NYE plans. But where one door is closed, another door opens. We ended up having a grand time at our friends place playing board games and drinking white russians. A toast to 2006!
By the way, I have to give a shout out to my soccer buddies. These are a diverse group including some amazing soccer players of a range of ages who showed up despite the rain to get a sweet game on. It rained the entire time except for the last 15 minutes or so. You gotta love that type of devotion (or is it insanity?).
My favorite play was the one in which involved a give and go between a teammate and his mother. A mother son play steals the day.
So it looks like our New Years Plans have been derailed by the rain and the
Fire Marshall event organizers as reported by the fire department’s blog. It stopped raining an hour ago, but the wet conditions and the sheer amount of electrical equipment needed for Giant Village has made it a safety hazard. Bummer.
While we’re on the topic of appropriate analogies for software development, my homie Micah writes a post about how certain analogies fall short, and he compares writing software to being an artist.
He has some great insights into the idea that there is no such thing as “maintenance” in software, it is merely just another software development phase. But I have to respectfully disagree on his idea that perhaps we would do better to call ourselves software artists.
I disagree because of the image I get when I imagine the general archetype of the “true” artist. I often think of an artist as one who takes some tools and a medium, and creates the art that was there all along, but dying to get out. Now let’s try applying that to software. Do you really think there’s an ERP system in your keyboard dying to get out, if you’d only let it? Perhaps.
Also, the true artist does not create art for his or her audience. The artist creates art for the sake of art, the audience be damned! Now try telling that to your next client.
- Ummm... we were kind of hoping for a content management system. You wrote an RSS aggregator.
- Indeed I did! Isn’t it beautiful! It is my masterpiece.
- Well we’re not paying.
- I wouldn’t expect such a simpleton as yourself to be able to truly appreciate such fine code.
I don’t know about you, but I’m not interested in living out the romantic image of the starving coder.
Rather, I think of writing code as being more like a DJ. You have your set of tools and existing code snippets (records) and until you’re a big name, you take requests. However, even if you’re a big name, you still read the audience as you play, refining the music choice, tweaking knobs and sliders here and there until you have the audience (your client) in a joyful frenzy on the dance floor.
Honestly though, I don’t think my DJ analogy is all that useful. Ultimately software development will mature to the point that it will not need an analogy, it will be understood for what it is. How many building engineers do you imagine lose sleep at night thinking about a proper analogy to their craft?
Wait, I got it! Building a skyscraper is like writing software!
In a blatant ripoff of Scott H, I am going to post the best of “You’ve Been Haacked” 2005 edition. This year, you laughed, you cried and when you were done, you came over and briefly glanced at my blog. But I took it in stride and continued to write, rant and rave... and this was the best I could come up with in 20051.
1 There is no objective criteria for choosing these posts. I simply deemed these to be the highlights.
In some of my projects, I take a less purist approach to unit testing in that I allow unit tests to touch the database. In order to “reset” the database to the state it was in prior to the test, the code enlists COM+ 1.5 transactions via the [RollBack] attribute in MbUnit (there’s also one for NUnit).
My preference is to have a local copy of the database when developing, but there have been times when this was not possible and I needed to run my unit tests against a remote database I did not have full control over. The problem is that the RollBack enlists the local Distributed Transaction Coordinator to acquire a transaction. If the database server is on a remote server, it attempts to use Transaction Internet Protocol (TIP) instead which is disabled by default.
At the time, I was being lazy and left it alone, moving on to something else. Fortunately, my laziness has paid off as another smart person dug into it and figured out the details to getting this to work properly. See, sometimes laziness does pay off. ;) Thanks Steve!
Thanks to the generosity of my folks, I’ll be reading the following books. If you were planning (or want to) read them as well, click on the images below.
My parents are downstairs watching basktetball, my brother will arrive here tonight around 8PM, I’m wrapping a gift for my wife, and my coffee downstairs is getting cold.
But still, I wanted to wish you my loyal readers (and determined Google searchers) a very Merry Christmas, or a Happy Hannukah (or is it spelled Channukah these days?), or a happy Kwanza, or Yuletide cheer, or a belated Happy Solstice. If you don’t celebrate anything this time of year, and I really don’t blame you, then just be happy that the terrible Christmas music will soon end and we can prepare for the real fun holiday, New Years!
Anyways, I hope you are all doing well.
My good friend Micah finally started a blog. He is the CEO of my company, VelocIT, which makes him a business partner as well as a friend.
Micah is one of those “deep thinkers” which explains why he has two posts already and nothing technical. Just some philosophical rubbish. Come on Micah, show us your code! ;)
All kidding aside, I expect you’ll see some insightful writing on software development, management, etc... This guy used to be a Java programmer so he’s, switched to C#, and now just bosses me around. He has seen the industry from both sides and has a lot of interestings things to say. Now he can just write them down.
As I recently said, you have to be a bit MacGuyver to be a successful consultant. I’ve also whined about how difficult hiring is, especially when you want to hire MacGuyver. But then there are times where you work with someone who makes MacGuyver look positively clueless.
Jon for example takes the gum wrapper (to really beat an analogy to a sickening death) and shows us how to upload a lot of custom data to MapPoint given its constraints. Now this is a sweet example of problem solving.
Just for the record, I let Jon have the interesting work while I futzed around with these stupid textbox labels.
Hiring good developers is challenging. There’s a small bit of science and a lot of art. Even when a hire is brilliant, he or she might not work out. When hiring, you don’t just want a list of experiences, technologies and languages... You want a person who exemplifies being a self-starter (rather than just listing it as a buzzword on the resumé) who is also smart and can get things done. You’re hiring a personality as much as a liste of skills and experiences.
One tool that I’ve found invaluable is the use of blogs. That’s how we hired Jon Galloway who is a total superstar. As I told Jeff Atwood recently in a conversation, not having a blog won’t disqualify a person from my consideration, but it certainly helps. Otherwise I would want a strong recommendation from someone I know and trust. I have just been burned with bad hires too many times over the years to rely solely on a resumé and an interview.
To make it more difficult, once you identify a superstar, you should not be surprised if their current company pulls out all the stops to keep them. This sort of happened recently to us, as we had another superstar interested in working with us, but his company, unbeknowst to him, was about to launch initiatives that addressed his major concerns. They made a compelling counter offer and he chose to stay, though it was not a decision made lightly. I won’t name names, but he’ll probably show his face in here at some point.
We are happy for him, as it is a good deal, but we are also disappointed because finding good talent is very difficult and costly. I’ve heard it said that it can cost up to a year of a developer’s salary to locate a good one. There is the cost in spending the time and resources to locate someone compounded by the opportunity cost of not having the developer currently plugging away at projects and providing value.
So in that vein, Jon put a job posting on his blog and we are still looking for one or more solid consultants/developers to help keep an eye on me.
So if you are interested, or know someone you can whole-heartedly recommend, please send me a resume (phil at veloc-it.net).
For those of you who have sent me resumes in the past, I apologize if I haven’t responded. We have started to put every resume in our internal Groove workspace so we don’t lose track of people. It’s been difficult keeping up with everything.
I’ve learned a valuable lesson recently. To be successful as a technology consultant, it isn’t enough to just be able to hit the high notes. You’ve gotta be able to hit the middle notes too. You have to channel a bit of MacGuyver inside.
A while ago we hired a brilliant consultant to help us deliver a project for a client. This was one of those “finger in the dyke” projects in which we had limited time and money and had to help the client deliver something to their clients just good enough so everyone could get paid and we could properly fund the next phase which would include complete repairs and refactoring and a much cleaner solution.
The project timeline and budget for this phase would have been impossible to make as a custom development project from scratch. We decided to that it would be good enough to use an open source project that got us 80% of the way there, and then customize the 20% to get the rest of the way.
Of course, midway, our client discovers that people at their client, fearing for their jobs, had withheld some crucial requirements. Our one-to-one mapping of the open source software to the problem domain was no longer straightforward.
This is where a consultant has to channel the inner MacGuyver. We needed for the consultant to look in his pocket, take out the piece of gum, foil wrapper, and loose thread and make it happen.
Sometimes, to deliver a product, you need a solution developer, not just a software developer. This consultant was a brilliant software developer, who had hit the high-notes on his pet project. But he could not bring himself to hack together a less than perfect solution.
Now, despite my last name, I chafe at the thought of hacking together a solution rather than executing something cleanly and elegantly designed. But as I pointed out in the past, there is no perfect design. You have to make do with what you have. The perfect design in any situation is one that works within the confines. It may be flawed from software development standards, but if it meets the needs of the client and fits all the constraints, then it is perfect in my book.
The consultants job is to make the client aware of the cost of the sub-optimal design, not to reject the client’s needs.
Sir Tim Berners-Lee starts a blog and it’s a veritable love fest in his comments section.
And why wouldn’t it be? He did invent the World Wide Web after all. What would we be doing for a living if it were’t for the web? Probably still writing code, but still. It would be a slower costlier affair to write code without the benefit of Googling information.
One person commented that the Web would probably have happened anyways, but that misses the point. It may have happened anyways, but perhaps it would have been poorly realized and we’d only now be using a 1993 version of the web (blink tag anyone?).
Remember, Leonardo Da Vince conceptualized the helicopter long before the modern helicopter was invented, but you could hardly call him the inventor of the helicopter. Had he been able to follow through, perhaps we would have had helicopters before the mass produced car. Imagine that? Our world would probably look very different. Sir Tim followed through and we have what we have, warts and all.
Men who engage in online relationships in chatrooms and such are constantly suspicious that the person on the other end is not who they say they are. Often the vision of another middle-aged man looking for action is envisioned. That would’ve been a welcome relief for the guy in this news story.
“I walked out on that dark beach thinking I was going to hook up with the girl of my dreams,” the rattled bachelor later admitted. “And there she was, wearing white shorts and a pink tank top, just like she’d said she would.
“But when I got close, she turned around -- and we both got the shock of our lives. I mean, I didn't know what to say. All I could think was, ‘Oh my God! it’s Mama!’ ”
Windows OneCare Live Beta reports that TestDriven.NET is a virus. Anyone else run into that?
Just browsing around and saw this video of the most amazing soccer juggling skills ever. Yes, that is a screenshot of the guy jump-roping while juggling a soccer ball on his head.
If Joel can do it with FogBugz, I can try and do it with my blog. That “it” being to post a picture of the day.
This is one of many metro entrances in Bilbao, Spain, home of the Guggenheim Bilbao. As I stated in a previous post, Bilbao is full of interesting design touches like these cool entrances.
Strangely enough, we never went in the metro in Bilbao because everything we wanted to see was within walking distance or a short bus ride.
I can’t believe I didn’t notice this when he first published it (I only saw an internal email on it), but
Steve Harman wrote this excellent guide to branching with CVS, complete with an easy to follow diagram.
He created these guidelines for the Subtext project, but they can just as easily apply to any project using CVS as an example of a sound branching policy. Keep in mind that for many branches you may encounter in the wild, you are typically done at Step D. However, in some cases you may want to continue making experimental changes on the same branch (rather than creating a new one), in which case (as the diagram points out), you continue repeating steps B through E.
If anybody out there has some constructive feedback, I am sure Steve would love to hear it. Afterwards, I will try and incorporate this into my Quickstart Guide to Open Source Development With CVS and SourceForge. Happy branching!
In this post, I plan to give out some rough code I hope you find useful. But first, an introduction. Occasionally, in the search to compress more into less space, web designers will create a form in which the text inputs double as labels. For example, this is a login control I wrote for a recent project.
In my mind, this idea making the standard text box perform the double duty of being a label has several usability problems. First of all, in a large enough form, if the user starts filling in data, and then realizes after the fact that he or she made a mistake, the user no longer has any context of what each field represents except the mistaken information they typed. Believe me, it happens.
Secondly, notice that the password textbox displays the word “Password”. Well what happens when the user starts typing his password? With a normal text input, it is there for the world to see. If you use a standard password text input there, then how would you display the label text? It would look like
However, it is important to give the client what they want, and what do I know about web design? So I created a control named
TextBoxLabel that helps resolve some of the usability issues. I need to give some credit to Jon Galloway who showed me one implementation of this idea that spurred me to try and iterate on it and make it even better.
- When the control receives focus, I want the user to be able to begin typing immediately. Originally, I cleared the textbox, but I found that simply selecting its contents works just as well and has the added benefit that you can still see the label when you give the control focus. Also, if you clear the field when it receives focus, you’ll run into problems in pages that automatically give focus to the first text input, since the field will be cleared before the user has a chance to read it.
textInput.defaultValue to do this, but I found one flaw in this approach. What happens if you use this control to edit an existing record. The default value will be the current value, not your label value. To resolve this, I use a custom attribute, “label”. Of course, if you clear the text input, perhaps you do want the original value and not the label value. In my case, that was not the desired behavior.
In order to help maintain context, I made sure to add the
title attribute to the textboxes. It’s a tiny improvement, but by highlighting a textbox with the mouse, a tooltip will show the user the label for the textbox.
I built a very simple demo you can play around with to see the control in action. Pay attention to how the password input changes to a text mask when you start typing in there.
So instead, I created a simple web project that contains the controls and all supporting code files. Since I was at it, I added a few other classes I’ve written about in the past, including one control I haven’t written about. This is a small subset of our internal libraries. Over time I hope to provide more polish to some of our internal controls so I can publish more of it in this project. Here’s a listing of what you will find in this project (in addition to the
It’s not a lot, but it is a start. As these are controls we use internally, they aren’t necessarily the most polished and won’t work in all situations. We do not provide any warranty, liability, nor support for the controls. However, if you make improvements, feel free to let me know and I will incorporate them. You are free to use them in any project, commercial or otherwise.
And before I forget, as I tend to do, here is a link to the code.
The controls do work with the ASP.NET validation controls, but not perfectly. When I say they “work”, I mean they work perfectly when client scripting is disabled. With client scripting enabled, you get some weird behavior. In part, I think this is due to how we hook into the submit event. The timing of method calls is important as the TextBoxLabel clears its value when submitting if the value is the same as the label. This makes sure that on the server side, you do NOT have to compare the value to the label to determine if it is valid. The side-effect of this approach is that if client validation prevents the form post, the textbox is now cleared. I haven’t spent any time to look into a better approach to this.
This morning I woke up with visions of sugar code dancing in my head. It is a coding day and I was ready to sling it, only to be bowled over in stomach pain. Not sure what it was, but it was very unpleasant and wasn’t accompanied by any other symptoms like gas or otherwise.
So I put a heat pack on my stomach and went right back to sleep and just got up and am feeling somewhat better. At least I wasn’t in poor Danah’s shoes. No worshipping of the porcelain god this time.
These days I tend to find the holidays more a burden than something to look forward to. However with my family visiting us this year, I am quite excited. Maybe I’ll put up some lights like this display.
The screenshot doesn’t do the video justice. It has to be seen.
Wesner writes that a couple of readers criticized him for his desire to aspire for greatness. Well obviously Wesner, you should aspire for mediocrity! In any case, one reader comments,
YOU do not get to tell if you are great or not.
And I agree that you do not get to decide if “history” or the public at large considers you to be “great” in whatever definition of that word you mean. However that misses the point entirely. Who gives a rat’s ass what the public thinks.
Wesner’s point is that his life is under his control, not that of others. Therefore it does not really matter whether the public sees him as great. Rather, he will strive for greatness and let the chips fall where they may. At least that’s my take on it, and you know I’m never wrong.
A valuable lesson I learned a long time ago is to behave as if you’ve reached where you want to be. You want to be a better soccer player, adopt the habits and obtain the mindset of a better player. You want to be a better developer, behave like one. This goes beyond simply visualizing your goals and has applications in many facets of life.
My first job out of college was at a very small consulting company. We wanted to grow and be a larger, well organized, well executing company. However there were times I would get frustrated at our progress and our perceived lack of professionalism. It occurred to me one day that I had to stop whining about it and start behaving as if we were already the company we strived to be. So we worked at it, became better organized, and started executing like a more professional firm (certainly with our ups and downs). We started to behave like a well run larger firm and it worked!
Despite all evidence to the contrary, I wasn’t exactly a ladies man growing up, and a lot of it had to do with lack of self confidence. It wasn’t till college that I started to get my “flow” going. In part this was a result of starting to behave in a confident manner as if I was already God’s gift to women. Sure enough, it had an effect. Just ask my wife about the night we met. Perhaps I was a bit too confident. ;)
For me, I’m not necessarily striving for greatness. Greatness is a very vague term. I would prefer well-liked and well-respected. That would do nicely. Just remember, it’s not wrong to strive for greatness or other goals, just behave in a manner of one who has achieved the goals.
One common objection I hear to TDD and writing unit tests is that it creates a lot of extra work to develop software. And this is true, but it does not give a complete picture. TDD and writing and maintaining unit tests do take discipline and do increase the time (thus cost) of writing code. No doubt about it. However, this cost reflects the true cost of writing quality code and lowers the total cost of developing and maintaining software.
Unfortunately on many projects, management looks only at coding milestones to determine how quickly software is progressing. By milestone 1, these ten features must be implemented. What inevitably happens, assuming a tight deadline, is that developers cram and jam to get these features implemented and checked in by the milestone. They reach this milestone, and management checks these items off their project plan and record the time to completion and consider this to be the cost of developing these features.
This is completely wrong and gives a false sense of cost. Inevitably, the more time pressure a developer is to finish a feature, the more likely he or she will introduce bugs. Bugs that may not be caught much later and are much more costly to find and fix then.
Robert Glass points out in his book Facts and Fallacies of Software Engineering that Error removal is the most time-consuming phase of the life cycle. It can account for anywhere from 30 to 40 percent of the time spent coding. However this time is often booked to the task debugging and not booked back to the original feature, giving a true sense of the cost and time involved to implement the feature.
Glass also points out that 80% of the cost to implement a project is spent in the maintenance phase. I don’t know about you, but I’ve had the unenviable task to maintain a large creaky system whereby I would make a change to implement a new feature or fix a bug, and would hope and pray I didn’t break something else in some subtle manner. I would spend way more time trying to test and verify my change than it took to implement the change.
This is where I believe that unit tests ultimately provide their cost savings. They both reduce the true cost of developing a feature and reduce the Total Cost of Ownership (or TCO) of a codebase.
They reduce the true cost of software development by promoting cleaner code with less bugs. They reduce the TCO by documenting how code works and by serving as regression tests, giving maintainers more confidence to make changes to the system.
Remember, as in all writing, consider your audience. The audience for your code is not the compiler, it is the poor maintenance programmer six months from now who has to go in and make a change to the system. Sometimes that poor soul is yourself. Believe me, that person will thank you profusely if the system has sufficient unit tests.
And before I’m misquoted, I want to remind the reader that my predilection for unit tests does not mean that it is a substitute for other forms of testing.
In his post Unit tests are the new documentation Scott sees unit tests as an undue burden much like documentation. Documentation, typically written after the fact, inevitably falls sway to the laws of entropy and becomes hopelessly outdated.
On one level, I do agree that unit tests are the new documentation, but I would add new and improved! Unit tests are a great way to provide code samples to document how an API is to be used. Though agile proponents point out that the code (when well written) is the documentation, well named methods and variables only tell you what it does and what they are used for, but not how to use it. There are several ways that I see unit tests as better than your traditional documentation.
Unit Tests Are Closer To The Code
First of all, unlike traditional documentation sitting in a binder or word doc on the corporate network, your unit tests are typically in a project within the same solution the unit tests test. It is even possible to place the unit tests within the code being tested, but I personally avoid this approach. So it isn’t as close to the code as the code itself, but it is far closer than a word doc sitting on the network somewhere.
Unit Tests Are Hard to Ignore
Once you’ve adopted unit testing and made it a habit, having unit tests get out of synch with your code is hard to ignore. For one thing, unlike documentation, unit tests compile. If they don’t compile, well you know they are out of date. Secondly, if the unit tests compile, but do not pass, then you know they are out of date. Documentation doesn’t provide any sort of notice.
Unit Tests Are Written As You Go
The holy grail of documentation is to write it as you go, but you rarely see that in practice. However in places I have worked that have adopted Test Driven Development, I have not seen this same problem with unit tests. Unit tests are written as you develop. It becomes part of the development process. In part, once a developer sees the value in unit tests, it is not hard to integrate it into his/her programming style.
The Question of Discipline
Many who question or are unfamiliar with unit testing assume that it requires a lot of discipline and will be the first thing to fall out during tight deadlines. But this isn’t necessarily true when TDD is adopted as good software practice. It doesn’t require much more discipline than using source control. These days, I hardly realize source control requires any discipline at all because it is so well integrated into my work style. But if you think about it, it really does take discipline to do it properly. Especially if you employ branching. Likewise TDD does take some discipline, but it becomes second nature. And the benefits are worth it. Documentation, though providing some benefits, requires much more discipline to keep in synch.
I haven’t confirmed this myself, but I believe Scott when he says that the latest version of RSS Bandit changed some of the keyboard settings. In particular he states that to mark a post as read changed from CTRL+M to CTRL+Q.
The reason I didn’t notice is that I am using customized keyboard settings. It isn’t too hard if you use my (unsupported) keyboard setting tool for RSS Bandit.
I wrote up a two-part article about how keyboard settings are implemented, but the only part you really need is part 2 in which I describe a quick and dirty tool for modifying keyboard settings.
This tool simply provides a GUI for modifying the ShortcutSettings.xml file (an embedded resource file available with the source code) and making a copy of it to the following directory: C:\Documents and Settings\YOUR_USER_NAME\Application Data\RssBandit\ShortcutSettings.xml. Once there, new installations shouldn’t override your custom keyboard settings.
Sam Gentile is preaching and I am in the choir. I’ve talked about the benefits of unit testing and refactoring in the past, but Sam makes this great point.
BDUF makes a huge gamble that all the business and development people can think of all the X's up front in the "requirements" stage. In my 22 years of software development, I have very rarely seen that this is the case, Why? Many the aspects of design of software and the problem are completely unknown until one begins to write the test or the code. Code speaks to you. It tells you which way to go. Often we need to learn what its saying, upgrade our original understandings. Thats why Red-Green-Refactor works so well. You think a bit, write a test, write some code, and then refactor it based on the new learnings that you have made while doing it.
This is in response to the critics of refactoring and TDD who suggest that software developers simply spend more time thinking about the code up front in order to produce better code. But as Sam points out, what use is better code if it does the wrong thing?
And this point is crucial. When you wrote the code, it may well be doing the right thing. But somewhere down the line, some biz dev guy is going to realize what he sold the client is completely different than what he told you. Now your correct code is incorrect and you don’t have the safety net of unit tests to help you refactor the code to now correct thing. This, Virginia, is how the real world works.
In case you were wondering, this is where my wife and I will be spending our New Years Eve this year. Some of the highlights of the expansive line-up include John Digweed, Christopher Lawrence, The Crystal Method, Miguel Migs, Muytaytor and Black Eyed Peas (though they seem a bit out of place, they are a hot ticket).
This is one of them big-fangled parties, taking up six blocks in downtown Los Angeles. Yeah, there will be a lot of people (maybe even too many), but this particular party has sentimental value since it is the party my wife and I met at in 2001/2002. We’ll make sure to ride the ferris wheel.
In part, I post this to make Jayson jealous.
Apparently I am quite sensitive to jet lag. My wife has been cheerful, upbeat, and energetic, while I’ve come very close to biting the heads of little babies and throwing my own feces on the wall. Yeah, it’s that bad.
In this dazed catatonic state, I’ve found my mind to be a blank slate. Not the good kind of blank slate which implies a fresh start. No, I am talking about that dreary empty slate that means I am bereft of ideas. Tap on my head and you hear an endless echoing inside.
The end result is that I am suffering (and “suffering” is not too strong a word my friend) from Bloggers Block. My friend Jon tells me he has five unfinished posts and notes for at least 50. I checked my notes and I have about zilch ideas waiting in the wings.
The best way to beat writer’s block is to write. Anything. So there you have it. I am making you, the reader, suffer through this mindless drivel, so I can remove a block. Interesting content will follow in the future. One hopes.