473,767 Members | 2,224 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Zen and the Art of Requirements Analysis

jwwicks
19 New Member
A Guide for the Beginning CIS Student

Introduction

It's that time again. A new semester is starting and CIS students all over the country are beginning to program. It can be an overwhelming experience trying to decipher syntax while learning to code an assignment effectively. There are many practices I see that cause beginning programming students to suffer through their assignments. I'm going to outline those problems in this article.
I'll use a short typical programming assignment from a first semester class to show the student how to analyze the problem and break it into manageable parts. This assignment converts from one temperature to another, Kelvin, Celsius and Farenheit.


Analysis 101

The biggest mistake I see, besides not checking return codes, is students starting to code without any analysis of the problem. They'll write some code, figure it works, and write some more. Soon a monolithic program is ready to compile and they wonder why there are so many errors. They followed their instructors guidelines to the letter. They've copied the code from the worksheet the instructor has been using as an example for the last 20 semesters. Never mind that the example has nothing to do with the current assignment. Or the specification is deliberately vague in some parts to make the student think about the task. Get used to vague specifications, they are a way of life in development. In a real project a developer will clarify any ambiguities with the client. In academia that client is your instructor. Ask him/her to clarify anything that seems unclear. There's no dishonor in asking questions. Assumption is the mother of all dead programs.

Save yourself the grief of the monolithic program and analyze the problem before coding. Identify the expected output first. This is the end game. This is what we're working toward. Next, identify the data you'll need to complete the task. Then, how is the data entered; read from storage, direct user input or can it be hard coded? Next, decide what tasks get from raw data to the expected output. Finally, break down the tasks into small functions/methods that complete one portion of the task.


The End Game

The specification says convert one temperature scale to another. It doesn't say how the data is entered or whether we convert to all the other scales or not. We'll clarify this later, right now the end game will be this:
  • Given a Kelvin temperature be able to convert to Farenheit and Celsius
  • Given a Celcius temperature be able to convert to Farenheit and Kelvin
  • Given a Farenheit temperature be able to convert to Celsius and Kelvin

The calculations for each of these conversions is well known so I won't outline them here. If you need some help with the math look up Celsius on Wiki.


What's Data Got To Do With It

First we need the temperature, then we need the scale to convert from and then the scale to convert to. The specification isn't clear on these points so we ask the instructor a series of questions:
  • Where is the data coming from, user, storage or hard coded values?
  • What is the format of the input: 247.67K or 247.67 K etc...?
  • Do we ask which scale to convert to or just convert to all the other scales?

For this particular assignment the instructor wants user input. Input should be checked for correctness, no negative Kelvins and no values less than absolute zero. The values for input Temperature will be of the form 247.67 K, 34.56 C and 56.56 F. Data input can be seperated for Temperature and Scale. The letters need to be output in uppercase to match standard conventions but the user should be free to enter lowercase letters. Don't do same scale conversions like Kelvins to Kelvins.


How Do We Get There From Here

The tasks we'll need to complete are:
  • Get user entry of Temperature and Scale
  • Validate Scale entry
  • Validate Temperature entry
  • Get user entry of Scale to convert to
  • Validate Scale entry
  • Convert Temperature
  • Display Results

Here is where another mistake is made by beginning developers. The input and output formats are known, the conversions are known, let's start coding. Generally this approach winds up with all the code stuffed into the Main section of the program with no breakdown of tasks, therefore no reuse except by cut and paste. Testing becomes a headache because the developer has to wade through all this code just to identify a problem area. Changes mean all paths have to be tested to ensure nothing gets broken. The best motto to follow at this point is "Code Small, Test Small". What this means is write compact fully self contained functions or modules that do ONE task, do it well and then move on.


Break It Down, Break It Down

Notice from the tasks in the previous section that validation is done twice for Scale entries. In a monolithic program duplication of code is the result. Make this a function that validates only the correct Scale entries C,F and K. With a little work a generic function that can be reused can be created for this purpose. One solution is to pass in the Scale entry and a string of valid entries. Another solution might also include the return code from the data entry function as a parameter to ensure all the data we expected is entered correctly.

Next tackle the validation for Temperature. Make a function that checks for valid temperatures in different scales. One solution passes in Temperature and Scale and with the use of some simple control statements can complete the task. Adding the return code could be an option as well.

Now for the data entry. The programmer might decide to write two functions, one for Temperature and Scale, the other for just Scale. This is an acceptable solution but a more generic solution might take one more parameter and be able to get either Temperature or Scale or Both in a single function. The function should return the number of successful entries completed.

