As a developer it can be very useful to use principles such as SOLID and the Four Rules of Simple
Design to help me write better code. But it struck me that it might be helpful to apply the SOLID
principles to writing effective user stories.
SOLID Principles
So a quick recap of what the SOLID Principles are firstly. They are a list of principles to help
create easily maintainable object-orientated code introduced by Robert Martin. Thanks Uncle Bob!
- Single responsibilty principle
- Open/closed principle
- Liskov substitution princple
- Interface segregation principle
- Dependency inversion principle
Single Responsibilty Principle
A class should only have one responsibility.
It struck me that user stories can become overly complicated and try to cover too many requirements.
If a user story is broken down to its smallest possible size I think it helps the story to move
across a kanban board more easily.
The developer working on it will have a clearer idea of what is expected of them. Testing time should
shorter as it will be clearer if it has succeeded or not. Risk of deployment should also be reduced
smaller changes will be going to production.
Just as a single class can have many tests, a single responsibilty user story can have many
acceptance criteria.
If a user story adds value once complete, then I can’t really see how a user story could ever be too
small. For example if a form is required, I would be tempted to identify which fields are absolutely
required then they would be one user story. Each added value such as email validation or user name
checking should be a user story in their own right. This is because value can be gained without them
and more value will be gained with them.
Open Close Principle
A software entity should be open to extension but closed to modification.
So new features in software should be able to be implemented by adding new code to
extend the currect functionality, by using inheritance for example. You shouldn’t need to modify the
existing code.
I think user stories can behave in a similar fashion. When slicing a new feature each story should
keep adding value on top of the value from previous tickets. If a user story conflicts with a previous
story and means a previous story needs to be modified then waste is being created.
Liskov substitution princple
The Liskov substitution principle states that if S is a subtype of T, then objects of type T may be
replaced with objects of type S without altering the properties of the program.
While this doesn’t directly compare with user stories, I feel that user stories can often extend
other stories. As in, build upon or modify existing functionality. When creating user stories that
do this, it may be helpful to keep the Liskov substitution principle in mind. By thinking if the
modification in the new user story will alter or conflict with existing functionality, unpredicted and
undesirable side effects may be avoided. That isn’t to say that changing functionality is a bad
thing, just that as you move towards more granular user stories, taking a step back and thinking
of the wider user story can be useful.
Interface segregation principle
Its better to have many specific interfaces than one large general one.
By following this principle, code can be much easier to read as the smaller, specific interfaces
are much better at conveying the intent of the code over a large interface with many methods that
might not even be used. Furthermore, the increased coupling that will come from a large interface
will make the software less flexible.
Larger user stories can come with the same issues as large interfaces. When there are multiple
requirements the intent of the story can become confusing. Smaller user stories better convey the
intent, and will be easier to assess if the desired value has been achieved.
Also, smaller and separate user stories have less chance of coupling the solutions together. Much in
the same way as to pass a unit test you should do the smallest amount necessary, you should also do
the smallest amount needed to get the value from a story. If more requirements arise, these should
form new user stories.
Dependency inversion principle
Dependency inversion means that high level components should not have dependencies on lower level
components. This inversion can be achieved through abstracting the lower level components behind
interfaces.
While user stories don’t have dependencies in the same way that a class can, I think it could be
helpful to ensure higher level user stories don’t have reference to and depend on lower level
stories. For example, a user story for a new checkout form to increase conversion wouldn’t need the
details of a lower level story for the email validation on the form. If it did, it would be over
complicating the form story and slowing down getting value. However the lower level story would
obviously need to have knowledge of the higher level story.
SOLID User Stories?
After thinking how the SOLID principles can be applied to user stories I can’t see them
becoming the new standard to assess user stories anytime soon. However, thinking of why the
SOLID principles are useful has definitely made me think more about what makes a good user story
and how I can improve ay I write in the future.