Last updated: January 27, 2026

Needs & Requirements

One of the most underappreciated aspects of software design is that of well-defined and well-organised requirements.

Structure

As with anything in software development, if we can be smart about our requirement management, we may be able to reuse the requirements across projects and alleviate a lot of redundant work. Let's break down how this can be done.

Note from Author

Show hierarchical structure of need and requirement relationship. Make it clear how to structure for reusability.

Needs Form Direction

The needs are derived from users and stakeholders.

User Needs

The user is of course to be the primary source of needs. The product should solve the user's needs.

ExampleDescription
1As a user I want to stream music to my device from my phone

Note from Author

Describe what user needs cover

Use Cases

User needs are analyzed by formulating use cases and user scenarios.

Note from Author

Make diagrams

Stakeholder Needs

In addtion to the user's needs we may have stakeholders that impose needs on the system we are to build. The stakeholder may also

  • Marketing
    • Emerging technologies that are to be prioritized to be implemented
  • Developers
    • Usage data and logging thereof (crash reports, etc.)
  • Other

Note from Author

Describe what stakeholder needs cover

Requirements Impose Constraints

Note from Author

Describe how requirements form good constraints for designs. Make examples.

Types of Requirements

TypeDescription
FunctionalAnything that can be tested
Non-functionalAnything that cannot be tested

Functional Requirements

For instance, we might require that the system is fully booted and placed in a well-defined ready-state within a certain amount of time. This is testable, as we can measure it.

Non-functional Requirements

For instance, we might require that the non-volatile memory be of a certain capacity.

Vertical Slicing

In this section it will become evident why needs and requirements have a major impact on the design phase and decisions made therein, as well as how the work can then be used to break down work and even allow you to define interfaces directly from needs.

Example

Let's consider a feature, requested by the organisation.

Loading diagram...

Notice that the component is completely agnostic of the implementation details of the interface it makes use of. We can compile this component without even linking those details at all. This brings several advantages. Most notably we have a clear line of separation between the logic of the component and what ever implementation that might satisfy the interface it calls out to. And this is a key phrasing that I want you to understand; any implementation that satisfies the interface defined by the component, which was derived from the component's needs effectively is a valid implementation — any!

That implies that we can substitute the implementation at any time and the system will still function exactly as before, from the component's perspective, but the underlying implementation on which it depends has be replaced or adapted to some other requirement. One such replacement might be a mock, which we'll dive into now.

Note on Inversion

Note from Author

Rephrase this and put into the vertical slicing.

Perhaps this is mostly due to the fact that people tend to think of an interface as something that connects or bridges code from one component to another, and in embedded programming this often will be some sort of hardware, which inevitably leads to the faulty assumption that you need to define an interface around the hardware you intend to use through that interface.

This is a misguided way to think of interfaces. Instead, when designing an interface, you should instead think of it in terms of the requirements or needs of the component(s) that needs to use the interface — and that's the keyword need. Thinking of it this way allow you to naturally follow the Dependency Inversion Principle.

Testability

Designing your system in this way not only yields a highly modular and composable system that easily adapts to changing needs. It also makes it highly testable.