Requirements Engineering

Based on Chp 4 of Sommerville “Software Engineering” (9th edition)

Introduction

requirements are about what a system should do

requirements are not about how a system should be implemented (that’s design and implementation)

the activities of figuring out what users want, how they translate into software, and documenting all this is known as requirements engineering

requirements can be high-level and abstract, or low-level and detailed

Categories of Requirements

the different kinds of requirements can be organized into various categories

for example, one basic organization is:

  • user requirements are what the user wants, and are typically informal and high-level (so that users can easily help create/understand them)
  • system requirements are exact, detailed descriptions of what the system should do, and are specified with more detail than user requirements

keep in mind who will be reading the requirements, and write them for those readers

User vs system requirements, 4.1, Sommerville 9

(Figure 4.1 from Sommerville 9)

Functional and Non-functional Requirements

another basic distinction is functional vs non-functional requirements

functional requirements are about how a system should function, i.e. how it should (or should not!) react to a given input

non-functional requirements are constraints on the services and functions of the system, and are often system-wide

  • the best way to understand non-functional requirements is to look at the examples in the diagram below

Functional and Non-functional Requirements

for example, suppose you are creating a new course-management system for a school

functional requirements for such a system might include:

  • students can see a list all the courses they have taken and are currently enrolled in
  • every day, a list of students currently enrolled in a course will be available to the teacher of the course
  • teachers (but not students) can post announcements to their classes
  • anyone in a class can start, or participate, in a discussion
  • class should be able to make in-class groups of students

on-functional requirements for such a system might include:

  • all data must be stored on Canadian-owned computers
  • all personal information about students (including marks) must be kept private and made available only to the individual student and teaching staff
  • user IDs must be the same as school IDs, i.e. 9-digit numbers
  • up to 20,000 individual students could be enrolled in courses at any one time, and each individual student needs at least 25MB of disk space for files and submissions
  • old courses must remain usable for at least one year after the end date
  • the system should be efficient and easy to use

please note that these requirements are vague and informal, and leave a lot of room for interpretation as to what they actually mean!

a lot of what makes requirements engineering hard is make clear what exactly is required

ideally, discussion with users is needed

  • indeed, Agile methodologies insist upon consistent and frequent user interaction and feedback

but keep in mind just because a user thinks they want feature X, doesn’t really mean they want it!

  • what the user thinks feature X means might be different than what the developer thinks it means
  • or, after getting to use it, the user might discover that they really don’t need or want feature X after all
  • other users have think “not X” is an important feature — so requirements can be inconsistent!

in practice, aim for requirements that:

  • are precise and not open to interpretation
  • can, if possible, be quantitatively tested, i.e. don’t say “the system should be fast”, say it in a way that can be measured, e.g. “the system should have a response 500ms for any user basic interaction”
  • can be demonstrated to users to get their feedback
  • address specific and actual (user) problems
  • can be re-written as necessary during the project to make them clearer, more complete, more consistent, etc.

Non-functional Requirements

Non-functional requirements, 4.3, Sommerville 9

(Figure 4.3 from Sommerville 9)

Requirements Document

in traditional non-Agile software engineering, requirements are summarized in a Requirements Document

this is the official list of requirements for the system

agile software engineering often doesn’t do this, believing instead that requirements change so frequently that such a document will almost always be out of date

  • e.g. extreme programming (XP) writes requirements incrementally and keeps them on index cards that are easy to change

many projects still find it useful to clearly state important requirements

they are useful to users, developers, testers, managers

the textbook includes examples of the sections that might appear in a requirements document (4.2), e.g.

  • preface (who is the document meant to be read by?)
  • introduction (overall description of project, why it’s needed, how it fits with current systems, etc.)
  • glossary (explanations of technical terms)
  • user requirements
  • system architecture (high-level organization of the system)
  • system models (e.g. diagrams of important parts of the system)
  • system evolution (discussion of maintenance and operating concerns after releases, e.g. how will the system be kept running, how will it be upgraded, how will bug fixes and new features be deployed, etc.)
  • appendices (sections on other important topics, e.g. discussion of the database or security tools to be used)

