The Dread of Business Requirements

The Dread of Business Requirements

Business requirements are often presented as a boogeyman to developers. They are boring, work on them is futile, and we never get them right. But it doesn't have to be like this. I hope I can inspire a few folks that there is value in understanding the subject and getting better at it. After all, every person on the team has to read these requirements at various levels of the project's advancement, so it is important to read something written in a clear and understandable format.

Requirements have important implications for software systems architecture. Before we design any system, we must know what the system should be doing. We must also understand who is the end user and who wants the feature in question. Without that, we shouldn't design anything. It is key to have requirements before starting systemic design on any level.

There are many ways in which we can write up the system's requirements and its behaviour. The best approaches are taken from the perspective of the user.

The need for requirements can arise for multiple reasons. Typically, someone will request a feature to be implemented. That is called a demand pull. Things are pulled in by customer demand, either indirectly, through customer research, or marketing research, or directly, through a ticketing system (e.g. Zen Desk). Boom! There is a business need, now we need clear requirements.

What initially exists before requirements are fat marker ideas or big fat user stories. 

Fat User Stories 

A user story is an informal description that uses natural language. They are written from the perspective of the end user. A story can include a drawing, or a comic sequence if this makes things easier. Stories are conversational points and drive product discussions.

An example of a big fat user story

Big, fat user stories, are typically called Epics. These artefacts are unspecified pieces of work that need to be carved into smaller bits and pieces (e.g. smaller stories and tasks). For those unshaped items, your Project Manager will, at some point, organise a team session. It will likely include relevant business parties in order to discuss what actually needs to be done.

When items of work are in this early phase–they beg for specification and elaboration–the entire team's exposure is unnecessary. In many teams, this initial contact involves the so-called three amigos. Narrowing initial exposure helps the rest of the team. Three amigos can include a business-centric person, a design-minded person, and a tester. Many modern organisations don’t have dedicated testers, so they can pick up an engineer in this case, typically a lead engineer. Seniority and expertise are key in choosing the right people for the initial meeting. If you are an architect, you will be included in three amigo sessions, filling in the design side of things. (By design here, I mean systems design, not UX/UI.)

Alternatively (or additionally), some companies have Business Analysts (BAs). Those are the people involved in the early stages of feature development. Analysts can be involved in the process by themselves or be one of the amigos in the three amigos mode. Analysts fit the business responsibility.

Back to the user stories. User stories, of any granularity, are conversation starters. This means that one must always have a team-focused conversation about a story. It is best to treat user stories as requests for conversation that must happen to discuss and flesh out their fine details, and progress to implementation.

In all, we now have a picture of big user stories. What can we do next?

Onwards to the Structured Requirements

Fat user stories, as described earlier, cannot explain the system’s requirements. They appear as the first item on our plate, but by themselves, they don't show the whole picture in detail. They are high-level narratives. Furthermore, they only communicate the basic user intent. Inherently, they are so-called black box items, which means as much as they don’t (and shouldn’t) require any special technical knowledge to understand. They are perfect for stakeholders, and they should use user language or stakeholder language. For items that need technical language, we should use technical tasks, not stories.

Nevertheless, systemic logic will not be visible on such a level of abstraction. There is still something amiss here. It is not easy to understand the whole system from its (fat or slim) user stories or even technical tasks if we go that route. The big picture is relatively unclear this way. If all we have is technical tasks or stories, what we end up with is some piecemeal view through which it is notoriously difficult to glue anything into a coherent picture.

To fill this gap, it is often a common mistake to retort to flow charts or even physical architecture diagrams that employ some logical flows in a numbered fashion. This isn’t great, so to speak.

Luckily, there are ways to organise business requirements into a single coherent system, and, at the same time, still frame these from the perspective of the user. It is the use cases. There is vast literature regarding use cases and use case-driven development. One of the greatest books on that topic is Writing Effective Use Cases by Alistair Cockburn.

Use Cases

We can frame requirements early into use cases when gathering initial business requirements. We can then easily project these into our acceptance criteria, scenarios, and automated tests. We'll see it later in action.

First, when we get any user story (fat or not) we can immediately notice some potential for a use case. For example:

Not only does it communicate to us the use case, which is about booking a ticket, but also tells us about the actors involved in our system.

