Sound advice - blog

Tales from the homeworld

My current feeds

Wed, 2009-Jul-15

A brief introduction to Systems-style Functional Analysis

Software Engineers can easily get out of touch with the work of other engineering disciplines, and I think there are some things we tend to miss out on. Systems Engineering in particular is a discipline with significant synergies with Software Engineering on the large scale, and dovetails into a number of other more specialised disciplines.

Systems Engineering is a somewhat confused term in the trenches. To some software engineers the term is taken to mean "hardware engineer". If it isn't software, it must be hardware... so Systems Engineers are the guys who decide which servers to buy and how to wire the racks together. To others, systems engineers are simply the guys who write the requirements specification. To others again, the term is referring to people who integrate generic software products into turn-key solutions.. ie the guys who write configuration files.

When I talk about Systems Engineering I am referring to the MIL-spec concept: Someone who decomposes large complex systems into smaller systems, subsystems, and configuration items based on a functional analysis and a range of other techniques. The functional analysis approach used by Systems Engineers also has ties to Value Engineering.

Systems Basics

The first step towards understanding how to decompose systems is to understand what a system is. A system is defined in terms of its form, fit, and function:

Form
Form captures most of what consider non-functional requirements. For physical equipment it defines things like size, shape, and weight. More generally, it includes things like throughput, capacity, and latency. For software it includes memory consumption and demands on CPU resources.
Fit
Fit defines the interfaces by which products enter and leave the system. For physical systems this might include the form of raw and finished materials, the mechanism by which rubber bonds to the road in a tyre, the shape of the handle and the striking surface of a hammer head. For software this includes protocol specifications, service contracts, and APIs.
Function
Most important amongst a system's characteristics is its function or functions. A function defines the system's input in an relatively abstract way, and how those input are converted into output. A system's function defines what it is "for", why the customer wants to buy it, and what it should be scoped to "do".

Form, fit, and function are characteristics of a system that can be seen as a black box. Look inside the box, and we can see that systems can be made up of a number of things:

Other systems
A system made up of other systems is sometimes called a "System of Systems". Each system stands on its own in performing is functions more or less independently of other adjacent systems. The failure of an adjacent system may cause inputs to change their behaviour, but do not cause wide-spread collapse or knock-on effects. Some functions of the system of systems may fail, but the functions of individual systems continue operating.
Subsystems
A system made up of sub-systems is less robust, and typically lower-level than a system of systems. A subsystem is like a system in that it processes input into output, has a form, and has a fit. Like a system, a subsystem is also composed of lower-level components that operate to perform the subsystem's functions. However unlike a standalone system, subsystems may depend on each other in ways that can compromise each other's functions. We would ideally like to keep decomposing into systems rather than subsystems for as long as possible, but at some point our luck will run out: Software never constitutes a whole system, because it depends on the hardware it is running on.
Configuration Item
It is only necessary to decompose into subsystems if the constituent parts of a system are too numerous or complex to decompose directly into components. If the system is simple, it can be decomposed directly on to Configuration Items. A Configuration Item (CI) is the lowest level of configuration control of a system, meaning it is the lowest level component that still has its own requirements specification and design document. It is still decomposed within its own design, but onto "Components". CIs can be software or hardware, known as Software Configuration Items (CSCIs) and Hardware Configuration Items (HWCIs). Like subsystems, CIs are defined at a high-enough level that they still have a function relevant to the end use of the system.

Function Diagrams

When setting about a functional analysis I like to use StarUML's robustness diagrams. This is essentially an old-fashioned Structured Analysis approach. I find this approach a much more effective starting point for large systems than either use cases or object-oriented analysis techniques. I start with functions included in the context:

Context Diagram

I like to show a portion of the surrounding system of systems, and the relevant functions within adjacent systems. Stakeholders such as operators of the various systems or customers of a business are also useful to show, and create a useful bound for this diagram. If your system can impact on stakeholders through an adjacent system, even if that system is not directly adjacent but a few hops away that system and that stakeholder constitute relevant context.

From a requirements perspective, the analysis is essentially complete with this one diagram. You write a section in the specification for each of the identified functions. You include the list of input and output, describe the non-functional requirements, refer to documentation for system interfaces, and you're done. In practice this process will almost certainly require some rework and reconsideration of the functions as you go. It is important to characterise all flows in and out of the system and to understand what the system is doing with them and to them. Functions that do not share input or output can be safely split at this level. I generally don't have functions feeding into each other at this level, preferring each function to describe end-to-end processing.

Since we are not following a strict waterfall, the architecture specification is probably being written at the same time as the requirements specification. This too will throw up required changes to the set of functions based on its decomposition:

System Decomposition

The decomposition is onto systems, subsystems, or configuration items. Each of the constituent parts also incorporates an allocation of function. Each function from the context is either implemented directly by a standalone component as a whole, or is decomposed into several lower-level functions with interfaces between. The derived interfaces are configuration controlled along with requirements on the constituent parts.

Perhaps the key thing to understand about this decomposition is that it is not purely functional. We aren't picking bubbles willy-nilly, but allowing a functional decomposition to actively interplay with domain-specific engineering practice. That practice is Software Engineering in this case. The architect who puts the decomposition together uses all of the normal skills of their particular engineering profession to use in defining components that are loosely coupled, and appropriately abstracted, and complete. The functional model winds its way down through the components in parallel to the domain-specific engineering activity. The function allocation acts as an architectural abstraction of functional requirements that makes it easy to relate the lowest-level configuration-controlled elements of a system to their purpose in terms of meeting the needs of the end user:

Function Decomposition

This diagram follows some of the form of a value-engineering "FAST" diagram, with high-level system functions on the left and lowest-level functions on the right. Dependency arrows indicate that the high-level function is achieved by performing the low-level function. Reading in the other direction we can see that the low-level function is implemented in order to achieve the high-level function. If we were performing a value engineering workshop we would now add up all of the costs of the lower-level functions in order to come up with a total cost for the higher-level function. That cost could be compared to the worth of the function to determine if the end user need is being met most efficiently, whether gold plating is being applied to functions the end user does not value, and whether it should be applied more to functions the end user does value. Even without a formal analysis, having a diagram like this allows developers who may otherwise be a long way from the customer to understand the place of their work in the wider context and to make reasonable informed decisions about which parts have to shine.

Rules and Advice

I really try to limit the decomposition to what will fit on these three diagrams. For complex software this may not be possible. I am also prone to draw diagrams relating services to processes, processes to software packages, and software packages to configuration items as part of my broader software architectural descriptions. Nevertheless the context, configuration item, and functional decomposition diagrams should essentially be just that: Three diagrams, each fitting on a page, and each easily understood. In addition to this basic set of constraints there are a number of rules around function naming and structure that aid in ensuring the correct level of abstraction and consistency:

Once the architecture is looking neat you'll probably end up with a requirements specification per Configuration Item, plus Interface Control Documents covering all of the identified flows between components. If you are working below the level of the Configuration Item, such documentation would not be warranted.

This is an approach to decomposing relatively large systems with customers who are potentially quite distant from individual developers, so may not be applicable to everyone. It is only one small aspect of building those kinds of systems, and this has been the barest of introductions. I hope you have found it useful.

Benjamin