What Makes Software Flexible

Truth, Needs and Purposes

I just moved this chunk out of ExtremeProgramming, because I think the question is interesting enough to be considered separately.

"Young Obi-wan, do not delude yourself into thinking that features are stable. By the time you finish that first release of three months, the features that the customer did not select for that release may not be needed anymore; or may have changed form dramatically. Indeed, it is likely that even the features within the release will change significantly. You don't want to base your architecture on things that are likely to change do you? Wouldn't you rather base your architecture on the features that the customer thought most important?" --RobertCecilMartin (reposted w/o permission)

"But, master, since the universe is illusion, to base a system on a feature is surely a mistake! The features the customer thought most important, by your own admission, are what thecustomerthought , not the Truth itself. Is it not better to base my architecture on the thing that the application is about? Observe the joy of those programs that fullfill their OneTruePurpose!" --

"Ah, but is it Truth who must be satisfied, or those who pay you? Do not lose sight of what is being attempted. We are merely trying to make something that will work, not creating art."
Safety, Dangers, Additions and Modifications

For a big chunk of my professional life, I've thought flexibility in software was available from various OO ideas, like AbstractClasses, DesignByContract, and so on. These assume that the safest system change you can make is to add code rather than modify existing code. If I add a new class that conforms to an existing interface, or just uses existing interfaces, then nothing that exists is threatened.

If you believe this is important, then it seems that you'd be tempted to think ahead when designing, rather than follow YouArentGonnaNeedIt. The XP community challenges this orthodoxy, and (it seems to me) says that actually modifications need not be much more dangerous than additions. --DaveCleal

Also, if XP says that traditional OO ideas about flexibility aren't so important, then IsXpIndependentOfObjects or the traditional OO ideas about flexibility are simply wrong.

You're right that one's theory of 'safest change' is absolutely crucial here. Add or modify, the safest change is always to a system, in any language, where DoTheSimplestThingThatCouldPossiblyWork and RefactorMercilessly have been consistently previously applied. --RichardDrake

I remain unsure. The most critical piece of XP for making modifications safe is the comprehensive unit tests. For some kinds of changes that's fine, but I worry about reversing more abstract design decisions. I don't have a good example to hand, but I will think about it... -- DaveCleal
I think of flexibility as the quality which minimizes the amount of work you have to do to get from point A to an arbitrary point B; you need get rid of or avoid everything that you don't need, and then add what you do need. When you keep your system in a state where you only have to add things, it is very flexible. There is a cost to keeping around things that might, kind of, maybe will be needed someday; it is harder to see where you can put new things. The area around the code has more potential than any code you can put in its place. -- MichaelFeathers

Re: "When you keep your system in a state where you only have to add things, it is very flexible."

I'd be hesitant to make that a main principle just yet. What if we are making 20 additions to avoid changing 2 things? And accepting duplication of concept facilitates adding, but with the risk it will cause more points-of-change in the future (copy-and-paste is the ultimate "adding"). Or what if it takes 3 days to figure out where to add while only 10 minutes to figure out where to change? ItDepends. -t

Some colleagues and I were discussing topics like this the other day, and we came up with the following list of software characteristics that we think are typical of highly flexible systems. This is just brainstorming. But it feels at least partially right to me. The characteristics are:
  1. Simple objects
  2. Simple boundaries between objects
  3. As few of each as possible without compromising qualities 1 and 2
These are arguably so vague as to be useless, but there you go. Do these feel like the goals you're aiming toward as you build systems? --GlennVanderburg

I would add ... WhatMakesSoftwareFlexible? Whitespace.

There are two ways to define flexible. One definition would be a measure of how easy it would be to reuse that class in a new or similar context without touching a single line of code. Another definition would be a measure of how easy it would be to increase that classes functionality so that it can be used in a new or simular context without redesign. In the former one has intentionally attempted to anticipate all possible uses, in the latter one has only addressed current requirements, but has done so in a simple and straight forward way. --DonWells

Expanding on the previous comment:

runtime flexibility (or configurability) The ability to change the functionality of the software without making code changes. Achieved through configuration data, plug-in architectures and embedded languages. No code changes need be made to the core system.

internal flexibility

The code is easily adapted and extended to supply new functionality without major redesign. For instance, a flexible system would be able to have a security model added without major redesign. Is XP able to help us accomplish this?

external flexibility

The software be used as a library or framework and reused (without source code changes).


We should create flexible software through extensible architectures rather than implementing many possible solutions (of imagined requirements). I guess this is just another way of saying: YouArentGonnaNeedIt.

However, isn't extensible architecture in opposition to XP until a need for a particular extensibility is required. For example, using XP, would you create a level of abstraction to your persistence layer (for extensibility - in case you need to support multiple database vendors or both RDMBS and ODBMS), or would you leave this until there is a requirement to use more than one database vendor, and then refactor like mad?

My apologies for my abuse of the English language --StevenShaw.
I'm defining flexibility as follows (is this XP'ish ?):

A system is flexible, if modifications that are known to be necessary can be locally confined.

I distinguish three cases:

1. an aspect changes for the first time: Add the change and ReFactor the system as to eliminate any code duplication the change might have caused (OnceAndOnlyOnce). This will likely create a new VariationPoint?.

