|
|
The system functional requirements will specify the design of the system that we will develop to implement the operational metaphor. In the functional requirements we will contrive a functional metaphor that will make our software system appear to operate in the manner articulated in the operational specification. It will contain the high-level design of an intermediate system to implement the operational specifications.
Just as was the case with the operational system overview, we will need to create a statement of purpose for the system designers. That is the role of the functional system overview. This document will set certain design parameters and take the first step in the restriction of the degrees of freedom in the design process. In the case of the calc system, we could start this constraint development process by insisting that the underlying engine for our calculator be a decimal machine. That is, we will keep all the stack contents for our calculator in either packed decimal internal representation or as a string of decimal digits. This will immediately eliminate the design alternative of using binary arithmetic to represent our numbers internally at the functional level.
As we get further into the specification of the system, we are systematically constraining the problem and eliminating degrees of design freedom at every step. Ultimately, when the time comes to code the system, a programmer will literally have zero degrees of design freedom. Programmers should be automatons: slaves to the design documents.
Just as was the case with the operational requirements, there will certainly be nonfunctional requirements placed on the evolving design. These nonfunctional requirements might well include such items as operating system compatibility, protocol compatibility, and hardware compatibility.
The functional system metaphor will provide a system-level description of how the system will be implemented. In our calc example, we could implement the operational metaphor in any number of ways. We have several choices as to the nature of the arithmetic that we will use on the target machine. We could represent the contents of the stack as binary numbers, as character strings, as decimal strings, as packed decimal or even as floating point numbers. The stack could be represented in a variety of different data structures, such as an array or as a linked list. Even for this simple calc machine there are an astonishing number of degrees of freedom in how we are going to really implement the operational metaphor.
We will now turn our attention to describing the virtual machine (the system metaphor) that we will use to implement the operations. The framework for this machine is shown in Exhibit 2. We can see from this exhibit that there is a basic decimal arithmetic engine that runs the show. Data arrive from the user in an input string buffer. These data are then converted by the engine to a token representing each of the distinct inputs from the user. For example, if we find the string "+426" in the input string buffer, then this will be converted to a decimal number token. Results to be displayed to the user will be converted to an ASCII string and placed in the output string buffer. All arithmetic operators will be applied to the top two operands on the operand stack and the results will be pushed onto this stack. All arithmetic will be performed in decimal and the results of the arithmetic operations will be signed decimal numbers. All decimal numbers will include a sign in the leftmost position followed by ten decimal digits. Only the ten least significant digits of any calculation will be pushed back onto the decimal number stack.
Exhibit 2: Hypothetical Decimal Machine
This decimal machine metaphor is really a trivial example. Necessarily, it would be of limited utility in the real world. It does serve our purpose to convey the essence of the notion of what a functional metaphor should embody. The important thing to note is that the functional metaphor solves the problem of how we are going to implement the user operations. It has constrained the problem from the standpoint of design. There is no doubt as to how the numbers are to be represented in the virtual machine and how arithmetic is to be performed.
The word "functionality" is used to convey the sense of the functional description of the things that the virtual machine described in the functional metaphor will do. Functionalities are in no way to be construed as software functions or subroutine. Functionalities are the operational properties of the functional system metaphor.
A subset of the functionalities for the virtual decimal machine are shown in Exhibit 3. The functionalities listed are certainly not exhaustive. Even in this most trivial of examples it will take a lot of space to represent all of the functionalities. This is because of the degree of specificity of the functionality. It is clearly an issue of granularity of description. We could, for example, define the functionality: add two decimal numbers. Adding decimal numbers, however, is not an easy thing to do. This functionality must be decomposed into its constituent parts. We must have a functionality to check signs. If the signs are different, then we will need to compute the difference and not the sum. We must have a functionality to add decimal digits; we must have a functionality to iterate our digit adder; etc.
Exhibit 3: Functionalities from Hypothetical Software
Functionality | Description |
---|---|
get | Accept a string from the user input line. |
put | Print the string in the output buffer to the user's display. |
analyze input buffer | Convert the input buffer contents to a token. |
pop stack | Load the contents of the top of the stack into the analysis engine. |
copy stack entries | The top two values on the stack are popped, the first number is the divisor, and the second number is the dividend. The remainder is pushed onto the stack followed by the quotient. |
set stack pointer down | Move the top-of-stack pointer to the next entry. |
exit | Exit the program. |
translate number token | The contents of the ASCII string number token are translated to decimal. |
translate decimal value | A decimal number is translated to an ASCII string. |
add decimal digit | Two decimal digits from the signed decimal stack are added with a carry digit and the carry digit is updated from the sum. |
• | • |
• | • |
• | • |
Getting the granularity of definition of a functionality right is not always easy. Perhaps the best way to do this is to start at the highest level, such as: add two decimal numbers, and then decompose this functionality into the next level of specificity until all possible ambiguities have been removed. Again, the purpose of the high-level design is to constrain the solution space for the functional metaphor. We will have achieved the proper level of granularity of specification when all possible solution alternatives have been eliminated, save the one we wish to occur. We do not want programmers performing the design function. If we permit this to occur, they will simply tuck functional specifications into their code where they will reside implicitly. We want the entire functionality of our software to be articulated in the design specification and not in the code. This is a particularly vital consideration if the target language for our calc system will be write-only code such as C or C++.
|
|