Writing Requirements

requirements are notoriously difficult to write

  • sometimes the actual requirements are unclear
  • or finding the best words that everyone understands can be hard
  • even seemingly simple requirements can have subtleties that can cause problems if not handled well

good requirements should be: clear, unambiguous, easy to understand, complete, and consistent

good requirements should generally not say how they should be implemented

here are some ways that you can write requirements …

Natural Language Requirements

ordinary English sentences written as clearly as possible

use numbering, bullet points, underlining, sections, etc. to help clarity

be careful about using technical terms: make sure you are certain readers know their meaning

  • consider adding a glossary that defines technical terms
  • web hyperlinks can be helpful here, i.e. have hyperlinks to the defintions of all the important terms

sometimes concrete examples can be included to help clarify the intended meaning of a requirement

  • e.g. a sketch of a GUI widget might be a better way to describe the button then using a lot of text
Structured language requirements, 4.9, Sommerville 9

(Figure 4.9 from Sommerville 9)

natural language tends to be relatively easy to write (everyone has had practice writing natural language), but hard to read (due to ambiguities)

Structured Natural Language

structured natural language requirements follow a template, like filling out a form for each requirement

depending upon the systems and type of requirements, different kinds of forms might be used

Structured language requirements, 4.10, Sommerville 9

(Figure 4.10 from Sommerville 9)

Mathematical Specifications

precise mathematical specifications based on logic, set theory, algebra, etc.

in programming, the use of pre-conditions and post-conditions to specify the behaviour of a function is an example of a mathematical specification, e.g.:

// Pre-condition:
//    v.size() > 0
//    T is a type that supports <=
// Post-condition:
//    returns x such that x in v, and for all y in v, x <= y;
//    v is unchanged
T min(const vector<T>& v)

the pre and post conditions are written in semi-formal English, but it is possible to use a precisely defined logic for such things, and have another program check that they are correct and sensible

  • it’s instructive to compare this formal specification approach of the min function to the test-driven development (TDD) version

  • recall that TDD says that you ought to write tests first, and use those to help understand the function you are writing, e.g.:

    min({}) == error
    min({2}) == 2
    min({2,3,1}) == 1
    min({2,2,2}) == 2
    

    a nice thing about this approach is that it makes some of the important cases (like arrays with duplicate values) clear, and forces you to think about how to handle that case

    • in contrast, the formal specification makes no special mention of this case
    • however, it may not always be clear in TDD what test cases should be included, and how many cases are best
    • in TDD, you might simply miss an important case because it didn’t occur to you

relatively hard to read and write: requires training in the relevant mathematics

some modern mathematical specification languages can be checked automatically by computer to ensure the specifications are consist

  • can be extremely useful!
  • but forces you to think clearly and avoid ambiguity
  • takes time to learn, but can be interesting to use for developers since it’s similar to coding
  • in practice, has proven useful in specifying concurrent/parallel systems, where reasoning about the behaviour of interacting processes can be extremely subtle and tricky
  • for instance, here is an example of TLA+

note that universities often hold up mathematical specification as a model of a good way to write specifications

this seems to be because

  • academic computer science is often very closely related to mathematics, e.g. the kinds of problems academics like to study tend to be mathematical
  • academic problems are often relatively small and well-defined, and so amenable to mathematical description

real-life problems often seem more vague, messy, and ill-specified, and there is no obvious way to formalize them

plus the formalization of a real problem is often as difficult as writing the program itself

  • how do you know the formalization is complete and consistent?

Graphical Notation

diagrams and charts are often useful supplements to written requirements

many, many different kinds of diagrams and charts!

the Unified Modeling language (UML) is one popular graphical notation that standardizes a number of popular graphical models

for example, class diagrams are popular for organizing classes in object-oriented programming languages

  • in a class diagram, classes are boxes and arrows show inheritance (is-a) relationships