We’ll now explore a simple example of a user Booking a Ticket for a Gig, and capture it in our example use case. 

Use Case: Booking a Ticket for a Gig

Level:

User goal

Actors:

  • User (primary)
  • Ticket Booking System (secondary)
  • Payment System (secondary)
  • Account System (secondary)

Preconditions:

  1. The user must have access to the ticket booking platform (website, app, etc.).
  2. The gig details (date, time, venue, artists performing, etc.) are listed on the platform.
  3. The user has a valid method of payment.

Main Flow:

  1. Search for a Gig: The user logs into the ticket booking platform and searches for the desired gig using relevant criteria (e.g. artist, location, date).
  2. Select Gig: The user selects the gig they wish to attend from the search results.
  3. Choose Tickets: The user selects the type of a ticket (e.g. general admission, VIP) and views the total cost.
  4. Add to Cart: The user adds the selected tickets to their cart.
  5. Checkout: The user reviews the order and checks out the purchase.

Alternative Flows:

  1. Gig Sold Out: If the gig is sold out, the system notifies the user and suggests similar upcoming gigs on the booking page.
  2. User Needs an Account: If the user does not have an account, they must register before proceeding with the booking selection.
  3. Payment Failure: In case of a payment failure, the system prompts the user to re-enter payment details or choose a different payment method.

Postconditions:

  1. The ticket details are saved in the user's account.
  2. The user successfully uses the ticket on the concert date.

And below is the use case diagram which briefly shows all the use cases involved in our feature. Note that use case diagrams can involve many users, for example, there could be a system Admin involved. 

Straight arrow lines describe each use case. Forward dotted lines from a main use case mean that another use case is included in it (see Process Payment). Reversely pointing dotted lines show alternative flows–flows that only conditionally happen. (Those are sometimes called extensions.)

Use cases can describe systems at varying levels of abstraction. There are, in fact, several levels of use cases, named after the level which they describe, starting from the lowest to highest:

Clam: Low-level detail (i.e. low-level subroutine in the program)
Fish: Sub-function (i.e. see Search for a Gig step)
Sea: User goal (i.e. entire Booking a Ticket for A Gig)
Kite: Summary of the system’s goals
Sky: High-level system summary

It's worth considering use cases as a way to capture and organise requirements into a coherent system of specifications. Use cases are user-centric and have a lot to do with client-facing UIs. They are the bread and butter of many analysts, but can also be written out by three amigos.

The drawback of use cases might be the increased effort involved in this step of product development. However, use cases are just a particular format in which requirements are first captured. I believe that using this format pays off in multiple ways, for example, use cases can be directly translated to business logic services in your domain layer (of the application, e.g. SearchAGig , Checkout or AddToCart ). Additionally, use cases give us groundwork for the level C3 (component level) of the popular C4 diagram model that is used to describe software systems.

Now that we know how to frame the requirements from the perspective of a user, let's consider the next steps of the process of describing the system. Let's see how can translate business requirements into automated acceptance tests.

Behaviour-Driven Development

Since we have use cases written out already for our example, let’s use that as a starting point. Image that you received requirements for Booking a Ticket for a Gig in a use case format. (In reality, they might be written in any form).

We have nicely organised requirements that can guide the design of a system, but what exactly do we do next?

How does the team align and get a comprehensive list of acceptance criteria that they can materialise into something like automated tests?

Enter the Behaviour-Driven Development (BDD).

The BDD solidifies the notion that the behaviour of the system should drive (and precede) its development. What this means in practice is that the behaviours, acceptance criteria, and tests themselves are written before any code is implemented. As such, it is closely related to a popular practice called Test-Driven Development (TDD). Just like its cousin, it utilises the approach where we first write failing tests (Red), then we make them pass (Green), and when we make changes (Refactor) we start the cycle again. 

There are two crucial phases of BDD:

  • Discovery phase
  • Implementation phase

The discovery phase at this point is the BDD workshop, in which the team sits down to write User Stories and their corresponding BDD scenarios.

The implementation phase is where we take the scenarios that we’ve written, and write acceptance tests for them. Then we write the code so that the cases pass.

If we recall in our Use Cases for the booking system, we had several steps to achieve what we wanted:

  1. Search for a Gig
  2. Select Gig
  3. Choose Tickets
  4. Add to Cart
  5. Checkout

