software development
Multiple meanings of test-driven development
This Roy Osherove post surprised me because I hadn’t been aware of so many different interpretations of the idea before. Because I’ve always believed in at least some design up front, my understanding of TDD was the first of four mentioned:
"Test Driven Development: the idea of writing your code in a test first manner. You may already have an existing design in place."The fourth interpretation of TDD applies pretty well to what I do now whenever I inherit an application. Writing unit tests of the middle tier(s) of the application (if none exist) has proven to be very helpful whenever I've done this. Adding new features becomes easier, and regression testing becomes much easier.
Reactions to inherited code
This entertaining Phil Haack post on inherited code definitely tells the truth when it says:
"Here’s the dirty little secret about being a software developer. No matter how good the code you write is, it’s crap to another developer."Until I read this post, I hadn't even thought about the thousands of lines of code I've left behind at various employers and how my successors regarded them. I remember getting very positive feedback from a colleague who wrote the .NET replacement for my VB6/COM+/SQL Server 2000 implementation of our online recruitment tool, but that's it. My usual reaction to code I've inherited has rarely been empathetic. Phil's right in trying to be more understanding. And to anyone who has inherited my code in the past, I hope I didn't make your job too hard.
Between in T-SQL isn't truly inclusive for dates
I’d forgotten this when writing a stored procedure to provide access to log entries in a database table. This older post describes the problem, and two options for fixing it. I chose the version that uses the DATEADD() function call for my stored procedure.
Theory D or Theory P?
Earlier today, I came across this excellent post by Reginald Braithwaite on the management of software development. It does a great job of explaining many of the projects I’ve worked on in my career, whether they succeeded or not. Theory D clearly drove how I and various teammates ended up working. The post really helped me understand part of why the two years I spent managing projects was so difficult. I’m a Theory P guy at heart, and couldn’t pretend to be Theory D (much less actually believe it).
Braithwaite also writes a good follow up.
I really hate SQLDataSource
What I said about hating ObjectDataSource doesn’t count. SQLDataSource is worse. At least ObjectDataSource gives you error messages when it isn’t working. SQLDataSource appears not to work at all with stored procedures that have parameters. I found this forum thread that seemed to describe my problem. Unfortunately, none of the tactics suggested worked for me. I don’t even get error messages, just a screen with no GridView control in it. One of my colleagues looked at it and was just as stumped as I am.
Using an XSD, a couple lines of code, and an ObjectDataSource got me the result I needed with far less hassle.
NCover goes corporate
I was on vacation when this happened, but NCover has become a product you pay for. The rationale for the change is a fair one, and I’m impressed by how Gnoso (the vendor of NCover) is looking out for people who donated to the project when it was free. NCover 1.58 remains free, but doesn’t have the same level of features as NCover 2.0 (or 2.0 Enterprise).
Gnoso has that product niche basically themselves since Cenqua, the vendor of Clover.NET, got bought by Atlassian in August. Since Atlassian is end-of-lifing Clover.NET, the coverage tool bundled with Team Foundation Server is the only option for .NET code coverage functionality. Given the choice between paying for functionality that used to be free and losing it altogether (as happened with NDoc), I’d fork over the dough in at least some cases. Whatever they intend to charge, odds are they won’t be Microsoft prices. It will be interesting to see how many other tools that are currently free make a similar transition.
Lessons from failure
It’s an older Reg Braithwaite post, but an excellent one. His four most important causes of failure are all painfully familiar. The paragraphs he writes on hiring practices and “development hygiene” are especially important. In an environment where the cheapest vendor wins, those two areas are the source of many problems.
The post does a very good job of pointing out how weak stakeholders can doom a project. There’s also a clear example of how office politics can play havoc with outcomes.
It’s a pretty long post, but very worthwhile reading.
I hate DTS
I’ve spent a good chunk of this week trying to revise some DTS packages to account for changes in how MapQuest provides access to data they’ve geocoded for us. Since I haven’t used it in years, I’d forgotten how much I dislike the user interface for it. It probably didn’t help that I was trying to edit this things with a plug-in you install for SQL Server 2005.
Trying to have separate development and test environments to avoid the horrors of doing development and testing in a production environment is quite a trial also. I think you can put settings in a configuration file, but it’s probably something like an INI file.
It’s probably just as well that DTS was replaced by SSIS. I did use that to do a bit of flat file validation for the same project and didn’t find it nearly as painful to use.
Improving developers
Scott Hanselman posts a number of great tips for improving development teams. The technical brown bag idea is one we’ve been following at work since the spring. We call them “learning lunches”, and they’ve proven to be an excellent vehicle for knowledge transfer, as well as connecting different offices of the company.
At my current employer and the previous one, I’ve tried to promote conferences, off-site training, and .NET user groups. Getting the staff to attend them has been more of a challenge here than at my last job. They’re all excellent ways of keeping technical skills sharp as well as networking opportunities.
Now that we have a new CIO at work, it will be interesting to see to what degree he’d buy in to some of these ideas.
To rewrite, or not to rewrite?
This question comes up rather often in my job, and this post by Adam Turoff answers the question by including “when” as a variable. In short, the sooner a project needs to succeed, the less likely it is that a rewrite will succeed.
Whenever I come across an application that isn’t designed or implemented as well as it should be, I’m biased in favor of rewriting the application. That approach tends to meet resistance because the “when” is usually very short. Refactoring is a good fallback option, but only if the application is relatively current. My desire to refactor single-tier classic ASP is nil.
Leading by example
I found this post on technical leadership particularly useful because it’s my role at work. Humility, discretion, tact, and willingness to “walk the walk” are necessary to succeed as a leader. The only thing I would add to the author’s list is the importance of patience in leading development staff. You can follow all the advice and still not see changes for awhile. I’ve been in that situation before, and always found it frustrating.
The comments on the post were enlightening as well, particularly this one by Greg Askew:
"Individuals are responsible for fixing themselves. Leading by example is a noble concept, but at the end of the day everyone is accountable for their own performance."The quote is a great reminder that as managers, we can only influence--not control--employees. Askew makes two other strong arguments about hiring and motivation. His latter point is echoed by Steven McConnell's summary of classic mistakes and by Jim Collins in Good to Great. Undermining people's motivation (and/or hiring people who aren't self-motivated) can be counted on to yield a substandard result in the end.
The full article that inspired Jeff Atwood’s post is an excellent read as well.
No parameterless constructor defined for this object.
This error message started showing up during testing of some code changes I made to an application. It took me awhile to figure out precisely what the problem was because the top of the stack trace referred to this:
System.Activator.CreateInstance[T]()As looked further down the stack trace, it ultimately pointed out which class was the culprit, so I added an empty public constructor to and redeployed the result.
I found this post rather useful in diagnosing the problem.
Refactoring
An excellent post by Julian Bucknall of Developer Express on refactoring–more specifically the eight refactorings he uses most. Of the ones he names, I use the 8th one (use string.format) the most. As you might expect with inherited code, there are plenty of places where strings are concatenated with plus signs. I root them out of every piece of code I rewrite, and highlight them in code reviews.
SQL Server Table Properties
I needed a T-SQL statement to get the created date of a couple of tables as part of a project. One of my colleagues came up with this query:
SELECT create_date FROM sys.objects WHERE type = ‘U’ AND name = ‘<tablename>’
It works in SQL Server 2005.
The SQL Server 2000 equivalent is:
SELECT crdate FROM sysobjects WHERE xtype = ‘U’ and name = ‘<tablename>’
Jeremy D. Miller on Software Teams
His top three preferences in brief:
- internalized discipline over externally-enforced discipline
- coaching over enforcement
- collaboration over direction
Miller does the best job of explaining his third preference. Providing the rationale and context for a course of action gives a developer input and an opportunity to buy into an idea. The success of this approach still depends on the having the right people. I follow it with my own employees as much as possible.
Is Fit Testing Dead?
Jeremy Miller asks that question in this post.
I haven’t had a chance to use it on any projects, but I really like the idea of customer-facing tests. Miller describes them very well as “executable requirements”. The comments highlight a number of alternatives to Fit, including FitNesse, Green Pepper, and ZiBreve.
From the comment volume on Miller’s post, it seems that only the specific implementation of Fit is on its way out. The idea looks very much alive.
Implementing IDisposable
One of the FxCop rule violations I found in one of my projects had to do with IDisposable not being implemented. My search for examples of how to resolve this yielded a lot of helpful links, including these:
- An MSDN article on correct implementation of IDisposable
- A older CodeProject article on IDisposable that takes an odd shot at unit testing
- A newer CodeProject article on IDisposable and the dispose pattern
- A Channel9 discussion on IDisposable
Comma-delimited strings in SQL with COALESCE
I came across a nice how-to post this morning. When it comes to databases, I’m a fan of anything that eliminates the need to use cursors.
ALT.NET-->NOT.NET?
I came across this James Avery post via Mike Gunderloy’s blog. Avery attempts to make a similar point to one Martin Fowler puts forward about the best developers moving away from the .NET platform. Beyond the sort of anecdotal evidence I’ve read, I don’t see much abandonment of .NET as a platform.
When I read this post by Dave Laribee, I decided that Avery missed his point. The point of ALT.NET isn’t as a bridge to a different set of tools, but to recognize two things:
- The best solutions on the .NET platform won't always come from Microsoft.
- The best ideas from other software development communities can work very well on the .NET platform.
Strongly-typed datasets and queries without matching select clauses
I learned an annoying lesson about these late last week. I’d created the dataset by dragging and dropping the necessary tables from SQL Server in Visual Studio 2005. Then I added a query to one of the tables that didn’t include every one of its columns. Unfortunately, a number of the columns my query didn’t return didn’t allow nulls. I ended up modifying my query to include those columns, even though I don’t use them. I didn’t try removing the columns from the dataset, but that probably would have worked too.