for example, entity-relationship diagrams in databases

for example, state diagrams represent the state of a system by nodes, and transitions by arrows

  • regular expressions can be treated as state machines

we’ll see some popular kinds of charts later

Requirements Elicitation and Analysis

how do you determine the requirements for a system?

some requirements may be give to you

other requirements may need to be determined by analyzing the problem domain

  • one interesting way to do this is by an ethnographic study, i.e. discovering requirements by watching people doing real work
    • for instance, if you were going to make software for a young child’s electronic toy, watching children play with the toy is probably a good idea

or interviewing future users and other stakeholders

  • a feasibility study might consists of interviews and discussions with stakeholders
  • interviews could be open-ended, or follow a pre-made script of questions
  • interviews could be small, or large
  • good interviewing is a skill that takes practice!

keep in mind that many stakeholders:

  • don’t know for sure what they want
  • use their own terminology that might differ from yours, or be too vague
    • e.g. a manager might say “we want a recursive learning algorithm”, where “recursive” probably doesn’t mean a function that calls itself
  • find it difficult to explain concepts they are deeply familiar with to people who are not also deeply familiar with them
    • can you explain how to ride a bike?
    • many AI-type problems that humans have no problems solving can be difficult in part because no one has a clear, step-by-step way of describing how to solve those problems
  • may have requirements that are inconsistent with the requirements of other stakeholders
  • politics can be involved, e.g. people might try to get their requirements accepted as a way to improve their stature in the company
  • could change their mind, or leave (e.g. get a new job, go on vacation, go on parental leave, …)

some systems might have many different stakeholders, e.g. consider a course-management system like Canvas:

  • students
  • instructors
  • TAs
  • non-teachers who want to use Canvas for one of its features, e.g. as a discussion group, or as a way to post learning materials for staff
  • course designers
  • system administrators (responsible for keeping the system running)
  • guests, who want to explore the system or try it out without committing to a role

once you have the basic requirements, you should

  • organize them
  • prioritize them
  • write clear specifications for them

Use Cases (Scenarios)

a good way to discover requirements is to have stakeholders discuss common usage scenarios

we’ll call these use cases, i.e. examples of uses

different methodologies have different terms for these, and may differ in the details of what exactly they are

but the key idea is the same: a use case describes a common usage scenario for a system

use cases are usually more concrete and easier to think about than abstract requirements

use cases are often easy to base on actual usage of similar software

Use Cases

use cases typically describe an interaction between users and the system

a good use case identifies the users by their role, and how they interact with the system

Example use case, 4.15, Sommerville 9

(Figure 4.15 from Sommerville 9)

Requirements Validation

how do you know your requirements are clear, complete, and consistent?

basically, review the requirements carefully with these things in mind!

get experts to help out if you can

  • real users
  • human editors can help with grammar, style, and clarity

another way to check requirements is to create a prototype

  • a small, limited-function version of the system meant to check important requirements
  • prototypes need to be completed more quickly than the final product, and so may use special prototyping tools

another way to check the quality of a requirement is to derive test cases from it

  • all requirements should be testable! otherwise, how would you know if they’ve been met?
  • if you can’t think of how you would test the requirement, it may be too vague or too big and so should be re-written

Managing Requirements

as you might guess, in a large project managing requirements is a non-trivial task

there are lots of them, they have to be written carefully, they can change, etc.

even basic questions like how should requirements be stored can become tricky in big projects

  • in a database?
  • in HTML or markdown (don’t forget that any images would in separate files)?
  • would requirements files and folders have a standard format?

it takes time, money, and expertise to do all this well

you probably also want to save the things that worked well to re-use in future projects

so in big projects it pays to think carefully about how to manage requirements

  • need to keep track of who changed a requirement, and why they changed it
  • changing one requirement might have an impact on other parts of the system
  • there maybe significant costs associated with a requirements change, e.g. changing the database might require buying a new database, or buying support tools

section 4.7 of Sommerville 9 gives some ideas for how requirements might be managed