The above 1-5 points already form a nice sequential process. Each one of these cases is translatable into the conventional story language, such as:

As a User, I’d like to search for a Gig to see all available events
As a User, I’d like to select a Gig to find the details of the event
As a User, I’d like to choose a Ticket for an event that interests me
(…)

And so forth. Some of the steps can be split into multiple stories which create sub-flows of each step. For instance, viewing tickets applied in your checkout section could be another user story. Decomposition is used to reduce the effort required in a single-user story, as they can get large.

On the note of translating use cases into user stories. The difference between a use case and a user story is that the use case is the full specification with the system's failure conditionslevels. Use cases are not designed to be conversation-prompting items. Use cases and user stories may look different but they can be easily translated (back and forth).

Having a full use case specification upfront can save you from an entire discovery workshop session. From that position, it only takes a glance at the use case specification to find and link these to the stories and their scenarios. Much success depends on the way requirements are organised so that we do not miss some aspect of our future features.

Mapping the relationship between a use case and a user story could be one-to-one or one-to-many. Here's an example of one-to-one mapping:

A white oval with purple line

Description automatically generated
Direct one-to-one translation of a Use Case to the User Story

We can then proceed from that part to scenarios:

(You are very much in luck in 2025. We can easily use generative AI tooling to translate use cases into user stories and get the BDD scenarios from it. That saves you a lot of time. This is trivial since use cases describe the entire system's specification in a single document. It's enough to throw the entire use case document to your LLM of choice, and voila! Most of the hard work is done for you.)

As you probably recall from my earlier remark, if we map user stories directly to use cases in a one-to-one relation, user stories could get "fat". This is a bit of a warning. If that's the case, we need to decompose the stories further, so that they are smaller deliverables Eventually, when we are satisfied with how much we decomposed, each part of the process will be a user story that should have scenarios. Those scenarios will serve as the acceptance criteria, which will then be captured in the automated tests.

Scenarios, done the BDD way, have a specific format that we often refer to as Given-When-Then (GWT). For example:

Scenario: Existing user searches for a gig

Given the user is logged into the ticket booking platform
When the user searches for a gig by artist, location, and date
Then the system displays gigs matching the search criteria

And we can easily translate this into automated tests, where Given is a test setup (preconditions) When is the act (the doing), and Then is the assertion. Anyone familiar with AAA (Arrange, Act, Assert) will be familiar with GWT language. 

Let’s see the comparison between AAA:

And BDD (with Cucumber/Gherkin):

It is not that different, after all.

The Rationale for BDD

You might question the purpose of all the BDD work. The purpose is threefold.

First, the product owner is involved in the translation of requirements. Because of this, scenarios resulting from the discovery session are intelligible to everybody, not only technical folk. Now, when it is done the reverse way, where acceptance cases are written to the existing functionality, testers and engineers become bogged down with implementation details such as inputs, fields, models, and routes. What happens is that the scenarios lose their intelligibility and declarative value from the business point of view. Second, after the BDD discovery session, the entire team is well-aligned on acceptance criteria for features that must pass. Third, done this way, the scope of work is known before any part of the work is started. This means that having in mind all scenarios, not only the ticket estimations will get better, but the commitment to deadlines is more realistic. It is not uncommon that if not enough care is taken in the discovery phase of the product, the scenarios and edge cases crop up in the last phases of development, which is bad.

After the discovery phase is concluded, we typically want to conduct a story mapping session where we map user stories to technical tasks. User stories will simply be the hosts of our scenarios, which are implemented by technical tasks. This marks the beginning of the implementation phase. (Note also that this way of working forces vertical alignment between the backend and frontend, because they now work towards fulfilling the user story together–in a truly Agile way).

Since we now understand key aspects of requirements gathering, discovery, and scenarios, we have to see what’s next. This is where our abstract artefacts need to be made into something more concrete, a visible interface. We should make sure that the end product is not only functional but also intuitive and enjoyable to use. We’ll now explore the practice that guides effective UI/UX collaboration so that we can architect user-friendly interfaces and business-friendly systems.

UX and UI Processes

