Friday, September 17, 2010

On-time, thoroughly tested, and on budget: pick two

I'm sure many of you in the the corporate would know the age-old conundrum of the post subject. It's difficult to deliver all the right fixes on the original schedule and budget for pretty much any project. No matter how much we expect the unexpected there will always be even more unexpected issues to derail the schedule.

So how do you decide when to ship? We are performing a major rewrite of a component for our upcoming release and discovered an existing issue that would be very costly to fix. Now, we have three options: (1) fix it poorly, likely breaking something else in the process, (2) fix it correctly and delay the release, or (3) don't fix it in this release but slate it for future work.

My manager and I have opted for number three after careful consideration. The driving factors were the value of the other improvements to the component even without this fix and the time constraints on other work included in the release. As soon as slipping the timeline became a non-starter we were left with one very dangerous choice and one safer. Since we're working with patient data and using the information to drive patient care, safety wins almost always.

How do your teams decide when to hack around, when to slip, and when to delay?

Tuesday, August 3, 2010

Flow of control

I'm sure most experienced programmers already know that using exceptions for flow of control in a program is highly inefficient. The time it takes to unwind the stack alone is ridiculous, let alone the fact that compilers don't tend to optimize for exception paths. The question is then what to replace it with? Do you set status and return an empty or a null? Do you always return a "result" object that includes both the result state and any return types?

My team is working on updating our shared components' architecture and are considering this question as we go. We've decided to move towards returning a result object and having "out" parameters for most of the new methods we're writing. While not ideal, this does mean we always use the same type of return value. We could also create subclasses of that return type with more propoerties instead of using out parameters.

At the same time, I'm working on creating some unit tests for our new code and building both the "happy path" tests and the tests that supply null, empty, and otherwise invalid values. I do like the idea of not throwing exceptions unless something truely exceptional has occured but we can swing too far in that direction, getting ourselves into unknown states or overly complicating the program logic to the point where it constantly checks system state instead of simply executing. Trade offs all around, I suppose.