The conversion process might look daunting at first, a programmer might think that six different functions need to be created. Upon closer inspection though only four are needed:
  • KelvinToCelsius - Takes a Kelvin temperature and returns Celsius
  • CelsiusToKelvin - Takes a Celsius temperature and returns Kelvin
  • CelsiusToFarenh eit - Takes a Celsius temperature and returns Farenheit
  • FarenheitToCels ius - Takes a Farenheit temperature ans returns Celsius

The Kelvin functions are so trivial that they could be inline calculations, just adding or subtracting 273.15, thus reducing the conversion functions to just two.


This is Only a Test

The last problem encountered by beginners is not testing each individual task. Many times a programmer will integrate some function without testing it, only to see a program break. Use a simple test Main to check a function before integrating it into a bigger program. Unit testing frameworks are great as well.


Dawn of the Decomposition

Our program has the following functions:
  • Function MainFunction
  • GetTemperatureS cale( Out Temperature, Out Scale, In Which ) As Integer
  • Function IsValidTemperat ureScale( In Temperature, In Scale, In Which ) As Boolean
  • Function ConvertTemperat ureScale( In TemperatureFrom , In ScaleFrom, In TemperatureTo, In ScaleTo) As Real
  • Function CelsiusToFarenh eit( In Celsius ) As Real
  • Function FarenheitToCels ius( In Farenheit ) As Real
  • Function ShowResult( In Temp1, In Scale1, In Temp2, In Scale2 )

Note: The pseudocode above uses Out for pass by reference and In for pass by value. The As clause is the return type. We also decided to inline the Kelvin conversions.


Summary

In the Temperature example above we identified the result needed, identified the data, created tasks to go from raw data to result. We also worked out some ambiguous requirements with our client by asking a few simple questions before beginning to code a solution. The tasks identified were coded in such a manner that reuse in another program is simple. Testing in small increments meant less code to worry about as we progressed from task to task. The completed program is easier to follow and debug in the long term.


