Last week provided our office with an inconvenient lesson in what can happen when third-party dependencies break in unanticipated ways. PostSharp is a key third-party dependency in the line of business web application we sell. On the morning of May 20, our continuous integration server (we use TeamCity) began indicating a build failure with the following message:
- PostSharp.3.1.34\tools\PostSharp.targets(313, 5): error MSB6006: “postsharp.4.0-x86.exe” exited with code -199.
The changed file was a Razor template file–nothing at all to do with PostSharp. Only one person on our development team was experiencing this error on their local machine, but the end result–not being able to compile the solution locally–pretty much eliminated the possibility of that person being productive for the rest of the day. As the day progressed, the CI server began showing exactly the same error in other branches–even with no changes to code. It wasn’t until the next day that we received the explanation (and a resolution).
Reading the entire explanation is worthwhile, but the key reason for the failure is this:
“we … assumed that all failures would be in the form of a managed exceptions. We did not anticipate that the library would terminate the process.”
The fail-safe code that PostSharp implemented around a third-party licensing component assumed all failures would be managed exceptions (which they could catch and deal with accordingly). Instead, this third-party component simply terminated the process. The end result–any of their customers using the latest version of PostSharp couldn’t compile any solution that included it. There’s no way of knowing for sure how many hours of productivity (and money) was lost as a result of this component, but the amounts were probably significant. To his credit, the CEO apologized, his development team removed the offending dependency and sacrificed the feature which depended on it.
There are many lessons to be learned (or re-learned) from what we experienced with PostSharp, but I’ll talk about three. First, if a third-party dependency is critical to your application and has a licensing option that includes support, it is best to pay the money so that you have recourse if and when there’s an issue. On the Microsoft stack, this is proving increasing costly as more third-party .NET libraries and tools raise their prices (there are quite a few formerly free .NET tools that have been purchased by companies and re-released as rather costly closed-source software).
Second, whether or not there are licensing costs, it’s a good idea to have more than one option for critical third-party dependencies. In the case of aspect-oriented programming on .NET, there are a number of alternatives to PostSharp. The vendor is even confident enough to list them on their website. So if licensing costs are significant enough a concern, it may be better to choose an open-source option that is less-convenient but gives you the ability to customize it than a paid option which doesn’t (and yokes you to a specific vendor).
Third, It may make sense to avoid taking on a third-party dependency altogether. When it comes to the Microsoft stack, it’s likely that they offer a framework or API with at least some of the capabilities you need for your solution. In the case of AOP, Microsoft offers Unity to support those capabilities. Especially in the case where you’re only considering the free tier of capabilities for a third-party dependency where Microsoft offers a product, if that free tier functionality isn’t a significant improvement, it may be best to stick with the Microsoft option.