Friday, October 14, 2016

Handling User Data Securely - Really, Really Securely

Imagine you're building a web app that requires a password from a user for encryption. This password is not the same as their login one, it's used only for encrypting and decrypting their data in the browser. The user enters the password, the app uses it to generate an encryption key that the browser can use and then encrypts and uploads data. Later, the user types the password in again so that they can work with the encrypted data.

One of the things your app promises is that it never stores the password on the server in any form that another party could intercept or crack. And if someone compromises the user's computer or it gets stolen or seized the app promises that there is no trace of the password left behind.

This means never including the password or a hash of it on any posts to the server, neither in form submissions nor AJAX calls nor in something like ASP.NET Webforms view state. Similarly, the app must not save the password in any form to a persistent store like the browser's local storage or one of the database systems that some browsers support.

What options do you have for building such a system with a typical web system that involves form posts like ASP.NET MVC or WebForms?

There are 3 ways a web app typically persists data that the user enters from one page to another:
  1. cookies written to disk by the browser and sent back to the server with the page request
  2. a view state system that includes bits of data in hidden form fields
  3. session storage in the browser to leave data behind for the resulting page to read
The first 2 obviously send data to the server, so they are not solutions. The third one does't send data to the server, and it might seem as good as being only in memory. However different browsers treat it differently. They don't all clear it when you close the browser, and if the browser dies or the power goes out it may be left on disk.

You might be tempted to encrypt the value before writing it to view state or session storage, but who controls that encryption key? If you do, then you have to manage it and may have to reveal it under court order. If you generate a key in the user's browser, then you have the same problem of storing something between page views.

You conclude that the you can only hold the user's password in memory, meaning a JavaScript variable. The problem is that they disappear every time you visit another page. The easiest solution to program is for the app to ask the user to enter their password on every page that needs it. Not exactly a delightful experience.

Obviously you want to minimize the number of times the user enters their password. One approach would be for the app to have a field that collects the password, perhaps at the top. The rest of the page performs AJAX-y form posts that submit encrypted data, receives HTML from the server and updates the DOM with the response. Something like WebForms' UpdatePanel or Ajax.BeginForm in MVC.

If the user navigates to another part of the app that doesn't need the password, though, they have to reenter it when they return. This might be an advantage because the app only asks for the password in applicable contexts. Users would learn to do everything they need to before navigating, or they'd use 2 browser windows or tabs.

You could get the number of times the user needs to enter the password down to once per use session by using a single page app (SPA). If the app is all JavaScript and AJAX calls for data then it can keep the variable holding the password alive for the entire duration of use. If the user closes the window the password evaporates. (Well, it might still be sitting in RAM or on disk in a virtual memory file, but this seems beyond our control in a browser.)

SPAs have an entirely different development process that you may have to learn, especially if you are used to server side web development (ask me how I know :). Putting your time in to learn will be worth it, though, if you want to give the user the best possible experience of entering a secure value exactly once.

Sunday, July 17, 2016

Code Learnability vs. Feature Addability

I'd like to talk about made up words.

No, really I'd like to talk about the tension between making a code base easy to learn vs. the ease of adding things to it, specifically about web applications.

Imagine you had a slider control for your code that went from "easy to learn" to "easy to maintain".

When you slide the control all the way over to "easy to learn", most of the classes disappear along with all of the interfaces and many if statements appear. Methods balloon in size and contain duplicate logic because there are so few classes to encapsulate it. It's very easy to trace data and logic through calls up and down the stack. Anyone reading the code will come across all of the decisions it makes. The reader won't have a good sense of why the code does what it does, though. The lack of little methods like DetermineRanking or classes like RankingEngine mean that such code lives all over the place.

At "easy to learn", you can give a new developer your codebase and they'll be productive very quickly with little mentoring. Need to add a new data field when adding a customer? Just find the giant AddCustomer method or click button event handler and change line 654. A quick bit of functional testing shows that more related logic lives down on line 1233.

Oops, the same logic appears in SaveCustomer and now you can add a customer with a new field but users can't update it. QA or, even worse, customer support opens a bug, new developer finds duplicate logic, copy, paste, fixed. Again and again.

