flow.
"Flow is a condition of deep, nearly meditative involvement." - Tom DeMarco

What Investing Can Teach You About Software Development (Part 2)

In a previous post I talked about what investing can teach you about Software Development.  Specifically, I talked about understanding how the possible strategies of the big players in the technology industry can change the industry landscape and thus change the world your product lives in, as well as how it interacts with those products that co-inhabit that space.  Today I want to look at how these same ideas can help you choose the best vendor for integration into your product. 

Very few commercial products go to market today without the help of a third-party vendor.  There is a rich ecosystem of vendors out there and most decently sized products must lean on at least one of those vendors to fill a particular niche in their own product.  Although leaning on a third party vendor can save you countless development hours, both in initial development as well as maintenance and optimizations down the road, it also opens you up to a significant amount of risk because now your product contains components whose future you no longer directly control.

This risk is directly proportional to the level of integration that your product has with that vendor’s component.  For example, using a third party compression library to save disk space when archiving files typically presents little risk, especially if the compression library is using a standard format, such as GZip, for compression.  This is because a small utility like this can easily be abstracted away behind an interface greatly lessening the coupling between the tool and your code.  Also, you’re users are unlikely to interact directly with this utility so it’s not established as a key identifier of your product.  Sure, they may be aware that some of their files are archived off to disk for later use, but they likely don’t interact with those files directly or think about how it’s done.  Simply put, the archiving a files is secondary to the use of your product.

Contrast this, however, with a deeply integrated third party component such as a UX component library.  Although using a vendor’s flashy components to build the user interface of your product can greatly differentiate your product’s presentation layer giving you a significant advantage in the marketplace, you also greatly increase your risk by relying on another vendor’s components to build your presentation layer.  How great of a risk?  Well, simply ask yourself “What would happen to my product if I suddenly couldn’t use this vendor’s components anymore?”.  These products define your presentation layer, thus defining your product’s identity with your users.  Suddenly changing the components that make up your presentation layer can not only potentially forfeit the branding that you’ve worked so hard to build with your users but it can also result in significant costs surrounding the redesigning of training materials and curriculum as well as documentation.

And of course, this all pales compared with the cost of painfully extracting your vendor’s component code from your own codebase.  Sure, you could also abstract a UX library behind a generic interface like your could a compression library, but the cost and complexity of doing such a thing could easily outweigh any potential benefits that you would get down the road.  Also, whereas a compression library is basically an generic utility, UX vendors pride themselves on the unique controls and capabilities that they offer over their competitors.  While you could abstract these capabilities away, you risk either not being able to use these advanced features for fear that your next vendor won’t offer a corresponding feature, or taking advantage of them at the risk that you’ll need to remove or replace this feature altogether with something comparable from another vendor.

So, how do you mitigate this risk?  Well, first of all you should become a connoisseur of vendor licensing agreements.  Understand every detail of exactly what you are and aren’t allowed to do with your vendor’s components.  Can you still redistribute the components after you stop paying for your developer licenses?  How liable are you for a flaw discovered in the vendor’s components?  This is called indemnification and can be a big deal when you’re working with lot of components. Also, can you buy the component with source code included?  If you can, is it only for reference and debugging purposes or can alter the component’s using the source to suit your needs.

Beyond the technical information, look at the company from a business perspective.  Is the company publicly traded?  If so, then excellent.  Publicly traded companies are required to make their financial status publicly available, this can be invaluable information when you are trying to judge whether or not a company will still be around to support their product for years to come. 

Even if your vendor is not publicly traded and you can’t see their financials, you can still glean a good bit of information from simply looking at their product line and website.  Do they seem to be continually innovating new products or has their product line languished?  For example, if you are shopping for Windows Forms controls and the last two releases of the vendor’s Windows Forms suite seem to have only been maintenance releases with little new features whereas their ASP.NET suite is doubling in size each year, then this is likely an indicator that this company has shifted focus from their Windows Forms suite in order to focus on ASP.NET and may potentially drop the entire line in the future leaving you stranded. 

How about job postings?  The number of jobs a vendors has posted may not necessarily be a good indicator of it’s health, but if there are jobs posted then examining the skills required can be a great hint to the company’s future product strategy.  Our fictional company above only had an ASP.NET suite of components and a languishing Windows Forms suite of components.  But wait, it looks like they’re recruiting software developers with WPF experience.  This is probably a good indicator that company will have a WPF or Silverlight suite of controls in their future.  This may sound crazy, but it’s actually a very common technique for many Microsoft analysts to use when trying to predict the Redmond Monster’s next big move.

And speaking of the Redmond Monster, don’t forget, these same techniques can also be applied to the future of .NET as well.  There’s a ton of information available on the web as to where Microsoft may be taking it’s respective platforms, not the least of which are the quarterly earnings calls that Steve Ballmer and company give to shareholders.  The same rules apply, only on a much grander scale.

While none of these techniques can guarantee you won’t be burnt by a vendor’s product decision someday, they’re likely you’re best tool for planning ahead and mitigating your risk, short of a crystal ball.  Commercial software development inevitably comes with risk, but it’s up to you how you handle it.

Slides and Code from Pittsburgh ALT.NET ‘IoC with Windsor’’ Presentation

Thanks for everyone who came out for today’s Pittsburgh ALT.NET presentation on “Inversion of Control with Windsor.”

I’ve uploaded the code (as we left it today), my PowerPoint deck, and notes.  You’ll notice from the slides that we deviated quite a bit from the original agenda but that’s OK since I think it morphed into a much more interesting conversation anyway.  You can download everything from here.

Also, here are links to some of the technologies we talked about today…

