1. Overview of Software Engineering Principles
Software engineering can be seen as a technology that includes a process, a set of methods, and an assortment of tools, which are used to build computer software while minimizing cost.A few links
 capability maturitity level
 another link on capability maturitity level
 a scientific american article
In previous course assignments, you may have used an adhoc method to coding – simply sitting in front of the computer and typing code and testing it until it worked correctly.
This is fine for small projects that do not require maintenance, but for larger more complex projects, we require some guidelines or stages to follow or else code and projects become chaotic.
In particular, planning stages are necessary in the work force when you are part of a team developing a system that contains tens of thousands of lines of code. Without a system of control or organization, lots of money and time may be wasted.
As a solution to chaotic programming, software engineering offers some processes that try to assist and control the coordination of software projects.
The most basic process model for software engineering is the Linear Sequential Model, also known as the "classical life cycle" or the "waterfall model". The following diagram and paragraphs outline this approach.
 System/Information Engineering
 gathering info on a systems level
 considering elements such as interfacing software with hardware, people, and databases
 creating a strategic business plan from the requirements gathered and the options available
 Analysis
 determining what the program must do
 including requirements for both the system and the software
 Design
 recording how the program meets the requirements
 focusing on four distinct components: data structure, software architecture, interface representations, and procedural (algorithmic) detail.
 Coding
 implementing the design into a computer language
 Testing
 detecting and fixing errors and demonstrating the correctness of the program (according to requirements)
 Maintenance (after delivered and used)
 fixing errors
 adapting to changes such as in program function (enhancements), or in interface (for instance, in the case of a new operating system)
2. Application: Walking through an Example
(this section is based on the Chapter 1 Case Study in C++ Plus Data Stuctures)So, given this theory on Software Engineering, how can we put it into practice?
Given the problem:
"Write and test a C++ class that represents a fraction."
Where do we start?
Answer: you can go through the stages listed in Section 1. The following subsections breakdown this problem according to these stages.
2.1 Analysis
From your teacher's description of the problem, first write a complete definition of the problem, including the details of expected inputs and outputs. This definition should tell "what" but not "how".
For instance, the teacher has given the following description:
A fraction is made up of a numerator and a denominator. Create operations which enable you to initialize a fraction, get the numerator and denominator, reduce a fraction to its lowest terms, test whether the fraction is equal to zero or greater than 1, and convert a fraction greater than or equal to 1 into its proper form (a whole number and a fracton).This basically defines the problem. Now, you can specify what happens given examples. The following table summarizes three fraction examples:
fraction  initialized/ printed 
reduced  equal to zero 
Is not proper 
printed proper form 

3/4 
numerator=3 denominator=4 
numerator=3 denominator=4 
no  proper  3/4 
5/4 
numerator=5 denominator=4 
numerator=5 denominator=4 
no  improper  1 1/4 
6/8 
numerator=6 denominator=8 
numerator=3 denominator=4 
no  proper  3/4 
You should also specify the format of the input and output. We will specify that the input is two integers typed after the prompt for "numerator:" and "denominator:" The output is "numerator=# denominator=#", "yes/no","proper/improper", or a fraction value according to the table above.
We should also answer the question of what happens in error situations such as when the user inputs a demoninator=0? Perhaps we could print a message that says "Invalid fraction – zero in denominator"
2.2 Design
The design phase works more with the "Hows".
Many design methods are based on decomposing a problem's solution into modules – a cohesive system subunit that performs a share of the work. Cohesive means that each module should have a single purpose or identity and the module should stick together well. A cohesive module can usually be described by a simple sentence. If you have to use several sentences or one very convoluted sentence to describe your module, it is probably not cohesive.
In addition, each module should exihibit information hiding so that changes within it do not result in changes in the modules that use it.
To help visualize the breakdown of the design into modules, a visual tool called Class, Responsibility, and Collaboration (CRC) cards is used. They are used by objectoriented programmers to identify a set of cooperating classes. It is good to know something about these cards because are used throughout your C++ Plus Data Structures textbook.
The CRC cards contain room for the following information about a class: Class name
 Responsibilities of the class – usually represented by verbs and implemented by public functions
 Collaborators – other classes or objects that are used in fulfilling the responsibilities
The nouns become the objects; the verbs become operations.
The card created for our fraction class problem might look something like the
following.
The input specific to this problem is in blue font.
Class name: Fraction Type  
Superclass:  
Subclasses:  
Responsibilities  Collaborations 
Initialize (numerator, denominator)  Integers 
Return numerator value  Integers 
Return denominator value  Integers 
Reduce to lowest terms  Integers 
Is the fraction zero?  Boolean 
Is it greater than one?  Boolean 
Convert to proper fraction  Integers 
 We will create a class called FractionType
 We will have two data members:
 num
 denom
 We will have some member functions:
 Initialize – takes two integer values and stores them in num and denom
 NumeratorIs – returns the value of num
 DenominatorIs – returns the value of denom
 Reduced – checks whether the numerator and denominator have a common factor and, if they do, divides both by the common factor. Stores the result in num and denom.
 IsZero – tests whether the fraction is zero. A fraction is zero if the numerator is zero and the denominator is 1.
 IsNotProper – tests if the numerator is greater than or equal to the denominator.
 ConvertToProper – returns the wholenumber part and leaves the remaining part in the fraction.
