When software is new, it is very malleable; it can be formed to be whatever is wanted by the implementers. But as the software in a given project grows larger and larger, and develops a larger base of users with long experience with the software, it becomes less and less malleable. Like a metal that has been work-hardened, the software becomes a legacy system, brittle and unable to be easily maintained without fracturing the entire system. Brittleness in software can be caused by algorithms that do not work well for the full range of input data. A good example is an algorithm that allows a divide by zero to occur, or a curve-fittingequation that is used to extrapolate beyond the data that it was fitted to. Another cause of brittleness is the use of data structures that restrict values. This was commonly seen in the late 1990s as people realized that their software only had room for a 2 digit year entry; this led to the sudden updating of tremendous quantities of brittle software before the year 2000. Another more commonly encountered form of brittleness is in graphical user interfaces that make invalid assumptions. For example, a user may be running on a low resolutiondisplay, and the software will open a window too large to fit the display. Another common problem is expressed when a user uses a color scheme other than the default, causing text to be rendered in the same color as the background, or a user uses a font other than the default, which won't fit in the allowed space and cuts off instructions and labels. Very often, an old code base is simply abandoned and a brand-new system created from scratch, but this can be an expensive and time-consuming process. Some examples and reasons behind software brittleness:
Users expect a relatively constant user interface; once a feature has been implemented and exposed to the users, it is very difficult to convince them to accept major changes to that feature, even if the feature was not well designed or the existence of the feature blocks further progress.
A great deal of documentation may describe the current behavior and would be expensive to change. In addition, it is essentially impossible to recall all copies of the existing documentation, so users are likely to continue to refer to obsolete manuals.
The original implementers have moved on and left insufficient documentation of the internal workings of the software. Many small implementation details were only understood through the oral traditions of the design team, and many of these details eventually are irretrievably lost, although some can be rediscovered through the diligent application of software archaeology.
Patches have probably been issued throughout the years, subtly changing the behavior of the software. In many cases, these patches, while correcting the overt failure for which they were issued, introduce other, more subtle, failures into the system. If not detected by regression testing, these subtle failures make subsequent changes to the system more difficult.
More subtle forms of brittleness commonly occur in artificial intelligence systems. These systems often rely on significant assumptions about the input data. When these assumptions aren't met – and, because they may not be stated, this may easily be the case – then the system will respond in completely unpredictable ways.
Systems can also be brittle if the component dependencies are too rigid. One example of this is seen in the difficulties transitioning to new versions of dependencies. When one component expects another to output only a given range of values, and that range changes, then it can cause errors to ripple through the system, either during building or at runtime.
Fewer technical resources are available to support changes when a system is in a maintenance phase than there are for a system that is in a development or implementation phase of the SDLC.