In 2005, the .NET Framework had its 1.1 SP1 release and was relatively stable. Visual Studio .NET 2003 was a solid release. C# was being widely adopted throughout the industry. Selecting it for a project cost me my job, and nearly sunk my career as a software developer.
This was almost two decades ago, so I feel comfortable discussing it now. I was working as a software developer at Hewlett-Packard in Nashua, New Hampshire, USA. HP had recently merged with Compaq, and absorbed the office buildings and personnel that were once Compaq, and Digital Equipment Corp. before that. Our project was called ActiveAnswers, a Content Management System (CMS) that existed before the term was coined.
When I joined Compaq in 2000, ActiveAnswers was a set of HTML templates and text files that were converted into a massive static web site every night. During the day, content editors would make changes by editing the text files. The site used dozens of Perl scripts to combine the content from the text files with the HTML templates.
Over the next couple of years, my team of five people had completely rewritten the application into a mostly WYSIWYG UI that permitted our content editors to make changes directly in a web browser, seeing the results almost immediately. All of the content was stored in a SQL Server database. The front end code was written in VB 6, and was starting to feel a little overweight.
We had adopted many of the practices of the newly-released eXtreme Programming methodology. The project had automated unit tests and daily (if not continuous) builds. We even built a pair-programming lab. I wish I still had pictures, because doing that in 1999 was a sight to behold. We had taken over a former QA lab. It was about 16 x 24 feet, with windows on the long walls, and it had a locking door. We set up stations around the perimeter of the room, each consisting of a laptop docking station, a 21” monitor, keyboard, mouse, and two chairs. Each station had plenty of room for two without crowding the adjacent station. In the center of the room was a conference table with room for all of us.
HP “Merges” with Compaq
Not long after, Hewlett-Packard decided that they needed to be bigger than Dell. So instead of competing with Dell head-to-head, they decided to get bigger the new-fashioned way: they bought another company. The new company was indeed larger than Dell – for about six months.
As soon as the deal closed, the new HP (NYSE: HPQ) was the #1 computer maker in the world. Within six months, however, Dell had regained its #1 position and dropped HP to a solid #2. HP was suddenly in trouble, being dragged down by a bloated Compaq organization. That was their story, at least.
It was time to cut away some of the bloat. HP announced a 10% “reduction in workforce.” I suppose they call it that because it sounds better than a “lay off.” It also sounds better than “you’re fired!”
Amazingly, most of the people with whom I worked did not seem to care. In fact, many were excited by the prospect of getting a great “layoff package.” In case you are not familiar with these, a layoff package is money given to the suddenly out-of-a-job employee. In my case, only having been an employee for two years, I was only eligible for six weeks of pay.
After the merger, the team and project experienced some significant growing pains. Executives at HP had seen ActiveAnswers and wanted to expand its reach. They wanted to ensure the team could handle the additional workload.
All of the contractors on the team were made a similar offer: accept a full-time job with HP at a reduced pay rate, or be replaced. A few of us chose to remain. One colleague in particular, who was instrumental in designing and building the application’s UI, chose to leave. He was unceremoniously replaced with two junior contractors who combined were far less effective than he had been. Although we had more work to do, morale was low for those who remained.
Outgrowing Visual Basic
Over the next few years, our team of five grew to 20. Four times the size does not equate to four times the productivity. In many ways, we seemed to be much less effective. We struggled to keep up with the ever-expanding business requirements. Feature after feature was requested. New users and new content were added, putting a strain on an architecture that had been built for fewer than a dozen users. Training demands increased. The venerable VB6 was showing its age. It was time for something new.
The company provided all of its developers with an MSDN Subscription, and a few us were excited by the release of Visual Studio 2003. Windows XP was still fresh, and the two seemed to work flawlessly together. We decided to start experimenting with .NET and C# to see whether we could provide the users with the features and the performance they needed.
Initial Proof of Concept
At first, the idea of switching to a newer technology was met with mild curiosity. The leadership authorized a proof of concept. “Go do something and then show the rest of the team.”
We decided to hire a contractor with proven experience in .NET, though the fact that it was only a couple of years old made this difficult. We found a local consultant who had been using it since its introduction.
One of the tasks we assigned to him was to review our new .NET code and let us know where and how it could be improved.
Try/Catch as Flow Control
One of the first things he uncovered was large blocks of nested try/catch statements used to implement complex flow control. One instance he found was a single function with six or seven nested try/catch blocks. When asked about it, the developer who had implemented the function said he had heard that if/then was inefficient, so he used try/catch instead. No amount of persuasion could convince him that he had it backwards.
For Every Rule There is an Exception
Speaking of try/catch, every time an exception was caught, it was swallowed, and a new exception was thrown in its place. The pattern in .NET is to catch only those exceptions you can handle. The rest should bubble up naturally to higher levels of your application. It is acceptable to catch and rethrow, but there are only a few specific ways to do that. Throwing a brand new exception is not usually one of them. Trying to explain that to the other developers resulted in repeated explanations that it was the consultant who did not understand. My favorite line from those meetings was, “Let me say it again so you’ll understand.”
One of the improvements that had been made was the implementation of a set of web services. Our consultant discovered that every web service call was preceded by a separate call to an endpoint called “IsUp” to ensure the web server was listening, before making the actual call.
In 2005, bandwidth was not quite what it is in 2020, and each call was relatively expensive. Not only was this wasteful, it also did not accomplish its goal. On more than one occasion, IsUp would return true, and the next call would fail anyway due to the service being down.
Upon learning about this revelation, our management decided it would probably not hurt anything to leave it in place.
Everyone Into the Pool
One of the benefits .NET offered was robust database connection pooling. The pattern Microsoft suggested was to create an ADO.NET connection object every time you needed one, and release it immediately when you have finished using it. The system would maintain a pool of connections behind the scenes for you.
Rather than using ADO.NET, however, one of our contractors decided that it would make more sense to roll his own connection pooling system. When our new consultant pointed this out, he was accused of not understanding the subtle advantages our own pooling system had over Microsoft’s.
Turning the Money Crank
After a few weeks of this, our new consultant was beyond frustrated. We sat down and had a heart-to-heart talk. He felt he was adding no value to the project or the team. His suggestions were ignored or belittled. In fact, my manager essentially told him that his services were no longer required, and that his contract would not be renewed. I asked him whether he would stick around until it ended. His reply was amusing. He said that although he could stay and continue to “turn the money crank,” he felt that doing so would compromise his professional integrity. Six weeks after he started, our consultant left.
Right about the time our .NET consultant left, the word came down from management that our .NET experiment was a failure, and that we were to go back to VB 6 for all new code.
A few short weeks later, we were having a particularly difficult problem with one of our application components. VB simply did not have the language facilities to deal with this particular issue without massive brute-force coding. C#, on the other hand, had a very straightforward way to solve the problem.
I finally made the decision to implement that particular component in C#. My plan was to show management that .NET was still a viable option for our project, and this small enhancement would be the proof. The solution was everything I had hoped it would be: short, elegant, and easy to understand.
At this point in the story, I wish I still had the source code that I could share. However, I learned the hard way not to keep source code when leaving a company.
The Phone Call
We had a policy on our team that each new feature would be revealed on a team-wide NetMeeting conference, attended by anyone interested. The primary developer on the feature would explain it, show the passing unit tests, demonstrate the feature, and then answer questions from the rest of the team. We had these meetings a few times per week, as I recall.
This call was my time to shine, or so I imagined. I went through all of the normal steps, and all was going well. There were four critical things about this particular call that will soon become apparent:
- Most of the team was on the call, about 25 in total.
- My manager was in attendance.
- HP’s enterprise architect was in attendance.
- I had initiated the call.
I completed my demonstration and was feeling pretty good. Everyone agreed that the functionality was correct and what the business needed.
During the Q&A, most of my peers wanted to see the code. I was happy to oblige, excited to be able to have concrete proof that C# was a good fit for our project. I was finally excited again by the project and eager to help the rest of the team adopt .NET where appropriate for future features.
While showing off the elegant code I had demonstrated, the Enterprise Architect interrupted me. “I thought we weren’t using .NET anymore. Why did you use .NET?” I was actually prepared for that, though I did not expect it to come from him. In fact, he had been one of my strongest early supporters. I felt a bit flustered now that I had lost someone I had perceived as an ally.
I gathered my thoughts, and then began describing how difficult and convoluted the VB6 solution would have been, and that C# offered the perfect solution. I again walked through the code, noting where C# provided abilities that VB6 simply did not offer us. I ended by suggesting that although I was aware of the moratorium on .NET, as the senior developer on the project, I felt it was within my purview to take risks and show where decisions might need to be reconsidered.
That explanation was not good enough. The architect proceeded to berate me verbally in front of my peers for the next few minutes, making it absolutely clear that I had no such authority. My .NET code was not to be used; someone else would be assigned to rewrite it in VB6. Furthermore, from that point forward, all decisions about the project’s direction, architecture, or code patterns would no longer belong to me. One of our contractors, the one who insisted on writing his own connection pooling system, was assigned to be the gatekeeper of all such decisions.
No one was speaking. It was dead quiet. I think everyone was as stunned by the turn of events as I was. Most of my team was aware of my code and liked it. They thought it was a fantastic solution. Only management seemed upset. At that point I did something that probably sealed my fate, though it took a few days for the fallout to reach me completely. I took a deep breath, and apologized. I still remember my words. “I’m sorry, [name redacted]. I honestly felt this was the best solution for the project and the team. Given the choices I had, I did what I thought was best. I won’t make that mistake again.” And I hung up.
Remember what I said above? That I initiated the call? NetMeeting was a little more brutal than today’s conference call systems. When the initiator left the meeting, it ended abruptly. So not only did I hang up on the architect, I inadvertently killed the entire meeting.
As I said, it took a few days for the fallout to reach me. Most HP executives were in Palo Alto, California. You cannot get much farther from Nashua, New Hampshire, and still be in the continental United States. For us in the Northeast office, things went on pretty normally for the next couple of days.
The “Correct” Version
The only thing we heard in that time was that a different contractor had been assigned to rewrite my code “correctly,” meaning in VB6. However, it was not as simple as everyone thought. As it turns out, the contractor was unable to replicate it in VB6. After a few days of frustration, she came to me for help. We pair-programmed a solution in VB6 that afternoon. Her solution was immediately accepted and praised for its genius. I kept my mouth shut on that call.
Finally, about a week after my fateful meeting, my manager set up a call with me to discuss my punishment. First, she assured me that I would not be fired over my indiscretion. However, I would be on probation for 12 months, effective immediately. That would mean I could not be promoted, would not receive a pay increase, nor could I look for another job within the company. I was effectively placed in “time out.”
It was then I made a decision I had been contemplating ever since our consultant mentioned “turning the money crank.” I wondered how long I could allow my career to stagnate. Would having years and years of VB6 on my résumé ever be seen as valuable? I suspected not.
I told her that I was going to save her some paperwork and offered my two-week notice of resignation on the spot. She seemed surprised by this, offered some half-hearted objections, and eventually negotiated an additional two weeks out of me. I walked out the door for the final time a month later.
Looking back on this experience has made me realize a few things. It was not really .NET that led to me leaving HP. That was merely the excuse. The truth is I had been unhappy there for quite some time, and I was looking for a reason to leave. Could I have done things better? No doubt. I believe that I have grown and matured in the intervening years.
I am sure I would handle the situation much differently today, probably by providing both solutions. This would have given my leadership what they wanted, but also allowed me to demonstrate a direct side-by-side comparison of both options. It is highly likely that my alternative still would have been rejected, but at least that approach would be more professional. That is a significant lesson, not only for me, but hopefully for my readers.
This story is significant in another way. This incident marked what turned out to be the end of the “First Half” of my career. I left software development completely for a while, sold my house, and moved to a remote part of the state. I spent the next few years trying and failing to be a real estate investor. That, however, is a story for another time.
Do you have any comments, questions, or just want to see more? Please follow me on Twitter and let me know.
Did I make any mistakes in this post? Feel free to suggest an edit.