Assignment Operator Software Design 2-19-2013 › ~jsearlem › cs142 › sp13 › slides ›...
Transcript of Assignment Operator Software Design 2-19-2013 › ~jsearlem › cs142 › sp13 › slides ›...
Assignment Operator
Software Design
2-19-2013
Assignment Operator
Software Design Methodology
Introduction to Algorithm Analysis
Project #1: MiniMusicPlayer
Quiz Thursday, February 21
destructor, copy constructor, assignment op
Exam#1 – Wednesday, February 27, 7:00 pm, SC356
template <class T>
class Vector {
public:
...
/* destructor – delete the dynamic array */
~Vector( ) { if (buffer_ != NULL) delete[ ] buffer_; }
/* copy constructor – requires a deep copy */
Vector( const Vector & v );
/* assignment operator */
Vector<T> & operator=( const Vector<T> & v );
...
};
When does a class need
a destructor, copy
constructor and an
assignment op?
// the new vector is independent of the original vector
template<class T>
Vector<T>::Vector( const Vector& original ) {
buffer_ = create_new_buffer( original.size( ) );
for (int i = 0; i < original.size( ); i++)
buffer_[i] = original[i];
size_ = original.size( );
}
Vector<int> v1(2);
v1[0] = 36 ;
v1[1] = 24;
Vector<int> v2;
v2.push_back( 12 );
v2 = v1; /* v2’s old value (12) is replaced by a new value (36, 24) */
If a class doesn’t contain an assignment operator, the compiler will automatically generate one, and it will be a shallow copy.
Assignment is an operator in C/C++, and it does two things:
1. Stores the value of the source (right-hand side) into the target (left-hand side). This is called a side-effect.
int x = -7; /* x’s value changed to -7 */
int y = 5; /* x’s value changed to 3 */
x = y - 2; /* x’s value changed to 3 */
2. Returns the value that was stored
cout << (x = y – 2); /* prints 3 & changes x*/
Also note that assignment is right-associative:
e.g.
int x, y, z;
x = y = z = 0; is the same as
x = ( y = ( z = 0) );
implies that the assignment operator stores a value of some type T (in the above case, integer), and returns that value (so the above returns an integer)
Vector<int> v1; /* add some values to v1 */ Vector<int> v2; /* add some values to v2 */ Vector<int> v3;
v2 = v1; /* v2.operator=(v1) */
v3 = v2 = v1;
/* v3.operator=( v2.operator=(v1) ) */
thus, Vector::operator= returns a reference to a vector
Vector<T> & operator=( const Vector<T> & v );
// overloads the assignment operator =
template<class T>
Vector<T>& Vector<T>::operator=( const Vector<T>& v ) {
T* new_buffer = create_new_buffer( v.size( ) );
for (int i = 0; i < v.size( ); i++) new_buffer[ i ] = v[ i ];
if (buffer_ != NULL) delete[ ] buffer_; /* prevents a memory leak */
buffer_ = new_buffer;
size_ = v.size( );
return *this; /* returns the receiver itself */
}
From a user’s perspective, quality software should be:
easy to use
effective
efficient
reliable
robust
(would you add other qualities to this list?)
From a software developer’s point of view, software should be easy to understand, code, test and modify.
modularity and abstraction help to achieve this
Many flavors:
Waterfall
Rapid Application Development (RAD)
Xtreme Programming (XP, an agile methodology)
User Centered
Iteration is done throughout
Guides you through steps in development of technology
Sometimes institutionalized
Mother of all models
Outdated but variations are still widely used
Five stages
Requirements
Design
Code
Test & Verification
Maintain
®
IBM Software Group
© 2007 IBM Corporation
Agile Software Development (ASD)
What is ASD?
How it’s different
Mythbusters
Why does ASD Work?
Some Common Practices
IBM Software Group | Rational software
14
What is Agile?
An iterative and incremental (evolutionary) approach performed in a highly collaborative manner with just the right amount of ceremony to produce high quality software in a cost effective and timely manner which meets the changing needs of its stakeholders.
Core principles
“Fits just right” process
Continuous testing and validation
Consistent team collaboration
Rapid response to change
Ongoing customer involvement
Frequent delivery of working software
In many cases software development has been a “Code – and – fix” process
insufficient for production-level projects
Classic Engineering methodologies
predictive
process-oriented
Lightweight methodologies (agile)
adaptive
people-oriented
Most prominent of the Agile methodologies
Developed in late 1990’s
Adaptability emphasized over predictability
expect requirements to change, so must adapt to them
different from methods which attempt to define all requirements early in the life cycle
Communication: frequent verbal communication to ensure users and developers are on the same page
Simplicity: Start with simplest solution & increase complexity as needed
Feedback: Unit tests, acceptance tests (testing utility), quick estimates
Planning
divide project into iterations
Designing
simplicity
Coding
use standards & conventions
pair programming (two people working together)
Testing
unit test every module
then do integration tests
A Unit test is a test of a small functional piece of code
Easier to find bugs
Easier to maintain
Easier to understand
Easier to Develop
for example, in HW#1 a unit test was written for the Song class
http://www.testdriven.com
http://www.xprogramming.com
http://www-01.ibm.com/software/rational/agile/
AgileAlliance.com
ExtremeProgramming.org
http://www.martinfowler.com/articles/newMethodology.html
To Learn More:
CS350 Software Design & Development
EE368 Introduction to Software Engineering
CS459 Human-Computer Interaction
CS458 Formal Methods for Software Verification
cf. Chapter 1, Maciel, Pay Calculator
specification of the software
what does the software do from the point of view of the user
a good specification is clear, correct, complete and concise
iterative development (incremental)
develop a working prototype of a simpler problem
then successively build more complete versions
specification of the software
iterative development (incremental)
design
large programs are designed as a collection of smaller “software components”
● must identify the components
● decide how to store data
● decide which algorithm to use to perform major tasks
this “modular” approach has several advantages
● easier to implement
● can be divided among several programmers
result: precise specification for each component of the software along with notes on major implementation details
SPECIFICATION
OVERVIEW
This program computes what each employee of a company should be paid for a day of work. The program reads a file containing start and stop times for each employee. The program prints the pay amounts in another file.
see Figure 1.2, Maciel, pp. 2 - 3
SPECIFICATION, continued
DETAILS The input file is called “times.txt” and located in the same folder as the program. The file contains one line for each employee. Each line contains an employee number, a start time and a stop time. These three items are separated by blank spaces.
The output file is called “report.txt” and located in the same folder as the input file and program. The output file contains one line for each employee. Each line consists of an employee number followed by the start time, stop time and pay amount for that employee. These four items are separated by a single space. The times are printed in the same format as in the input file. The pay amount is printed with a dollar sign and exactly two digits after the decimal point. The lines in the output file are sorted in increasing order of employee number …
DESIGN -- DRAFT
Components of the program:
A function that runs the calculator
● implementation notes: delegates the execution of the operations on times to separate functions
A structure that stores each time as two integers, one for the hours, one for the minutes
Functions for operations on times
● initializes a time to 99:99.
● reads a time from an input stream.
● prints a time to an output stream.
● computes the difference, in hours, between two times.
DESIGN -- FINAL
Global constants:
const float kPayRate = 12;
const char kcsTimesFileName[] = “times.txt”
const char kcsReportFileName[] = “report.txt”
Functions:
void run_pay_calculator()
Data types:
Time
A structure that reporsents a time as two integers: hours and minutes
etc.
Figure 1.5, pp. 6-7, Maciel
specification of the software
iterative development (incremental)
design
implementation
write and test the code
● unit test each component
● then test the entire program
preface.txt -------------------------------------------------- 1 After a few computer science courses, students may start to 2 get the feeling that programs can always be written to 3 solve any computational problem. Writing the program may 4 be hard work. For example, it may involve learning a 5 difficult technique. And many hours of debugging. But 6 with enough time and effort, the program can be written. 7 8 So it may come as a surprise that this is not the case: 9 there are computational problems for which no program -------------------------------------------------- next previous open quit ---------- command: o file: introduction.txt
Figure 5.1: Sample interface of the file viewer
void run_file_viewer()
main function of the file viewer
● displays the given number of lines
● asks user what to do next:
►‘q’ quit
►‘o’ open a text file
vector<string> v_document_lines
● data structure for storing the document’s lines
void run_file_viewer() {
vector<string> v_document_lines;
string file_name;
open_file(file_name, v_document_lines);
while (true) { // while command is not 'quit'
display(file_name, v_document_lines);
cout << "command: "; char command = '-';
cin.get(command); cin.get(); // '\n'
switch (command) {
case 'q': return;
case 'o': {
open_file(file_name, v_document_lines);
} // end case ‘o’
} // end switch
} // end while
} // end run_file_viewer
void display(const string & file_name,
const vector<string> & v_document_lines) {
cout << endl << file_name << endl;
string long_separator(50, '-');
cout << long_separator << endl;
for (int i = 0; i < v_document_lines.size(); ++i)
cout << setw(3) << i+1 << " " << v_document_lines[i] << endl;
cout << long_separator << endl << " open quit" << endl;
string short_separator(8, '-');
cout << short_separator << endl;
} // end display
This project is to create a mini music player (along the lines of iTunes or Spotify). Your music player will allow a user to create and modify playlists, and display songs in a playlist. A user will also be able to select and play a song.
User interface: top level
Music Player ----------------------------------------------------------------------------- 1 Favorites
2 Skating Mix
------------------------------------------------------------------------------ (C)reate a playlist (I)nitialize a playlist (S)elect a playlist (D)elete a playlist (Q)uit the music player
User interface: Playlist screen resulting from user typing in 1 from the top level screen
Playlist: Favorites
--------------------------------------------------------------------------------------
1 Deja Blue Charlie Farren 4:02
2 Mad World (Alternate Version) Michael Andrews & Gary Jules 3:38
------------------------------------------------------------------------------ (A)dd a song (D)elete a song (S)elect a song (R)eturn
Characteristics of good software:
easy to understand, construct, test, debug, modify
efficient (fast enough)
How do we measure efficiency?
Two possible contexts:
1. Compare to desired target
measure the precise time, in seconds, on a particular computer for a particular input
2. Compare two possible algorithms
Question: How can we characterize the performance of an algorithm ...
Without regard to a specific computer?
Without regard to a specific language?
Over a wide range of inputs?
Desire: Function that describes execution time in terms of input size (time efficiency)
Another measure might be the amount of memory required (space efficiency)
consider the following code:
for i = 0 to n-1
print a[ i ]
i = 0 cassign is the time it takes to assign a value
i <= n-1 ccompare is the time it takes to compare
a[ i ] cindex is the time it takes to access the ith element
print cprint is the time it takes to print a value
i = i + 1 cincr is the time it takes to increment i
how many times
is each of these
executed?
for i = 0 to n-1
print a[ i ]
The running time of the above loop is:
t(n) = cassign +ccompare +(cindex+cprint+cincr+ccompare) ∙ n
Simplify the expression by letting
a = cindex+cprint+cincr+ccompare
b = cassign +ccompare
yielding
t(n) = an + b
So the running time is a linear function of n.
What happens if n is doubled? quadrupled?
suppose that algorithm 1 has a linear running time, i.e.
t1(n) = a1n + b1
and algorithm 2 has a quadratic running time:
t2(n) = a2n2 + b2
Eventually, when n is large enough, t2(n) will be larger than t1(n)
Analysis of Algorithms
Maciel: Chapter 8, sections 8.4 – 8.5