Don’t forget to stay tuned to the mailing list and wiki for announcements of future meetings.  Or, if you have any ideas for future meetings just place them on our UserVoice page for all to see!

Mystery Code Theater Presents ‘Dr. Serializer and the Case of the Mysterious Failing Unit Tests”

Here’s a really tricky issue that we just figured out today, hopefully this will help someone else out, as well.

Our product has a Favorites feature that allows you to save your favorite reports configured just how you like them, much how you would bookmark a page in a web browser.  This is essentially handled behind the scenes using XML serialization of a settings object.  Recently, we decided to replace the XML serializer with a binary serializer for maintainability reasons. 

The new implementation of the Favorites feature using binary serialization was built using TDD so we ended up with a full suite of unit tests around the serialization engine.  However, about once a week or so, a few of the unit tests for the engine would suddenly start to fail. 

One of the tests in question looked something like this…

   1: private readonly DummySettings _dummySettings = new DummySettings { IsSelected = false, Title = "My Title" };
   2: private readonly byte[] _serializedDummySettings =
   3:     new byte[]
   4:         {
   5:            0, 1, 0, 0, 0, 255, 255, 255, 255, 1, 0, 0, 0, 0, 0, 0, 0, 12, 2, 0, 0, 0, 92, 77, 97, 116, 114, 105, 120, 46, 68, 
   6:            97, 116, 97, 46, 85, 110, 105, 116, 84, 101, 115, 116, 115, 44, 32, 86, 101, 114, 115, 105, 111, 110, 61, 49, 46, 
   7:            51, 46, 49, 46, 49, 51, 55, 53, 55, 44, 32, 67, 117, 108, 116, 117, 114, 101, 61, 110, 101, 117, 116, 114, 97, 108, 
   8:            44, 32, 80, 117, 98, 108, 105, 99, 75, 101, 121, 84, 111, 107, 101, 110, 61, 101, 50, 53, 48, 50, 97, 50, 54, 48, 
   9:            51, 50, 99, 54, 98, 54, 97, 5, 1, 0, 0, 0, 47, 77, 97, 116, 114, 105, 120, 46, 68, 97, 116, 97, 46, 85, 110, 105, 
  10:            116, 84, 101, 115, 116, 115, 46, 70, 105, 108, 101, 67, 97, 98, 105, 110, 101, 116, 46, 68, 117, 109, 109, 121, 83, 
  11:            101, 116, 116, 105, 110, 103, 115, 2, 0, 0, 0, 22, 60, 84, 105, 116, 108, 101, 62, 107, 95, 95, 66, 97, 99, 107, 
  12:            105, 110, 103, 70, 105, 101, 108, 100, 27, 60, 73, 115, 83, 101, 108, 101, 99, 116, 101, 100, 62, 107, 95, 95, 66, 
  13:            97, 99, 107, 105, 110, 103, 70, 105, 101, 108, 100, 1, 0, 1, 2, 0, 0, 0, 6, 3, 0, 0, 0, 8, 77, 121, 32, 84, 105, 
  14:            116, 108, 101, 0, 11
  15:         };
  16:  
  17: [Test]
  19: public void Can_serialize_a_settings_object()
  20: {
  21:     var settingsSerializer = new SettingsSerializer();
  22:     var serializedData = settingsSerializer.Serialize(_dummySettings);
  23:  
  24:  
  25:     Assert.AreEqual(_serializedDummySettings, serializedData);
  26: }

 

It’s a very simple test, it simply serializes a dummy object and compares the results to a byte array that’s known to represent that dummy object.  In actuality, the test wasn’t really meant to be earth shattering.  It was one of the tests that was used to help drive out the design of the serializer’s API and was simply left in as a development artifact.  However, every so often it would break…for good.

Why did it break?

It turns that the test would break when the byte array that the settingsSerializer.Serialize(…) method created no longer matched the static byte array defined in a constant at the top of the file.  Since this test’s assertion is that the produced array must match the known array, the test failed.

Why did it fail?

As I mentioned before the test would work perfectly for days at a time before inexplicably failing one evening about once a week.  The test ran as part of our CI process so it ran dozens of times a day without issue.  It wasn’t until the third time it broke that I actually started to notice a pattern…

  • Test runs great.
  • Test runs great.
  • QA engineer makes a new internal build for testing.
  • Test fails.
  • Test runs great.
  • Test runs great.
  • QA engineer makes  new internal build for testing.
  • Test fails.

Spot the pattern?  If so then congratulations because you just solved in 5 seconds what took me about 3 weeks to pick out: every time a new build was made for internal deployment, the tests started to fail immediately afterwards.

Here’s the explanation

Whenever we make an internal deployment we increment out product’s version number.  We place the Subversion revision number of our last deployment at the end of our version numbers so one of our version numbers may be 1.2.3.15305 where 15305 was the Subversion revision number that build was tagged at. 

The issue arises because the binary serializer serializes every aspect of a class, down to the version number of the assembly that it resides in.  This means that if you serialize an instance of DummySettings at version 1.0 and another instance at version 2.0 then the byte arrays won’t match exactly because of the version number, even if the class hasn’t changed at all.

So what did we learn from this?

We took two important lessons from this.  First, we need to be incredibly careful with our user settings across versions of the product.  We’ve use binary serialization elsewhere in the product for similar purposes for quite time (several versions) and haven’t seen a similar issue, so we’ll need to figure out why it causes an issue here.  Secondly, this was a good reminder not to make our tests dependent on data that’s outside of our control.  Although I thought I was avoiding this by storing the byte array directly in the class as a constant I was obviously wrong.  The issue that we saw today is no different then using DateTime.Now in your unit tests.

Hopefully this will help someone else out there, as well.