2. an aspect changes for the second (third ...) time: If an appropriate VariationPoint? does already exist, just add the new variant. Otherwise, ReFactor to create one (similar to 1.)

3. an aspect might change: Then you YouArentGonnaNeedIt right now.

There are lots of different possibilities for defining a VariationPoint?, from case-statements to abstract base classes to reflective systems. The most appropriate solution depends on the particular change and context. Thus, flexibility is in no way specific to OO nor is OO required.

Can flexibility be considered independent of the flexor? Perhaps one programmer's flexibility is another programmer's straight jacket. Can you think of an example?

Sure. What about the frameworks in this book [1]. The authors claimed a good deal of flexibility for their various results. But I imagine there are those who would, from personal experience, claim the opposite.

I always find it's best to CodeDefensively? and CodeForTheMaintainer. This can add some cruft like the VirtualStaticIdiom, but it makes extending the system very fast, easy and less errorprone.

YouArentGonnaNeedIt suggests otherwise. I don't know. A little bit now can go a long way later. -- SunirShah

By the way, I've realized that the code first then refactor method isn't for me. It's far too bottom up, which means I have to throw out all my other problem solving heuristics. It seems like I'm jumping into a box instead of excaping from one. Bend like a willow.. keep flexible.

I am now experimenting with solving software systems one problem at a time, however. I believe deeply in microiterations. --ss
Tools and language make a difference. If our language or the way our files interdepend are deeply resistant to refactoring, then more investment up front is perhaps more valuable. In general, money spent on tomorrow instead of on building what we need today is inherently wasted. It's putting money in the savings account instead of buying food. There is a chance of earning it back tomorrow, if the product survives, and if we need what we foresaw we might, and if it really costs less, and other ifs. If there were no other way, we'd have to make investments in the future. But there is another way: clean code, refactored as needed. --RonJeffries

Being back into the theoretical stream of things, I've reconsidered slightly. My new answer is indirection. We know that from programming (PolymorphismVsSelectionIdiom, for instance), so let's apply that lesson to a metalevel. The system and the definition of the system are disjoint, giving us another level of indirection. So software systems are flexible to change because we can get at it at a higher layer. And naturally indirection makes for flexiblity because it allows you to defer decisions to much later, or even change decisions. Conversely, if we put all systems onto IC chips, then the system and logic are identical and inflexible. It's that Turing guy again. -- SunirShah
I think one has to first become a student of change. One has to learn what changes, why it changed, and practice testing their predictions against reality. I don't think there is any magic bullet. LifeIsaBigMessyGraph. I would, however, suggest not hard-wiring taxonomies/classifications into code and make them meta-data of some kind. I also find SetTheory a better fit for how I perceive change than type theory or polymorphism. Both the latter tend to assume hierarchies or mutually-exclusive lists of options (sub-types) which are a poor model of reality as I observe it. Mutual exclusion is unnecessary coupling (or anti-coupling). Related: PerceptionOfChange --top
"You don't want to base your architecture on things that are likely to change, do you?"

No, of course not. You want to base your architecture on the needs of the underlying system. Features are built on top of baseline functionality. Software is flexible when it can provide new or altered features based on functionality provided by the underlying substrate in the first place. Without this foundational support you have no means of providing features of any kind, so there can be no discussion of flexibility without first defining the limits of the baseline architecture.
Rules and Implementations

TwentyFiveOrSoRulesToBuildSoftwareThatWorksAndWhichIsEasyToMaintain offers some suggestions in the domain of custom business software. Of note is: The above appears to apply to at best a very, very narrow definition of software.

Narrow by quantity of domain categories, perhaps, but not quantity of implementations.

If we use the sheer volume of implementations to determine what application genre you're talking about, we'd have to assume your suggestions apply to embedded systems. In other words, please don't assume everything is a custom-written, database-driven, CRUD-screened business record-keeping application.

I don't want to get into a domain fight here. The title doesn't limit the domains considered. This does bring up an interesting question though: Does what makes one domain more flexible not work for another; and if so, why? For example, are the choices made different if the hardware or resources are comparatively limited?

If you're going to make recommendations particular to a given domain, please make the domain explicit.

Okay, but note that the rest of the material on this page doesn't do so either. Be careful what you wish for.

The rest of the material on this page isn't specific to any domain. Your suggestions are.

I'm not convinced of that so far. And why should any reader take that claim at face value? It's a premature assumption. For example, being in a database can potentially make something more flexible than polymorphic "lists" so much so that a power-user can make most of the changes without renting a coder. The coder has to do zero, zilch, nada. That's a strong metric of "flexible". But that may not be an option for embedded systems because of space or processing constraints.

If you're going to make recommendations particular to a given domain, please make the domain explicit.

I don't know which domains it covers and which it doesn't; I can't possible test them all in one lifetime; and most likely neither can the other contributors to this page. Why did you ONLY start policing scope when I came along? It appears I'm being singled out because I make controversial and unpopular statements on other topics and this is your way of getting even. [EditHint reminder: move these rants to a rant-related topic with a link when activity calms.]

You're reading too much into this. I singled out your post because it was recent.

Temporal discrimination! :-)
CategoryFeature? CategoryExtremeProgramming

View edit of June 19, 2012 or FindPage with title or text search