The process of designing the UIs is preferably done according to the system's requirements (Use Cases, Stories). It can also be designed upfront before requirements are gathered. The latter would mean that the UX department paves the way for business requirements.

Beware, here be dragons.

I intentionally put this section after the practice of use cases and BDD discovery. There is a reason for that. It is my opinion that we should first carve the requirements, and then let the UX designer sketch the wireframes. Ideally, this should happen in the same session. A perfect place to start sketching low-fidelity designs is the BDD Discovery session mentioned before. But every company is different, some UI/UX teams only design high-fidelity designs.

If it happens that UX has to forerun the existence of business requirements, it is still best to start with low-fidelity designs and ask the user (or Product Owner) what's the expected behaviour along the way. Low-fidelity designs are essential, but often forgotten. The high-fidelity first approach can be more expensive than starting from the low-fidelity design. If we make the design too specific very early on, then rework of the design is more costly.

The example of a painter should be compelling. Let’s say that you paint portraits and your friend asks you to paint her one. She strikes up a pose, and you proceed to draw. Now, your friend is not entirely aware of the angle that you as an artist see. If you paint an entire picture in six hours, and your friend does not like the angle of your face, you have a very costly update to facilitate. On the other hand, if you started with a small sketch on the canvas and kept asking your friend to verify the angle and the pose along the way, along with the palette and the theme, you wouldn’t have to spend this much time on rework eventually.

(The above example was borrowed from an excellent paper called Using Both Incremental and Iterative Development written by Alistair Cockburn. Even though that paper is related to designing software systems, it is even more apt in this case. Similar mistakes in software architecture are combated in the same way, taking small steps, getting feedback early, and getting feedback often.)

Still, the UX design process can follow the stages of UX discovery that, at first, only involve the customer. UX person researches the market and customer needs. Wireframes are created, along with a quick UI prototype that verifies assumptions. (There can be few A/B tests at this point). All this results in a continuous feedback loop between the designer and the customer, which hardens the hypothesis. The last step is filling a gap between the product owner and the engineering team to deliver a proper market-fit solution.

According to Lean and Agile principles, design and development should be a collaborative effort rather than a sequential process. The danger of the sequential process is falling into a waterfall trap, where developers, who typically have much to say about UIs, are detached from the work of designers. The result is that the problems arise late in the development cycle and propagate back to the UI/UX team, which needs to rework certain solutions. Developers might need to rework some of their technical implementations due to infrequent communication with designers. This is not great. Hence, it is crucial to have good collaborative practice between developers and designers. An architect, or whoever serves that position on the team, should always make sure that this is the case.

As we can see in the above, the typical waterfall model can risk a disjointed development cycle. Issues are found late, in the stage of implementation or testing. Changes propagate up the waterfall.

In contrast, the Agile (and Lean) approach is about short feedback loops early in the cycle. Below is a diagram of the feedback cycle when UX Research is at play:

Once UI and UX are done and features are released, artefacts such as Design Systems and UX Guidelines will be produced. Design System is something that can be exposed and shared between the teams and used by the entire company as a guideline that acts as a reference to the implementation.

An example of the full Process

There was plenty of information in this post, and I hope that people will find it insightful. To reinforce some clarity I will provide a working example of what's (in my view) the ideal process, starting from requirements gathering, up to the actual delivery phase.

Suppose we received the full, yet rough, specification of a feature from the business. After we know the necessary business asks, a team will take these artefacts and run a few sessions together, where acceptance scenarios will be crafted. In those sessions, teams can specify basic functionality and phases of product development. If there is UX/UI involved, it is first designed as low-fidelity designs on initial discovery sessions. From there, the mapping of the stories will occur. From the output of these sessions, we'll have acceptance criteria and automated tests could be written to pass these. Ideally, those tests can precede the development phase (this is sometimes called Acceptance Test-Driven Development–ATDD).

This process can be visualised as follows:

Example Business Requirements and Story Mapping process

Conclusion

Everyone should think deeply about requirements gathering and try to translate requirements into actionable and testable pieces. Overburdening any single person with this task is detrimental to the health of the team, the mental health of the individual and the company overall.

In the cross-functional world of Agile methodologies let's help each other in this task. Let's make better products this way by improving the process of requirements gathering.

Subscribe to Trust Me I'm an Architect

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe