Friday, November 21, 2014

Code is like Wet Sand Built on Wet Sand

The softness of software means that everything we build is sitting on a liquefaction zone. Everything works until someone decides to change the underlying structure. A NodeJS package changes and breaks your code. Entity Framework 6 removes a feature that you need and now your have to refactor your data layer. Chrome adopts the latest CSS revision and text now doesn't appear on your page.

We need updates to software to fix bugs and make development tasks easier. If we didn't do that we'd still be developing with assembler and running DOS. We also need to retire old things because the combinations of things to support grow exponentially over time. Like that estimate before the invention of the transistor that we'd one day need every grown woman in America to be a phone operator, we'd need every high school grad to be a software tester to test all the combinations.

The most common approach to keeping software flexible is to keep areas of functionality with an app very specific and to use abstractions so that no one part knows how another part works. In object oriented programming these are known as the SOLID principles.

Now, if you and your team have the time, skill and discipline to obey these principles, your codebase can survive changes for many years without it getting much harder to modify. But companies need to make deadlines to make money, not everyone knows these ideas and sometimes people just want to be done with a task. Damn real world :)

One way companies mitigate the amount of code they have to maintain is to drop support for things in their products. No more Windows XP and Internet Explorer 6 patches. jQuery 2.x and AngularJS 1.3 need IE9+. Otherwise the testing becomes too onerous, and makes paid products too expensive relative to their value. For free products, this is just too much to ask

I think there is another approach taking shape: planned obsolescence at the app level, not just at the feature/platform level.

The SOLID principles help keep it easy to replace tiny units of code within an app. Lately, though, it feels like people want to expand that approach to entire apps. I've heard people on coding podcasts ask JavaScript developers how they plan to keep a web app running for over 5 years when JS libraries change so fast and the answer is that they don't. They expect the app to be obsolete and to be replaced by something else.

Every app that lives in a cloud system like Azure or Amazon Web Services costs someone some money for every moment it's running or every byte it delivers. Once an app's popularity wanes and the revenue stream drops below the cost of keeping it running it will be decommissioned. Online games are already doing this.

You can see this happening with mobile platforms, too. It's easy to do with hardware that can't be upgraded and costs as much to repair as to replace with the latest version. I have a Windows Phone 7 phone and the flow of new apps for it has almost stopped. Your iPhone 4S can run iOS 8, but it probably shouldn't for performance reasons. As apps start requiring iOS 8+ your 4S and down will be left behind.

As someone who works with some 10+ year old code at work, I support the idea of planned obsolescence at the app level. What would that look like for executables on PCs and servers?

  • A set of small apps with very limited responsibilities. No monolithic services with 20 threads doing 20 different things.
  • Lots of executables. Maybe one that launches the rest, but again, no 1 giant process with a ton of threads.
  • Self-updating. Don't rely on users to keep things up to date. Provide control for the risk-averse enterprise, but limit component use to a year or 2.
Shortly after I started this post Martin Fowler's wrote about "sacrificial architecture", which seems to be a way to deal with retiring large scale systems. Great minds think alike? :)

Saturday, October 11, 2014

How to Fund Childcare in Canada

My idea is this: don't limit the childcare deduction to just people's own kids

In Canada, childcare expenses are tax deductible in the same way that retirement fund (RRSP) contributions are. They come off the total of your income, so you get back whatever percentage your highest tax rate is. The more you make the more the deduction is worth. (Whoever has the lower income in a couple has to claim it.)