Now, we are ready to code the class, but what about a test driver to ensure that this class works correctly?
We will accept some commands from the user and quit only when "Quit" is typed
as keyboard input.
Accepted commands are:
 "Initialize" – to set the numerator and denominator
 "NumeratorIs" – to print out the numerator.
 "DenominatorIs" – to print out the denominator.
 "Reduced" – to reduce the numerator and denominator and print the results.
 "IsZero" – to print out "yes" or "no"
 "IsNotProper" – to print "proper" or "improper"
 "Convert" – convert to proper form and print
2.3 Coding
The code is created in C++ and three files are produced: frac.cpp – contains the implemention of all the FractionType member functions.
 frac.h – contains the definition of the FractionType class.
 fracDr.cpp – contains the code to test the FractionType class.
2.3 Testing
In the past, you may have tested your programs without any method, haphazardly plugging in data until the program fails. There are, however, methods designed for testing: blackbox testing. Testing based on data coverage. The
tester must know the interface – its expected inputs and
outputs – but does not need to know the details of what's
going on "inside".
 goaloriented approach. You test at least one example of each type of input, as well as boundaries and other special cases. For instance, if you have integer input, you should test negative values, zero, and positive values.
 clearbox testing. Testing is based on code coverage.
The tester must look at the lines of code detailing the
functioning of a module.
 statement coverage. Requires that every statement in the program be executed at least once.
Our test plan will document the test cases planned for a program, their purposes, inputs, expected outputs, and criteria for success.
In our fraction project we can test our seven member functions.
For IsZero and IsNotProper, we will have to test the
true and false conditions.
We will need at least one situation where the
numerator is 0, and one situation where the fraction is improper.
We should also test Reduced with one proper and one improper
fraction that can be reduced.
To test our initialization, we should also ensure that it will not accept
a fraction with a 0 in the denominator.
The following might be a test plan for our fraction project.
Test Plan
Reason for Test Case  Input  Expected Output 

To test true condition for IsZero  Initialize 0 1  numerator=0, denominator=1 
IsZero  yes  
To test false conditions for IsZero and IsNotProper  Initialize 3 4  numerator=3, denominator=4 
IsZero()  no  
IsNotProper()  proper  
To test NumeratorIs and DenominatorIs  NumeratorIs  numerator=3 
DenominatorIs  denominator=4  
To test Initialization with Denominator=0  Initialize 5 0  error 
To test ConvertToProper and IsNotProper  Initialize 4 3  numerator=4, denominator=3 
IsNotProper  improper  
Convert  1 1/3  
To test Reduced  Initialize 36 27  numerator=36, denominator=27 
Reduced  numerator=4, denominator=3  
To test Reduced  Initialize 25 35  numerator=25, denominator=35 
Reduced  numerator=5, denominator=7 
In fact, when we try it, our input and output will look like the following:
Please Enter a Command: Initialize numerator: 0 denominator: 1 numerator= 0 denominator= 1 Please Enter a Command: IsZero yes Please Enter a Command: Initialize numerator: 3 denominator: 4 numerator= 3 denominator= 4 Please Enter a Command: IsZero no Please Enter a Command: IsNotProper proper Please Enter a Command: NumeratorIs numerator= 3 Please Enter a Command: DenominatorIs denominator= 4 Please Enter a Command: Initialize numerator: 5 denominator: 0 Invalid fractionzero in denominator Exiting without initializing... numerator= 3 denominator= 4 Please Enter a Command: Initialize numerator: 4 denominator: 3 numerator= 4 denominator= 3 Please Enter a Command: IsNotProper improper Please Enter a Command: Convert 1 1/3 Please Enter a Command: Initialize numerator: 36 denominator: 27 numerator= 36 denominator= 27 Please Enter a Command: Reduced numerator= 4 denominator= 3 Please Enter a Command: Initialize numerator: 25 denominator: 35 numerator= 25 denominator= 35 Please Enter a Command: Reduced numerator= 5 denominator= 7 Please Enter a Command: Quit Testing completed. Press any key to continue
2.4 Maintenance
Maintenance involves making changes to the functioning program to fix operational error and/or to add to or modify the program's function.In our example class that we've been looking at, after going through all these steps, we may realize that there are some shortcomings to this code and running program.
For instance, when we ConvertToProper, the "whole" number is lost to the fraction (see the below running).
Please Enter a Command: Initialize numerator: 8 denominator: 3 numerator= 8 denominator= 3 Please Enter a Command: Convert 2 2/3 Please Enter a Command: NumeratorIs numerator= 2 Please Enter a Command: DenominatorIs denominator= 3 Please Enter a Command: Quit Testing completed. Press any key to continueIt would be nice to have an additional data member called whole. Then, we could convert between proper and improper.
Another improvement to make is to Reduce the fraction before we ConvertToProper.
This is left as the postlab exercise.
3. Lab Exercise
Part 1
Consider the following description:A date is made of year, day, and month. Create operations to initialize a date, get the month, get the day, and get the year.
Your primary tasks for this exercise are:
 Create the CRC card for this class (sheet provided by instructor)
Steps include:

Circle the nouns and underline the verbs in the description.
You can use the nouns to determine your data members and the
verbs to determine your member functions.

Create the CRC card, and show your instructor.
Hint: the date class will have 4 responsibilities.
Part 2
 mydate.h – contains the class definition
 mydate.cpp – contains the implementation of the member functions
 main.cpp – contains the test driver
Steps include:
Today is: 9 20 2011 Birthday is: 9 20 1983 Press any key to continue
Today is: 9 20 2011 Birthday is: 9 20 1983 Happy Birthday Press any key to continue
4. Postlab Exercises
For postlab exercices, click here.
Tuesday, 24Jan2012 10:30:05 CST 




Copyright: Department of Computer Science, University of Regina.