Solutions
Expand|Select|Wrap|Line Numbers
  1. ///////////////////////////////////////
  2. /// \file main.c
  3. /// \brief Main module for Temperature program
  4. /// 
  5. /// \author John `Ghost' Wicks
  6. /// \version 1.0.0
  7. /// \date 2008-08-08
  8. ///
  9. ///////////////////////////////////////
  10. #include <stdio.h>
  11. #include <ctype.h>
  12.  
  13. int getTemperatureScale( double* temp, char* scale, int which );
  14. int isValidTemperatureScale( double temp, char scale, int which, int howMany );
  15. double convertTemperatureScale( double tempFrom, char scaleFrom, char scaleTo );
  16. double celsiusToFarenheit( double temp );
  17. double farenheitToCelsius( double temp );
  18. void showResults( double tempFrom, char scaleFrom, double tempTo, char scaleTo );
  19.  
  20. /////////////////////////
  21. /// \fn main(int argc, char** argv)
  22. /// \brief Main module for Temperature conversion program.
  23. ///
  24. /// \param argc - integer number of arguments passed from system to program
  25. /// \param argv - pointer to array of characters of arguments passed to program from system
  26. ///
  27. /// \return integer value for success or failure
  28. /////////////////////////
  29. int main( int argc, char* argv[] )
  30. {
  31.     int retVal = 0;
  32.     int r = 0;
  33.     double tempFrom = 0.0, tempTo = 0.0;
  34.     char scaleFrom, scaleTo;
  35.  
  36.     do{
  37.         r = getTemperatureScale( &tempFrom, &scaleFrom, 2 );
  38.     }while(!isValidTemperatureScale( tempFrom, scaleFrom, 2, r ));
  39.  
  40.     do{
  41.         r = getTemperatureScale( &tempTo, &scaleTo, 0 );
  42.     }while(!isValidTemperatureScale( tempTo, scaleTo, 0, r ));
  43.  
  44.     showResults( tempFrom, scaleFrom, tempTo, scaleTo );
  45.  
  46.     return retVal;
  47. }
  48.  
  49. /////////////////////////
  50. /// \fn getTemperatureScale( double* temp, char* scale, int which )
  51. /// \brief Gets data from user regarding temperature
  52. ///
  53. /// \param temp - pointer to storage for temperature value
  54. /// \param scale - pointer to storage for temperature scale
  55. /// \param which - allows multiuse of function for just scale (0) or temperature (1) or both (2)
  56. ///
  57. /// \return integer returned from scanf
  58. /////////////////////////
  59. int getTemperatureScale( double* temp, char* scale, int which )
  60. {
  61.     int retVal = 0;
  62.  
  63.     switch( which ){
  64.         case 2:
  65.             printf("Enter the Temperature and Scale (CFK) (Example 270.15 K): ");
  66.             retVal = scanf_s(" %lf %c^%*", temp, scale);
  67.             break;
  68.         case 1:
  69.             printf("Enter Temperature : ");
  70.             retVal = scanf_s(" %lf^%*", temp);
  71.             break;
  72.         default:
  73.             printf("Enter Scale : ");
  74.             retVal = scanf_s(" %c^%*", scale);
  75.             break;
  76.     }
  77.  
  78.     return retVal;
  79. }
  80.  
  81. /////////////////////////
  82. /// \fn isValidTemperatureScale( double temp, char scale, int which, int howMany )
  83. /// \brief Checks if scale or temperature are invalid
  84. ///
  85. /// \param temp - temperature value to check
  86. /// \param scale - scale to check
  87. /// \param which - allows multiuse of function for just scale (0) or temperature (1) or both (2)
  88. /// \param howMany - check to see if all expected values were correctly entered from scanf function
  89. ///
  90. /// \return integer value for success (1) or failure (0) of validation check
  91. /////////////////////////
  92. int isValidTemperatureScale( double temp, char scale, int which, int howMany )
  93. {
  94.     int retVal = 0;
  95.  
  96.     switch( which ){
  97.         case 2:
  98.             if( howMany == which ){
  99.                 switch( toupper(scale) ){
  100.                     case 'C':
  101.                         if( temp >= -273.15 ) retVal = 1;
  102.                         break;
  103.                     case 'F':
  104.                         if( temp >= -459.67 ) retVal = 1;
  105.                         break;
  106.                     default: // Kelvin
  107.                         if( temp >= 0 ) retVal = 1;
  108.                         break;
  109.                 }
  110.             }
  111.             break;
  112.         case 1:
  113.             //Can't check Temperature without knowing scale
  114.             break;
  115.         default:
  116.             if( howMany == 1 ){
  117.                 switch( toupper(scale) ){
  118.                     case 'C':
  119.                     case 'F':
  120.                     case 'K':
  121.                         retVal = 1;
  122.                         break;
  123.                     default:
  124.                         break;
  125.                 }
  126.             }
  127.             break;
  128.     }
  129.  
  130.     return retVal;
  131. }
  132.  
  133. /////////////////////////
  134. /// \fn convertTemperatureScale( double tempFrom, char scaleFrom, char scaleTo )
  135. /// \brief Converts from one temperature scale to another
  136. ///
  137. /// \param tempFrom - temperature value to convert from
  138. /// \param scaleFrom - scale to convert from
  139. /// \param scaleTo - scale to convert to
  140. ///
  141. /// \return double value of temperature converted to
  142. /////////////////////////
  143. double convertTemperatureScale( double tempFrom, char scaleFrom, char scaleTo )
  144. {
  145.     double retVal = 0.0;
  146.  
  147.     switch( toupper(scaleTo) ){
  148.         case 'C':
  149.             if( toupper(scaleFrom) == 'K') retVal = tempFrom - 273.15;
  150.             else
  151.                 retVal = farenheitToCelsius( tempFrom );
  152.             break;
  153.         case 'F':
  154.             if( toupper(scaleFrom) == 'K') retVal = celsiusToFarenheit(tempFrom - 273.15);
  155.             else
  156.                 retVal = celsiusToFarenheit( tempFrom );
  157.             break;
  158.         case 'K':
  159.             if( toupper(scaleFrom) == 'C' ) retVal = tempFrom + 273.15;
  160.             else
  161.                 retVal = farenheitToCelsius( tempFrom ) + 273.15;
  162.             break;
  163.         default:
  164.             break;
  165.     }
  166.  
  167.     return retVal;
  168. }
  169.  
  170. /////////////////////////
  171. /// \fn celsiusToFarenheit( double temp )
  172. /// \brief Converts from Celsius temperature scale to Farenheit scale
  173. ///
  174. /// \param temp - Celsius value to convert
  175. ///
  176. /// \return double value in Farenheit scale temperature
  177. /////////////////////////
  178. double celsiusToFarenheit( double temp )
  179. {
  180.     double retVal = 0.0;
  181.     retVal = 9/5 * temp+32;
  182.     return retVal;
  183. }
  184.  
  185. /////////////////////////
  186. /// \fn farenheitToCelsius( double temp )
  187. /// \brief Converts from Farenheit temperature scale to Celsius scale 
  188. ///
  189. /// \param temp Farenheit value to convert
  190. ///
  191. /// \return double value of Celsius scale temperature
  192. /////////////////////////
  193. double farenheitToCelsius( double temp )
  194. {
  195.     double retVal = 0.0;
  196.     retVal = (temp - 32) * 5/9;
  197.     return retVal;
  198. }
  199.  
  200. /////////////////////////
  201. /// \fn showResults( double tempFrom, char scaleFrom, double tempTo, char scaleTo )
  202. /// \brief Shows the converted temperature value
  203. ///
  204. /// \param tempFrom - temperature value converted from
  205. /// \param scaleFrom - scale to converted from
  206. /// \param tempTo - temperature value converted to
  207. /// \param scaleTo - scale to converted to
  208. ///
  209. /// \return none
  210. /////////////////////////
  211. void showResults( double tempFrom, char scaleFrom, double tempTo, char scaleTo )
  212. {
  213.     printf("Original Temperature: %.2lf %c\n", tempFrom, toupper(scaleFrom));
  214.     printf("Scale To: %c\n", toupper(scaleTo));
  215.     if( toupper(scaleFrom) !=  toupper(scaleTo) ){
  216.         printf("Converting...\n");
  217.         tempTo = convertTemperatureScale( tempFrom, scaleFrom, scaleTo );
  218.         printf("Converted Temperature: %.2lf %c\n", tempTo, toupper(scaleTo));
  219.     }
  220.     else{
  221.         printf("No conversion needed...\n");
  222.     }
  223. }
  224.  