I understand the reason an RRSP contribution comes off the top of your income. You're loosing access to money now in hopes that you will be in a lower tax bracket later in life. But I don't quite understand why childcare is treated the same way. Tax law history is not easy to find online. It's probably something to do with the idea that you spend $50 a day to go to work and make $150. You don't get to spend the $50 on yourself or on goods or experiences for your kids. (A good daycare can be a good developmental experience, so this reason doesn't make complete sense.)

Whatever the reason I suggest we let people pay to send other people's kids to day care and let them deduct the cost in the same way. It would be a like a charitable contribution, but worth more than 15% to those in higher tax brackets.

There are a couple of different ways you could run this. One would be to have to pay for a particular child. A group of family and friends would all pay a child's parent(s) some amount towards day care. There would have to be receipts from the child's parent.

Another way would be to have non-profit companies to which anyone could contribute and parents would apply for help. You'd loose some of the contributions to the overhead of running the company, but the benefits would be more widespread.

My next step is to write to all of the federal leaders and maybe even the provincial ones. I'm not a fan of the federal Conservatives, but it wouldn't be the first time that they extend a tax deduction. This might be right up their alley.

Monday, May 26, 2014

Don't Be Afraid of SingleOrDefault

The following is based on an issue I've seen many times in a code base at work, and only recently caused the problem described below.

Consider the following code:

Assume that for good reasons we need to find JobSources by their Source and JobId values. The calling code doesn't have the Id. The "database" doesn't enforce uniqueness of these 2 values as a key, we just assume that every other system that feeds up data behaves this way, too. Well, hope is a better word, as we'll see.

The first time UpdateOrAdd is called, it will find the one and only matching JobSource and update it. Then someone adds a second JobSource for job 2. We again try to update the JobSource with JobId 2 and SourceType File. Success! No exceptions.

Except, we're using Any to see if there are 1 or more items and then updating the first one. The code tolerates the condition of there being more than one item that matches our "key". We have potentially updated the wrong data. Corruption!

Now let's change UpdateOrAdd to use SingleOrDefault:

Not only is the expected shape of the data clear, but it's shorter too. SingleOrDefault returns the 1 item that matches or the default value for the type. For any class type, the default is null. If more than 1 item matches, it throws an exception.

Now on the second call to UpdateOrAdd, we get the following exception:

System.InvalidOperationException: Sequence contains more than one element.

Oh no! A noisy exception, instead of silent data corruption!

Why would someone write code the earlier Any/First stuff? Because some coders are scared of triggering exceptions. More scared of that than corrupting data. Any time I see this pattern in code at work I change it to use SingleOrDefault, or just Single if the item is definitely expected to be present. I've had to convince people that it's better to report a problem than update the wrong item.

Yes, there is a chance that the exception won't happen during testing because the data in the lab might be very clean. Perhaps no one has yet created the conditions there that break your assumption about the shape of the data. It just might be found by a real customer. That customer, though, will report the issue and, more importantly, not lose data.

Monday, May 12, 2014

A Very Practical Use of C# Structs

A programming interview question folks will tell you to be prepared for is "when should you use structs" and the general response is "when you want pass by value behaviour". That is, when you want data to be passed as a copy rather than as a reference.

Ok, but when would you ever want that behaviour? An issue at work recently provided an example: when you can't trust that the thing your object was passed won't be changed. Or that the object you passed in turns out to be the same one passed out later. Here's an example:

There is a class, PersonUsingClasses, that takes items from two data sources and holds on to the references, rather than making copies of all of the properties of each. It then uses those references to construct a new property, DisplayName. I've written such code myself, unaware of the dangers. This class also has a way to convert it back to one of the data source types, ToServicePerson.

A couple of things to notice:
  1. The PersonClassFromService reference sent into the constructor is the same one passed out in ToServicePerson
  2. Someone forgot to remove his debugging code in the constructor.
This means that any changes made to the Service person object inside or outside of the PersonUsingClasses object will appear everywhere at once. Frank changed his salutation in Main to Dr. from outside the class, but the class reflected this change. Also, some code in Main tries to detect if the Age property changed by comparing the input and output objects, and what do you know, there was no change.

One option to fix this is to not hold on to the references passed into the constructor and make copies of every property that matters to PersonClassUsingClasses. That might be a good option, but we need to support recreating the PersonClassFromService object, which could have properties that don't matter. Or, there could be dozens and dozens of properties to track. (I worked at a bank - trust me when I say this happens.)

A nearly equivalent approach is to use return structs from the DB and service:

Now the system copies every property in every input parameter for us because they are structs. It copies every property again when we call ToServicePerson. This means that changing the input parameter does not get reflected in PersonUsingStructs and we can detect the accidental change in the constructor. This approach uses more memory because of all of this copying, but it's not much more than if we'd made copies of every property ourselves in PersonUsingClasses. We've protected the system from accidental changes.