High-level goals for interactive software
1. Typical usage should be easy and efficient.
2. All expected usage should work correctly.
3. Unexpected usage should result in safe behaviour.
Clearly it isn't just unexpected usage that should result in safe behaviour and we would certainly expect that typical usage should be correct as well. But that hierarchy makes it easy to see the cascading importance of software properties in relation to the degree to which user behaviour is expected to happen. If we plot expected human interaction on a distribution curve then we can overlay the probability axis with one that indicates what level of behaviour the software should respond with. That probably made sense to very few so here's a clearer explanation.
Under no circumstances should software ever do something unsafe. Losing data or allowing it to be accessed by unauthorized parties are typical examples of failure at this level. Although I posit this as a minimum requirement for software, in practise both of these things occasionally happen because it is generally intractable to enumerate all possible things a user might do for any piece of software sufficiently powerful to be worth discussing. But there are tools like fuzzers that can help automate the task of searching for such problems.
For every action that a user might reasonably be expected to perform, software should respond in a manner that the user could reasonably expect. Put like that, it seems only fair! That level of behaviour is usually verified by manual feature and regression testing based on feature specifications. Because this level of usage is not typical, it is important to provide contextual user-assistance for it. Of course, users tend to assume that performance will scale linearly with the amount of data they provide. It is therefore important to keep these expectations realistic by detecting input data beyond the range of typically expected workloads and warn the user that they will produce uncharacteristically low performance.
Typical usage is what software is designed for and therefore using it in these ways should be discoverable (so that documentation is unnecessary), simple (so frequent usage does not frustrate) and efficient (even at the cost of code complexity, so that users do not waste their time).
It is illuminating to think about software evolution in terms of these three levels. Initial releases of software tend to have tiny sets of behaviour considered typical and large set of behaviour considered unexpected but as software matures, more behaviour moves away from being considered unexpected and toward being considered typical. This tends to increase the complexity of code unless it is refactored to account for the changing levels of expectation assigned to different user behaviour.
Anybody care to disagree?


