Affordance Open-Space at XP Day
Giovanni Asproni and I facilitated an open-space session at XP Day on the topic of affordance in software design.
Affordance is "a quality of an object, or an environment, which allows an individual to perform an action". Don Norman distinguishes between actual afforance and perceived affordance, the latter being "those action possibilities that are readily perceivable by an actor". I think this distinction applies as well to software programming interfaces. Unless running in a sandboxed execution environments, software has great actual affordance, as long as we're willing to do the wrong thing when necessary: break encapsulation or rely on implementation-dependent data structures. What makes programming difficult is determining how and why to work with the intentions of those who designed the software that we are building upon: the perceived affordance of those lower software layers.
Here are the notes I took during the session, cleaned up a little and categorised into things that provide help affordance, hinder affordance or can both help and hinder.
Helping
Repeated exposure to language you understand results in fluency.
Short functions
Common, consistent language.
Domain types.
Good error messages
Things that behave differently should look different.
- e.g. convention for ! suffix in Scheme and Ruby for functions that mutate data.
Able to explore software:
- able to put "probes" into/around the software to experiment with its behaviour
- know where to put those probes
TDD, done properly, is likely to make most important affordances visible
- simpler APIs
- ability to experiment and probe software running in isolation.
Hindering
Two ways software has bad affordance:
- can't work out what it does (poor perceived affordance)
- it behaves unexpectedly (poor actual affordance) (are these two viewpoints on the same thing?)
Null pointer exceptions detected far from origin.
Classes named after design patterns incorrectly.
- e.g. programmer did not understand the pattern.
- Factories that do not create objects
- Visitors that are really internal iterators
Inconsistencies
- can be caused by unfinished refactoring
- which code style to use?
- agree in the team
- spread agreement by frequent pair rotation
Names that have subtly different meanings in natural language and in the code.
- E.g. OO design patterns.
- Compare with FP design patterns that have strict definitions and meaningless names (in natural language). You have to learn what the names really mean instead of rely on (wrong) intuition.
Both Helping and Hindering
Conventions
- e.g. Ruby on Rails
- alternative to metaphor? but:
- don't be magical!
- hard to test code in isolation
If you break convention, draw attention to where it has been broken.
Naming types after patterns
- better to use domain terms than pattern names?
- e.g. CustomerService mostly does stuff with addresses. Better named AddressBook, can see it also has unrelated behaviour that belongs elsewhere.
- but now need to communicate the system metaphors and domain terminology (is that ever a bad thing?)
Bad code style you are familiar with does offer perceived affordance.
Bad design might provide good actual affordance.
- e.g. lots of global variables makes it easy to access data. but provides poor perceived affordance
- e.g. cannot understand how state is being mutated by other parts of the system
Method aliasing:
- makes code expressive
- common in Ruby
- but Python takes the opposite stance - only one way to do anything
Frameworks:
- new jargon to learn
- new conventions
- provide specific affordances
- if your context changes, you need different affordances and the framework may get in the way.
Documentation vs Tests
- actual affordance of physical components is described in a spec documents and not obvious from appearance. E.g. different grade of building brick. Is this possible for software?
- docs are more readable
- tests are more trustworthy
- best of both worlds - doctests? Used in Go and Python
How do we know what has changed between versions of a software component?
- open source libraries usually have very good release notes
- why is it so hard in enterprise development?