David Scott Bernstein's Blog, page 3
April 12, 2022
Break Complex Stories Down into Knowns and Unknowns
In 2020, I finished a series of 72 blog posts that expanded on the first set of “Seven Strategies…” for each practice in my book Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software. I included two sets of “Seven Strategies…” in my book and so I am expanding on the second set here. The next seven blog posts are expanded versions from “Seven Strategies for Splitting Stories”. You can find the original post here.
At the risk of waxing Rumsfeldian, “There are knowns and unknowns.”
The second reason that I find stories are big, aside from being composed of compound stories, is that stories are complex. Complex stories are complex because they have elements that are unknown. So, a complex story has known elements and unknown elements, typically.
An unknown element could be not knowing exactly what the customer or user wants from the story or it may be that we know what they want but we don’t know yet how to implement it.
One of the biggest things that developers who are used to traditional Waterfall requirements must get used to when they’re doing Agile is going into coding without knowing all of the requirements. Agile does this intentionally because it’s more effective and efficient to figure out many requirements as were working through them in the development process rather than trying to do it upfront in a planning process. This is far more efficient, but it does mean that we’re going into iteration with unknowns, which we’ll have to figure out in the middle of the iteration.
I have a whole range of techniques for managing unknowns during an iteration, as well as ways of encapsulating them so they don’t bite me when I’m not expecting it. When I’m confronted with something that I need to know, then typically I’ll stop what I’m doing and figure it out. I often do this in tiny iterations that last anywhere from a few minutes to a few hours.
In my own personal tiny iteration, I will identify the questions I want to address and give it a time limit for when I’ll check in to see how much progress I made. The time limit might be 20 minutes, or it may be a couple of hours. When that time limit is reached, I’ll reevaluate and see if I’ve addressed any of the questions that I had or if I have new questions that need to be addressed, or if I resolved the issue and can just move on.
There are several reasons for not wanting to figure out everything up front before I start coding. I noticed that a lot of the issues that I thought were important while I was planning turnout two either be unimportant or get resolved on their own so that by the time I get into the coding phase they have resolved themselves. Since many issues turn out to be like this, I find that a lot of the things that I thought would be important issues for me turned out to be things that I don’t have to worry about.
Conversely, however, several things that I hadn’t even considered turn out to be quite important while I’m coding, and since I’m not wasting my time on guessing what they are upfront then I have time to address the important ones when they come up.
The post Break Complex Stories Down into Knowns and Unknowns appeared first on To Be Agile.
March 8, 2022
Break Compound Stories Down into Components
In 2020, I finished a series of 72 blog posts that expanded on the first set of “Seven Strategies…” for each practice in my book Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software. I included two sets of “Seven Strategies…” in my book and so I am expanding on the second set here. The next seven blog posts are expanded versions from “Seven Strategies for Splitting Stories”. You can find the original post here.
Story splitting is one of the critical skills in Agile software development. We want stories to be small, as small as possible while still deriving some value to the user.
Story breakdown is both an art and a science that requires learnable skills. I worked on several projects where I thought that our work was so large that it would be very difficult to extract out small stories, only to be proven wrong. I’ve been able to extract small stories from every domain that I’ve worked in. It is not that difficult if we understand how to break out our work to provide the highest value with the fastest delivery time.
We like short stories because stories that are short tend to be more cohesive and uncoupled from other stories. This means that the code that is generated from short stories tends to be more focused and well encapsulated with clearly defined responsibilities.
Shorter stories are also easier to test and validate. The biggest benefit of short stories is that we can implement them quickly so that we can get feedback on them quickly. Agile is all about feedback.
How small should a story be? As small as possible and ideally, I would like my stories to be completed within about four hours. Obviously, there are many kinds of stories that require more time than that, but if I can split out a piece of work into a four-hour chunk then that’s ideal for me.
My reward for breaking stories down into small, heterogeneous chunks is that I no longer have to use story points. I’ve seen story points in Scrum estimation be misused because when we try to use it to measure productivity we almost always fail. Story points weren’t intended to be a productivity measurement. Story points were intended as a capacity measurement.
But if we are able to break out stories or tasks into heterogeneous chunks of work then there’s no need to assign story points to them. We can simply count stories instead of having to estimate the complexity of each story. Then we just look at how many stories we’ve completed during the last iteration and very likely this is the number of stories that will be able to complete in the current iteration. Therefore, there is no need for estimation based on story points.
The first strategy that I want to share with you for splitting stories is one that I use the most. It’s simply about disaggregating stories that are embedded in existing stories. Oftentimes, a story can be broken out into multiple stories because the story is made up of several sub-stories.
If the story is a compound story, then we simply break it down into its components and have each one of its components act as a separate story. This yields smaller stories that are more straightforward to work with.
Breaking down compound stories into their components is the number one technique that I use for breaking down stories. But there are several other techniques that are useful for breaking down stories, which we will cover in the next six upcoming blog posts, so stay tuned.
The post Break Compound Stories Down into Components appeared first on To Be Agile.
February 8, 2022
Use Acceptance Criteria for Stories
I’m wrapping up this series of blog posts based upon Seven Strategies for Writing Better Stories from my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, with my last strategy–use acceptance criteria.
There are many ways to define or break down and split up user stories. Generally speaking, the smaller the better because smaller stories are faster to implement, faster to verify, and give us the opportunity for more frequent feedback. We like small stories and as long as we can see stories are composed of smaller stories then we can decompose them and construct them so that we can recompose them into fuller features later.
A lot has been written on story breakdown. Mike Cohn’s book User Stories Applied is a classic and offers many techniques for story breakdown.
Generally speaking, I find that stories are big, and we don’t like big stories, because of only two fundamental reasons. A story is big either because it is a compound story or because it is a complex story.
If it’s a compound story, then break it down. You already recognize that it’s composed of multiple sub-stories so make each sub-story its own story. Compound stories are great because you can easily split them apart and then later put them back together.
How small should stories be? My answer is as small as possible while still deriving value to the user. Ideally, I’d like to be able to implement a story in less than four hours, and with a good continuous integration server and a clean codebase, you might be amazed at how much can be accomplished in four hours.
The other reason I find stories are big is that they are complex stories. Complex stories are stories that have components that are both known and unknown. It’s the unknown components that make a story complex. When I encounter a complex story then what I try to do is separate out what I know from what I need to know and then iterate on what I need to know until I shrink the unknown and expand the known.
For example, I might research a particular library or technology that I might want to use to accomplish a particular task. Whatever the unknown is, I’ll work on moving it into the realm of the known so that I can better manage it.
Whatever way I define stories, I want to be focused on making them provide value so I define stories in terms of the story’s acceptance criteria. In other words, a story should be defined by the value that it creates.
This is represented by the acceptance tests that we’ve defined for our stories because when our acceptance tests pass our stories are finished and ready to deliver. This makes it really clear where we stand when we’re developing on an Agile project and we can all breathe a sigh of relief.
The post Use Acceptance Criteria for Stories appeared first on To Be Agile.
January 12, 2022
Think About Edge Cases
Continuing my series of posts based on Seven Strategies for Writing Better Stories from my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, here is the next strategy.
Although stories are composed of three elements that include WHAT the feature is, WHO the feature is for, and WHY the feature is wanted, I always think about a fourth element to a story and that is the edge cases. Edge cases represent the boundary conditions of a story. This includes exceptions and error handling as well as alternate and secondary paths of execution.
Often, I’ll jot these edge cases down on the back of a story card as I think of them. They sometimes end up as unit tests that I used to drive the creation of exception handlers.
If I’m using an exception testing framework such as FIT or Cucumber or SpecFlow then these edge cases can be expressed as acceptance tests that I can use to drive the development of the feature. Edge cases include boundary conditions for all parameters, starting with an object’s constructor.
Objects should be instantiated in a stable, ready-to-use state that often involves passing dependencies into an object’s constructor or initialization method. Constructors should be short and simple. They should accept and validate their parameters and if one of the parameters that they depend on is invalid they should throw an exception in languages like Java or C# or C++.
When we’re writing unit tests for exceptions, we have to test two things. First, we have to test that the exception is thrown when it’s supposed to be thrown and this drives us to create the exception handler. Next, we have to test that the exception is not thrown when it’s not supposed to be thrown.
Edge cases help us drive the creation of exceptions and error handling and help make our systems more robust. Edge cases often hold core business rules that need to be expressed in the system and so they’re valuable to document.
But we can go overboard in specifying edge cases and so we want to only really focus on major edge cases in stories. We’re not trying to ferret out all the error conditions or do quality assurance at this point.
We’re simply trying to cover the major cases so that we can come up with a clear high-level definition of the behavior in the system. “The devil is in the details,” as they say. Very often the details are in the edge cases. Capturing them can help us define significant aspects of our systems.
The post Think About Edge Cases appeared first on To Be Agile.
December 8, 2021
Start Simple then Enhance
Continuing my series of posts based on Seven Strategies for Writing Better Stories from my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, here is the next strategy.
Another great aspect of using stories to drive Agile software development is that we can start with simple stories that create a minimal viable feature and then enhance that feature in subsequent stories. This allows us to build the most valuable parts of a feature and find out from the user if more is needed.
When I built a feature, I usually start with the happy path. In other words, I don’t think about what could go wrong, I just think about what could go right. This approach gives me a good sense of what I want to build without worrying about all the things that could cause what I want to do to fail and of the error conditions that could occur. I’ll get to them but first I’ll focus on the happy path.
This is a more efficient and effective way of building software than taking the opposite, more paranoid approach of constantly thinking about what could go wrong. We want to take that perspective as well but it’s better to take the critical perspective in a second pass as an afterthought rather than to start out with that perspective.
This is often reflected in the way I build a feature by starting with the happy path and then peeling off exceptions. Sometimes I take the opposite approach by first writing tests for the exceptions and driving to the happy path.
Note that all of my features and my stories and my acceptance tests are all based upon behaviors that I want to create in the system. Agile software development strongly encourages the notion of creating behaviors because behaviors are testable and they’re also understandable, we can reason about them and talk about them.
Very often when we start with a simple design, that’s all we really need, and we can move on to other things. When we do need more of a design, it’s often because we come across a second situation that’s similar to something that we did before and when we encounter that situation, we can address it and generalize it then.
This is the notion behind doing emergent design or evolutionary design. I was skeptical when I first heard about this idea because it’s difficult to visualize a design emerging on its own, just like it’s difficult to visualize the process of biological evolution. You can’t see biological evolution in action, it takes place over hundreds of millions of years.
Evolutionary design in software happens much more quickly but, in many ways, just as unexpectedly. I end up with designs that I don’t think I’d ever come up with on my own and far better than I would’ve ever come up with on my own.
I don’t know how it happens but using the simple process of test-first development and refactoring to patterns, I’ve discovered elegant solutions effortlessly and I know other developers who have done the same things with the techniques that I’ve been using.
Agile stories and emergent design go hand-in-hand. It’s a powerful and productive way of building software that I highly recommend experiencing for yourself.
The post Start Simple then Enhance appeared first on To Be Agile.
November 10, 2021
Know Why a Feature is Wanted
Continuing my series of posts based on Seven Strategies for Writing Better Stories from my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, here is the next strategy.
One of the most powerful and important aspects of user stories is the WHY clause. WHY a feature is wanted is often never mentioned in written requirements documents or specifications. This is one of the fundamental characteristics of Agile software development where we focus on the WHY so that we are clear on how to meet the needs of our users when we implement a feature.
When we know WHY our users want a feature, we can often build the feature to more directly address their needs. Building software requires making an endless set of decisions in order to build even a simple feature. Understanding the purpose of the feature helps us make those little decisions in the moment more accurately.
But there’s another reason that knowing WHY a feature is wanted is so critical when we’re building it, and that is that it connects all of us to the purpose of building what we’re building in the first place and this helps give meaning to what we do.
If Maslow was right and after our physical needs like food and shelter are taken care of and we begin to start to give back to others and want to make meaningful contributions, then knowing WHY we’re doing what we’re doing can help us on the road to personal fulfillment.
I know some managers who insist that is pointless for developers to know why features are wanted by a user. In their minds, developers should just do what they’re told and that it is even possible to accurately tell someone exactly what to build in a feature, but I don’t think this is always the case.
I don’t want to think about professional software developers as people who simply implement a specification. There’re many aspects to software development that require vastly different skill sets. Some developers are really good about thinking from the user’s perspective. Others are good in terms of thinking about how to implement complex algorithms and still, others might focus on performance.
All of these things are important, but we tend to weigh the importance differently and sometimes we don’t always come to agreements because of it. Knowing the WHY can oftentimes clear up ambiguities and help us build features that are more consistent and on point for what the user wants.
I personally believe that the more a developer knows about WHY a feature is wanted the more the developer can address that need because if the development team isn’t addressing the needs of the user, then they are not being addressed.
Oftentimes, it’s the Product Owner or customer representative that stands in for the user and acts as their proxy. If that individual, and it’s usually best if it is an individual rather than a committee, understands WHY the feature is wanted then she will be able to craft solutions that are more valuable to users.
The post Know Why a Feature is Wanted appeared first on To Be Agile.
October 13, 2021
Personify the Who of Stories
Continuing my series of posts based on Seven Strategies for Writing Better Stories from my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, here is the next strategy.
When developers know WHO a feature is for and can identify with that user then they can often build a better feature that more fully meets that user’s needs. “Walk a mile in someone else’s shoes,” as the saying goes. When we can see the perspective of our users and empathize with them, it helps them get more of what they want from us.
Different users have different needs. They interact with the computer in different ways. These factors are important to consider, both when we are designing and building features as well as when we’re defining feature sets for release. In fact, WHO the feature is for it is particularly important when helping us define the minimal marketable feature-set (MMF) for a release.
When I’m designing a new system, one of the very first things I do is think about who is going to use the system and I jot down the different roles for the people who are going to be using the system. Then I personify those roles by giving each one a backstory. Fiction authors do something very similar, as do actors when there studying their part in a movie.
We can also explore the user’s backstory to more deeply understand a feature that we’re going to build. The goal is to build a feature that addresses the needs of a user and we do this by clearly understanding the user and understanding their needs by putting ourselves in their shoes. This can help us gain insights we might not otherwise get when building a feature.
Sometimes I like to have a little fun with this process. My wife is a filmmaker, and we have a video production studio in our home, complete with full props and costume departments. Sometimes when I’m working with the team on story writing and we get stuck, I’ll bring in some of our costumes and props so that the team can dress up and really step into the shoes of different kinds of users.
We have a lot of fun making up silly names and backstories for these users but at the same time, we’re gaining valuable insight as to how these users think so we can build features that address their needs more fully and completely.
Of course, you don’t have to go to the extremes of dressing up like a user in order to understand their needs. Empathy can come in many forms and simply visualizing what our customers want from their software can help us build features that users are satisfied with.
It’s often true that a feature is for a specific kind of user and addressing features from the user’s perspective helps us segregate features to address specific sets of needs. This can help us fine-tune features for specific types of users. Are the users subject matter experts or are they novices? Do they need step-by-step guidance or are they power users? Understanding these kinds of questions can be just as important as understanding what the features are in the first place.
Knowing WHO a feature is for and WHO a set of features are for can help us better address the needs of our users and helps us create feature sets that are more complete for a particular kind of user.
The post Personify the Who of Stories appeared first on To Be Agile.
September 8, 2021
Focus Stories on the What
Continuing my series of posts based on Seven Strategies for Writing Better Stories from my book, Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, here is the next strategy.
Focus Stories on the What
The most important aspect of a user story is contained in the WHAT clause because that’s where the feature is described. It says WHAT the feature is supposed to do, which defines the primary success criteria for the story.
By simply stating WHAT the story is to accomplish, it gives the developers a clear idea of what the feature they need to build will do and also helps the team define their success criteria so they know when the feature will be done.
Acceptance tests are an important aspect of user stories and acceptance tests are drawn directly from the story’s WHAT clause. The WHAT clause of the story clearly states what the story is to accomplish so it can act as the basis for the acceptance criteria. When the story does WHAT it says it’s supposed to do then the story is done.
This means that each story is unambiguous. Every story should be unique and functionally independent from other stories, as much as possible. If we must have dependencies, then they should be backward dependencies and not forward dependencies. In other words, we should depend on features that we’ve already built rather than having to depend on features that we will build in the future.
Sometimes the WHAT clause of the story doesn’t match the WHY clause and what we say that we are doing doesn’t seem to be in alignment with why we want to do it. When this happens, it raises the opportunity for a different kind of conversation between the development team and the Product Owner or between the Product Owner and the users or customers or stakeholders.
Ideally, the WHAT of a story is in alignment with the WHY of a story and also WHO the story is for. Each story should address the needs of just one specific kind of user of the system. This helps us build systems that are more decoupled with a more complete feature-set for a particular set of needs.
There are various techniques around defining a cohesive set of user stories that address the needs of one type of user. For example, Jeff Patton has a technique called Story Mapping that’s very helpful for creating story themes that address a specific set of user needs. This kind of approach is useful for building a consistent set of features.
I find that the best WHAT clauses are the ones that are stated simply and directly. It’s okay to generalize in a story and miss some edge cases because remember, a story is not a specification, it’s simply a placeholder to have a conversation, and those kinds of details get worked out in the conversation with the team rather than writing them down as part of a document.
Remember, in Agile we say ‘barely sufficient documentation and we say this because documents are expensive to create and maintain plus the fidelity of written documents is far lower than a face-to-face conversation. When describing WHAT to build we should always describe it from the primary user’s perspective in the context of WHY they want it.
The post Focus Stories on the What appeared first on To Be Agile.
August 11, 2021
See Stories as Placeholders
Last year, I finished a series of 72 blog posts that expanded on the first set of “Seven Strategies…” for each practice in my book Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software.
I included two sets of “Seven Strategies…” in my book and I think it’s time to start expanding on the second set. But not all at once. Here is the first set of seven blog posts based on the section Seven Strategies for Writing Better Stories.
Agile says to get rid of long-winded requirements. Get rid of use cases. Get rid of specifications. What is Agile recommend we replace these documents with?
The answer isn’t just user stories because a story is just a single sentence that describes WHAT the feature is, WHY it is wanted, and WHO it’s for. That’s not enough information to build a feature with. But stories were never intended to be enough information to build a feature.
A story is just a placeholder for a conversation that happens between the Product Owner and the development team, and it’s out of this conversation that the team gets enough information in order to build the feature.
This conversation might start during sprint planning but continues throughout the development of the feature. This is why it’s important to have a Product Owner available to answer questions as the feature is being built because, rather than explicitly specifying all the details of a feature before we build it, we discover the details of the feature as we’re building it.
This turns out to be a highly efficient way of creating software. The time and effort required to write down requirements in the form of a specification document and then to read and interpret those documents accounts for a great deal of waste in the software development process. It’s been estimated that poorly defined requirements and the bugs that result from them cost half of our development budget (see https://www.nist.gov/sites/default/files/documents/director/planning/report02-3.pdf).
It turns out that we only have to write down requirements so that they are captured if we have a long development cycle. If it takes three months, six months, or even a year before the feature is actually implemented then we have to write down requirements and I think there is an enormous amount of overhead and waste that results.
But when we build to a feature and our development cycle is measured in weeks or more preferably in days or even hours then we won’t have to write much down, and this vastly improves the efficiency of our software development process.
Stories are valuable because they help us focus on the most important aspects of what we’re building, which is WHO it’s for, WHY it’s wanted, and WHAT it is. Notice that there is no room in a story for implementation details. The business of how to implement a feature doesn’t show up anywhere in the story and this is by design. We don’t want to leak implementation details into our stories because we find that it causes implementation details to leak into our code as well, and this makes code unencapsulated and difficult to change in the future.
By keeping stories focused on the WHAT, the WHY, and the WHO, we can keep the conversation at the right level of abstraction to define what to build and then leave it to the developers to figure out how to build it.
The post See Stories as Placeholders appeared first on To Be Agile.
July 14, 2021
Green Tests and Red Tests
In practice I found that there are times that I want a bit more test coverage than I get from just doing test-first development. When I do test-first development, I always write a failing test first and then I create the implementation to make that failing test pass. As a result, I get by default 100% test coverage for my code. But that still may not be enough. There are edge cases and boundary conditions that may also make sense to have tests for.
So, I think of my tests at three levels. At the highest level are acceptance tests. These tests certify that features are working as expected. The next level is the unit tests I write to drive the creation of my code while doing test-first development. Amir Kolsky calls these kind of test “green tests,” and they’re almost always written in a unit testing framework like JUnit for JAVA or NUnit for .Net.
Green tests are the tests we use to drive the development of our code. They are the result of doing test-first development. Green tests should never break when you refactor code because green tests test behavior; they do not test implementations of behaviors.
Finally, there may be additional tests needed to assure that features behave as they’re supposed to. This can include functional and non-functional tests. I prefer to do much of this kind of testing in a unit testing framework rather than a more traditional testing framework. This allows me to test at the code level. The tests you write after you write the code are what Amir Kolsky calls “red tests.”
Red tests, unlike green tests, may be implementation dependent. They are written after the code is written, during a review process that basically asks: “What else could go wrong?” We don’t ask that question when we’re writing the code initially because we’re in a different mindset. We’re in the mindset of what could go right so we’re laying out what we call the happy path and perhaps picking off a few exceptions along the way.
But just like in creative writing, where we don’t want to try to edit ourselves while we’re in the process of writing, when we’re doing test-first development we don’t have our “QA hats” on. We’re not thinking about what could go wrong. That’s the second stage—the editing process. It happens later. If you try to do both writing and editing at the same time, you often end up with writer’s block. The same thing is true in software development. That’s why I start by writing green tests to build out the behaviors I want to create and then later I go back and write red tests to address any areas I feel I need additional coverage.
The post Green Tests and Red Tests appeared first on To Be Agile.