Aug 15 '08 #1
2 4759
asedt
125 New Member
This is good, I like it.

It's to much focus on learning languages in schools general, and I wish for more Software engineering and Design analyse in the introduction courses, because in the real world it’s what matters most.
.
Sep 4 '08 #2
balabaster
797 Recognized Expert Contributor
Fabulous guide - having gone through a computer science course or two, I've often wondered why these principles aren't taught so much (if at all). Of course, the world of academia (in my experience) rarely teaches much in the way of real world skills, like how to apply the theory in a practical environment.
Sep 9 '08 #3

Sign in to post your reply or Sign up for a free account.

Similar topics

0
1572
by: wwalkerbout | last post by:
Greetings, Although, this relates to Analysis Services administration, I thought I'd post it here in case someone with the administrative side of SQL Server who subscribes to this Group may also know Analysis Services and DSO as well. I have a need to run Analysis Services on a single Server instance, but obtaining its data from a SQL Server Cluster. I gather Analysis Services is not designed to work within a SQL Cluster. However, the
9
1603
by: Jimmy Cerra | last post by:
I am a little confused how the memory for objects is allocated in JavaScript. David Flanagan, in "JavaScript: The Definitive Guide," states that each property of a class takes up memory space when instantiated. So space is created for aMethod three times in this example: // Example 1 function aMethod() {/*stuff*/}; function AClass() { /*stuff*/
2
2942
by: kbd | last post by:
Hello: I know that hardware requirements are dependent upon many factors. However I need a sanity check on this configuration. First the purpose of the database. - database will be used to support a risk analysis group in a small financial firm. - there will be daily "bulk" loads to the database - as well as updates via GUIs (JSP or java programs)
2
1441
by: C | last post by:
Hi, I have come mainly from a Development background. I have now to get involved in some Requirements Gathering / Analysis. My Customer is going to give me a brief Requirements document of what they want. I am then going to write a Functional Specification document and get him to
0
1694
by: garry | last post by:
Dear All, Currently we have very urgent requirements for Artix professionals in S'pore.The details of the requirements is as follows: Job Location: Singapore Role · Develop and/or enhance and support existing/future IBIP FE rollouts based on IONA Artix
2
4490
by: =?Utf-8?B?UmljaCBBcm1zdHJvbmc=?= | last post by:
I see that the RTM version of ASP.NET AJAX requires installation of the ASP.NET AJAX assemblies in the GAC. I've been through all the docs, and deployment, per se, is never directly addressed. 1. Is installing System.Web.Extensions to the production server's GAC the only (additional) step required to support ASP.NET AJAX? Or is the distributed installer (.msi) doing other stuff that would be required in a production installation? I've...
9
3042
by: Xah Lee | last post by:
REQUIREMENTS FOR A VISUALIZATION SOFTWARE SYSTEM FOR 2010 Xah Lee, 2007-03-16 In this essay, i give a list of requirements that i think is necessary for a software system for creating scientific visualization for the next decade (2007-2017). (for a HTML version with images, please see http://xahlee.org/3d/viz.html )
0
1453
by: tavares | last post by:
--------------------------------------------------------------------------------------------------------------------------------------------- (Apologies for cross-posting) Symposium "Computational Methods in Image Analysis" National Congress on Computational Mechanics (USNCCM IX) San Francisco, CA, USA, July 22 - 26 2007 http://www.me.berkeley.edu/compmat/USACM/main.html We would appreciate if you could distribute this information by...
0
9571
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9404
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
9959
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
7381
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5279
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5423
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3929
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3532
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2806
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.