In some organizations, this is totally acceptable to devs, managers and customers. They can hire less skilled, cheaper developers and undercut the competition. Their customers are probably buying the software for some cost center in their business, so spending as little as possible is the goal. Everyone here operates at the low end of some market, which might make sense at the moment. As the dev shop or the customer grows they'll try to level up the software they make or use.

(The field of Economics contains an idea that ideally every product exists at every quality and price point so that everyone can afford the version of a product that fits precisely with their income. If there were only shacks and mansions to live in you'd have to live in a shack until you can afford a mansion. Better to have a wide range of housing options, especially within a neighbourhood.)

I'll bet the development shop's employee turnover is pretty high, though. As soon as a dev learns a little more about development they look for a more advanced employer. Again, some companies accept this and keep hiring from the ever growing pool of junior developers, which is fine.

I'll also bet that successfully adding features takes weeks, including writing code and back and forth with QA. Such code is not unit testable, so people find all bugs during end to end manual or automated testing.

At the other end of the slider, "easy to maintain", classes and interfaces abound, if statements largely disappear, but the structure obfuscates the code's flow. Frameworks and libraries, like inversion of control (IOC) containers and request pipeline handlers, automatically set up actions and dependencies. This means that for the app to know what to do with a class or method you only have to put a specific interface or attribute on it.

The experienced developer's productivity goes way up and bugs go way down because of unit testability and the inherent design (e.g. code no longer allows the string "0" or "1" for values, it uses booleans). However, the major trade off is the learning curve and cognitive load of the code base. The concept count goes through the roof. With so many classes and seemingly magic behaviour, new developers need a lot of guidance with the design. That could be in person or in a recorded video or design docs.

(I recently experienced this myself looking at code samples that rely exclusively on IOC containers to resolve dependencies. Some containers use an easy to follow "map interface IFoo to class Foo" syntax, while others use "map all of Foo's interfaces to Foo". The latter makes it harder to find the thing that maps IFoo to Foo with Visual Studio's Find All References because IFoo doesn't appear in the mapping. I even found one IOC container with a convention-based mapping method like "map all classes in assembly X to the interfaces matching their names". This meant that neither the classes nor the interfaces appear in the container setup code. Unless you find the conference video or series of blog posts where the author goes from original code to the heavily refactored version, you can end up puzzling over the approaches you see.)

Adding features now takes days and involves mostly one way trips through QA.Production bug counts due to actual code problems go down.

The code now requires more experienced developers who demand higher pay. This causes the software to cost more. Customers are happy to pay, though, because the software "just works", which they need to keep their profit centers working. Turnover drops.

There is a joke (belief?) in programming that the more complicated and obscure the code the more job security you have because only you know how to update it. This depends on what makes the code complicated, though, and what the benefit is to the company. Are you using well documented but advanced libraries that do a lot of heavy lifting, or are you writing 1000 line methods of bit shifting code with single letter variables?

Friday, April 1, 2016

It Doesn't Matter How They Get The Data

I was reading about using the SecureString class. This is a class that encrypts a string so that it is readable only on the current machine so that it does not hang around in plain text. Strings in C# are immutable, so they stick around until they are garbage collected, even if you set your reference to a string to String.Blank (""). The typical use is to collect the value from the user directly into a SecureString and shuttle it around on the current machine. As soon as it leaves the machine it must be turned back into a plain string, which is not a best practice.

I was looking into using SecureString in ASP.NET to handle a password. That password is passed in in plain text, and probably again when you actually use it, so there would be more than 0 instances in clear text in memory. Most StackOverflow answers point this out, but it would at least cut down on the number of instances as it is passed from method to method. Strings are a value type, meaning that every time you call another method with one as an argument .NET creates another copy.

In addition, I kept coming across the same kind of comment:

Yeah, no one has ever been able to read a remote, web-accessible machine's memory. Until they could.

This reminded me of a comment a co-worker made about something you could do with a value from one of our databases: "How could anyone get it?"

It doesn't matter.

How did they get the Ashley Madison data? How did they get the Sony data? How did they get the U.S. Office of Personnel Management data?

It doesn't matter.

What matters is what more they can do with it. This is called "pivoting", or using one breach to hop a level deeper. Security through obscurity works until your whole database appears on the web. Any SQL system is one SQL injection vulnerability away from giving up everything. Any software involved in serving web requests is a buffer-overflow bug away from barfing memory.

Practice defense in depth to limit a small compromise from becoming much bigger.



Friday, March 13, 2015

Assert.DoesNotThrow Does not Preserve Stack Traces

Just a short post about an issue with an NUnit feature.

It has an assertion called DoesNotThrow that takes a delegate function as an argument. If the delegate throws an exception then NUnit will throw its own exception. The method is great at pointing out exactly where the code under test is. However, if an exception does occur, NUnit reports the exception type, but looses the original stack trace. There have been enough occurrences of lost stack traces that I've stopped using it. Now I just comment the actual test line and let the exception bubble up to the test runner.

Wednesday, March 4, 2015

Make Classes not Enums

The main C# code base I work with at work is full of generic objects and methods written to use enums to drive behaviour. I'm not sure of the reason. The people who created it have all since moved on, so I don't know who to ask. All I can do is live with the giant switch statements and undo them into classes when I can. Why classes? Let's take a look.

The full example code base on which the gists are taken is available in https://github.com/claq2/MakeClassesNotEnums.

The (Evil) Enums Way


Say you have a service that creates different kinds of backup jobs. One of its arguments is an enum that indicates what kind of job to create. It returns only 1 kind of object, Job, that is not abstract. This object represents all the different possible kinds of jobs. A property, JobType, indicates whether it's for backing up files or a SQL database.

In this example, creating a job means calling a single CreateJob method that takes an enum argument that indicates the type. This might seem contrived, as in "who would build this", but it's easy for a UI to consume. Show the user a drop down with the job types and call the one method with the user's choice in the enum.

In object oriented programming there is something called the Single Responsibility Principle. It states that a class should have only 1 reason to change. Another way to put it is that a class should have exactly 1 concern. The enum approach violates this in at least 2 ways.

First, the Job class represents all possible job types. It needs properties for every job type. A change to any job type or the addition of a new one means changes to this class. Some properties apply to all types and some apply to only some types. How do upstream developers of the Job class know which properties to fill in for each type? They have to look at the documentation. I hope they don't miss one of the comments.

Second, the JobService has 3 concerns - determining which type of job to build, verifying the values and mapping input values to properties. If any of these aspects change this class must be updated. The more you need to change it, the more risk there is that you will introduce a bug. Especially if the switch has many clauses with pages of complex logic.

The cyclomatic complexity of this method is already 7, meaning you need at least 7 unit tests to completely cover it. This approach will only get harder to test fully and understand. There's already a little extra logic for Sql2014Jobs. How long before the logic becomes so tied together that you have to write tortured logic to get exactly what you want?

Think about what load and save methods in the JobService class will look like. Nearly the same - more switches with extra if statements for the special cases.

The (Righteous) Classes Way


There are 2 sources of cyclometric complexity in a system - the conditions that the business defines and those created by developers. You usually can't reduce the business's conditions, but you should be able to control the developer-created ones. The way you do this in an object oriented system is usually with classes and inheritance.

In this example one might wonder why the interface doesn't already know what kind of job it need to create in response to the user's actions. Well, it does. Outside of a text-menu driven console app, there shouldn't be any logic needed to decide what to create. The user chose to click on a button or use a drop down to pick the job type. The UI now has enough information to call a job-specific method and expect a job-specific result. Hence, separate job service classes.



No conditional logic. The logic for SQL 2014 jobs is contained in a class that only has to do with SQL 2014 jobs. Any change to File jobs does not involve anything related to any other job or the services. As written, the services don't really add any value to consumers. They could just use the job constructors themselves. Imagine they had load and save methods, though. Those methods will be specific to the job types.

The logic for constructing the SQL 2014 job's instance name and for rejecting non-root path file job is now in those classes. There is no chance that a change to file job logic could impact other job types.

A Hybrid Approach


Let's say you have a system that looks like the first example that has a single method and for non-technical reasons you cannot easily change the interface. Are you stuck? No.

Change the service to be or use a factory, as in the factory pattern. Job-specific logic is still in separate classes and the service now has just 1 responsibility - to invoke the right service and return the result.

It is a lot more code than the original enum-only version, but it more closely follows the SOLID principles that make software more maintainable. The other classes are the same as in the class version, except the AbstractJob class. It now has an abstract ToJob method that each specific job class must implement to convert itself into a generic Job object. Again, this logic is encapsulated inside each specific class.

Summary


Enums and switches make for less code, but over time it becomes harder to understand and more easily broken. In an object-oriented language classes are there to segregate logic and responsibility for better maintenance. It's a little more code, but you will introduce less bugs.

Wednesday, January 21, 2015

Handling Exceptions: Everything You Ever Wanted To Know

Exceptions have been around for a long time, but some seemingly experienced people still struggle with them. I will explain how to handle and communicate them in various .NET applications.

All exceptions in .NET inherit from System.Exception. You can't throw an instance of just any class; it must inherit from Exception. So, catching Exception means that nothing will get past your catch clause.

If there is a specific type of exception that you know you can handle, you must catch it before more general exception types. The class inheritance structure indicates which exceptions are more specific. ArgumentNullException inherits from ArgumentException, which inherits from Exception. So, if you want to handle the null exception differently from the argument exception, you must catch the null exception first. Each exception will be caught only once and by the first catch block that matches.

You can also add a "finally" clause after your catch clauses, in which you run code that must be run whether there was an error or not.

In the above examples and the following ones you'll see a variable called ex that holds the Exception object. You don't have to declare such a variable if you don't need a reference to it. Also, omitting the exception is the same as catch (Exception).


Default Exception Handling


Before we discuss how and when to handle exceptions, let's first look at how .NET handles them if our code doesn't.

Here is the code for a set of apps that throw exceptions in different ways: https://github.com/claq2/Exceptions

Console


Any exception in a console app, whether on the main thread, a new Thread/ThreadPool thread or started with the await keyword produces this:

Very straightforward, no ambiguous choices for the end user.

WinForms


When a WinForm application generates an exception on the UI thread that the code doesn't handle (e.g. in a button click event handler), .NET shows the user this:

What's a user to do? In my opinion, this is too much information for a non-developer to deal with, and the user has no idea what each choice's implications are. Do not rely on this dialog for end users. We'll see how to avoid this later.

If you start a thread, either using new Thread or ThreadPool.QueueUserWorkItem, and it generates an uncaught exception, .NET will terminate the application:

I have a Debug option here because Windows knows I have a debugger installed (Visual Studio). Again, we'll see how to prevent this later. The runtime will log this in the Application Event log along with the stack trace.

An exception thrown on a thread started with await results in the same prompt as the exception on the UI thread.

When you let .NET's manage your threads one thing it gives you is much better exception handling. Though again, the user must make an uninformed choice. The runtime doesn't add anything to the event logs because it handled the exception.

WebForms


An exception on the thread that is executing a web page request (e.g. in Page_Load or a button click event) shows:
Also known as "the yellow page of death". Only this request has come to an end. The system is still serving other requests. By default, when the request originates outside of the web server there is no stack trace giving away potentially sensitive information about the app. When viewed on the web server it will show more information. There is no event log entry because the runtime handled the exception.

The same thing happens when an uncaught exception is thrown on a thread started with await. Again, .NET handles it gracefully.

A truly insidious thing happens when a ThreadPool thread or one started with new Thread throws an unhandled exception: the .NET worker process dies. The symptom might be invisible to the user that caused it, but every request that w3wp.exe process was serving will come to an end. If the app uses in-process session state, those sessions will be lost. If the app uses Windows authentication, all of the auth sessions are gone and users will need to re-authenticate. (Ask me how I know! :) We'll see how to guard against this later. The runtime will record the exception along with the stack trace in the Application event log.

By default, the settings for an Application Pool (the thing the runs your ASP.NET website AKA the worker process w3wp.exe) will disable the pool if something kills the pool 5 times in 5 minutes. This is called Rapid-Fail Protection. When this kicks in, IIS returns HTTP 503, Service Unavailable for subsequent requests. If you find yourself having to disable this feature then I hope it's a short term mitigation while you hunt for the thing that's throwing exceptions on background threads.

WCF


An exception thrown on the main thread or an async thread sends an HTTP 500 error with this XML:


<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</faultcode>
<faultstring xml:lang="en-US">The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the &lt;serviceDebug&gt; configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.</faultstring>
</s:Fault>
</s:Body>

</s:Envelope>


The WCF proxy that Visual Studio/wsdl.exe generates throws a System.ServiceModel.FaultException. As the text above indicates, you can have the server send the server code's stack trace by changing a web.config setting. This might be acceptable in a development environment, but you don't want your service leaking implementation details in production.

Exceptions on background threads kill your ASP.NET worker process, w3wp.exe, just like WebForms. It's the same engine and threading mechanism. Again, the runtime records it in the Application event log.

MVC


Like WebForms, both exceptions on the thread processing a request and on a thread started with await result in an error page:
And like WebForms, an exception on a background thread (new Thread, ThreadPool) kills the w3wp.exe process serving the request, with all the same effects. This includes an Application event log.

WebAPI and HttpClient


WebAPI is very webby. Exceptions on the main thread and async threads that are not wrapped up into an HttpError and HttpResponseException result in an HTTP 500 Internal Server error and the following JSON:

{"Message":"An error has occurred."}

You can have WebAPI send more information by setting config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always in WebApiConfig.cs's Register method. With this enabled, an exception not thrown as an HttpResponseException will send:

{"Message":"An error has occurred.","ExceptionMessage":"Oh noooo!","ExceptionType":"System.Exception","StackTrace":"   at MVC.Controllers.ExceptionController.Get() in c:\\Users\\xyz\\Documents\\GitHub\\Exceptions\\MVC\\Controllers\\ExceptionController.cs:line 19\r\n   at ..."}

Oddly enough, wrapping up a caught exception in an HttpError and throwing HttpResponseException will cause the stack trace to be null.

There are 2 ways to detect an error with HttpClient: examine HttpResponseMessage.IsSuccessMessage or call HttpResponseMessage.EnsureSuccessStatusCode to get an HttpRequestException. EnsureSuccessStatusCode will not deserialize the above message. It's up to you to turn it into an object after determining that IsSuccessMessage is false. Here I've built my own class in a console application that has most of the same properties as HttpError, because HttpError lives in System.Web.Http.dll, which is part of the WebApi.Core package. I also needed a custom exception type so that I could specify the stack trace:

I understand that HttpClient is not specifically for interacting with WebAPI, but I am a little surprised that nothing natively converts WebAPI error responses into exceptions on the client side. ServiceStack built handy client and service components that share an error message format. This allows the client to reconstruct exceptions for you.

WPF


WPF applications have a consistent approach that I like. In all instances the application dies with this message:

Like a console application, there is no choice for the user. I like this because the state of the application is unambiguous.

Handling Exceptions


The general rule to catching exceptions is to catch only ones about which you can do something. For example, catch a timeout exception so that you can retry on behalf of the user. Or ignore an exception when deleting something that isn't there.

There are a few situations where you want to catch all exceptions:

  1. In background threads. As mentioned above, any unhandled exception in a background thread will kill your process, including your ASP.NET worker process.
  2. When you want to translate one application layer's exceptions or .NET exceptions into another layer's exception type.
  3. You want to throw a different exception in order to remove the stack trace.
  4. It's the last stop in your application's stack and you want to log the exception before letting it propagate up or out. For example Application_Error in Global.asax.cs.
  5. You want to handle all exceptions in a generic way instead of letting them reach the runtime engine.

"Safety Net" Pattern for Background Threads



I once saw this described as the safety net pattern, but I can't find the term in general use. You can see where it gets its name, though. Another name might be the Pokeman pattern, as in, you gotta catch 'em all.

Translating Exceptions



There are times you want to put some context around an exception for the next layer up so that they know which operation failed and whether there's something to be done about it. Include the current exception in the new one so that it gets put into the new exception's InnerException property. That way when it finally gets logged by something near the top of the call stack all of the error information will be present.

A similar approach is to purposely not include the current exception in the new exception. You want to do this when you want to be sure that potentially sensitive details don't escape a layer. In this case, you want to consider logging the inner exception before it is lost to upper layer logging.

Centralized Logging and Handling




Some systems, like ASP.NET WebForms/MVC and WebAPI provide a way to catch all unhanded errors, at which point you can log and transform the output. You can also perform extra steps like emailing support. This can remove an awful lot of try/catch and error logging code from individual methods.

Custom Exceptions


Before creating a custom exception or a set of them you need to think about what you want to get out of them. Generally, a custom exception communicates that you've reached a very particular condition that you want to identify from other conditions. That way you can log it and trace it back to a single line of code and potentially let users know what they need to do.

For example, business logic can be complex. It's usually a good idea to have a custom exception that represents a business layer failure, like not providing a needed bit of data. It's not enough, though, to throw this single exception type for every rule failure. You could hardcode the message to show e.g. "No IP address specified", "Invalid IP address specified", but then your app is limited to one language of user. (If you've ever used FxCop or Visual Studio's Code Analysis then you are probably familiar with the "move string to resource file" warning :)

What's needed is one of the following:

  1. A collection of specific custom exceptions all inheriting from a layer-specific parent exception class. The parent class is for the convenience of the next layer up so that it can catch all layer-specific exceptions and handle them differently from other libraries' errors or .NET's.
  2. A single layer-specific parent exception and a collection of error codes/enum values, each representing a particular condition.
An app can then map the collection of exceptions or the error codes/enum values to matching culture-specific strings. .NET provides Resource classes for this scenario.

If you use the error code/enum approach, put the value in the Data dictionary property that is part of the .NET Exception class. This is effectively a dictionary of <Object, Object> into which you can stuff whatever you like in order to send values up the call stack. Don't add properties to your custom exception. You may find yourself having to hand your custom exception to some generic handler that won't know about your properties. It will also save having to perform a slightly expensive cast to your custom type to get the property. Generic handlers will only need to query the Data property for the error code. Keep the key in a public static property.


The alternative is an exception for each error instead of an enum value. Each exception should look up its own error message from a culture-specific Resource class. This approach is more in line with how .NET does things. Some drawbacks are the extra code and that the exceptions will only be understood by other .NET or SOAP-based systems. There is no standard way to send exceptions over, say, JSON.

This way you can send a language-specific message to the user and log in another language.

Anti-patterns and Common Mistakes


Catch-Log-Throw


Doing this all the way up the call stack will fill your logs with the same error again and again, each time adding another call to the stack. This makes logs much harder to read. Did the same error really happen just once? How do you accurately count the number of errors?

Do centralize your logging and stick to the strategy. In the above case you would remove the try and the catch block. Just let the exceptions propagate up the stack.

Throw ex


To propagate a caught exception up the stack as-is, just "throw". When you "throw ex", you create a new exception with the same type as the caught one, but the call stack in the exception starts from where you threw it. The stack trace from the one that you caught is no longer available to upper layers. I don't know of a good reason to "throw ex". I've only ever seen it lead to poor debugging sessions and confusing logs.

Complex Exception Families


Don't group your custom exceptions under other custom exceptions. For instance, if you have a SaveCustomerException and a LoadCustomerException, don't make them inherit from CustomerOperationException that inherits from a base CustomException class. It's needlessly complicated. No code needs to catch this vs. the specific exception or the base custom one.

The worst approach I've seen is a combination of custom exceptions that each have their own embedded enum of reasons. Translating these into a single custom exception and single enum value ends up looking like this:

Now every time there is a new exception reason in one of those enums this method needs another case statement. If there is a new class of exception to catch then we need a  A total waste of time.

Not Using Exception.Data


I've never seen .NET use the Data property, but it is the best place to put custom information, rather than adding properties to your custom exceptions. If you feel you must use custom properties, use Data as a backing store so that it is available without casting to your custom type.

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? :)