Software Engineering: CS/ENGRD 2110 Object-Oriented Programming and Data Structures
Software Engineering: CS/ENGRD 2110 Object-Oriented Programming and Data Structures
Software Engineering: CS/ENGRD 2110 Object-Oriented Programming and Data Structures
CS/ENGRD 2110
Object-Oriented Programming
and Data Structures
Spring 2012
Thorsten Joachims
Software Engineering
The art by which we start with a problem
statement and gradually evolve a solution.
There are whole books on this topic and most
companies try to use a fairly uniform
approach that all employees are expected to
follow.
The IDE can help by standardizing the steps.
Top-Down Design
Building a Search Engine:
Bottom-Up Design
Just the opposite: start with parts:
Search Engine
Crawler
Queue
HTTP
Client
Search Engine
Indexer
Database
Hashmap
Inverted
Index
List
Ranking
Function
Pagerank
User
Interface
Spelling
Correction
Crawler
HTTP
Server
Term
Weighting
Queue
HTTP
Client
User
Interface
Indexer
Database
Hashmap
Inverted
Index
Ranking
Function
List
Pagerank
Spelling
Correction
HTTP
Server
Term
Weighting
Composition
Build-It-Yourself (e.g. IKEA furniture)
Software Process
For simple programs, a simple process
Waterfall
13/02/2012
TESTING AND
TEST-DRIVEN DEVELOPMENT
Many people
Write code without being sure it will work
Press run and pray
If it fails, they change something random
Never work, and ruins weekend social plans.
The Example
A collection class SmallSet
containing up to N objects (hence small)
typical operations:
add
adds item
contains
size
# items
Test-Driven Development!
JUnit
What do JUnit tests look like?
SmallSet.java
package edu.cornell.cs.cs2110;
SmallSetTest.java
package edu.cornell.cs.cs2110;
import org.junit.Test;
import static org.junit.Assert.*;
public class SmallSetTest {
@Test public void testFoo() {
SmallSet s = new SmallSet();
...
assertTrue(...);
}
@Test public void testBar() {
...
}
}
13/02/2012
A List of Tests
We start by thinking about how to test,
not how to implement
A First Test
We pick a feature and test it:
SmallSet
class SmallSet {}
SmallSetTest
class SmallSetTest {
@Test public void testEmptySetSize() {
SmallSet s = new SmallSet();
assertEquals(0, s.size());
}
}
Red Bar
A test can be defined before the code is written
Green Bar
Whats the simplest way to make a test pass?
SmallSet
class SmallSet {
public int size() {
return 0;
}
}
SmallSet
class SmallSet {
public int size() {
return 42;
}
}
Adding Items
To implement adding items, we first test for it:
SmallSetTest
class SmallSetTest {
@Test public void testEmptySetSize() ...
@Test public void testAddOne() {
SmallSet s = new SmallSet();
s.add(new Object());
assertEquals(1, s.size());
}
}
Adding Items
The test now fails as expected:
It seems obvious we need to count the number
of items: SmallSet
private int _size = 0;
public int size() {
return 0;
return _size;
}
public void add(Object o) {
++_size;
}
13/02/2012
Refactoring
Too Many
SmallSet (before)
public void add(Object o) {
for (int i=0; i < MAX; i++) {
if (_items[i] == o) {
return;
}
}
_items[_size] = o;
++_size;
}
SmallSet (after)
private boolean inSet(Object o) {
for (int i=0; i < MAX; i++) {
if (_items[i] == o) {
return true;
}
}
return false;
}
public void add(Object o) {
if (!inSet(o)) {
_items[_size] = o;
++_size;
}
}
Size Matters
We first have add() check the size,
SmallSet
SmallSetTest
...
@Test public void testAddTooMany() {
SmallSet s = new SmallSet();
for (int i=0; i < SmallSet.MAX; i++) {
s.add(new Object());
}
s.add(new Object());
}
ArrayIndexOutOfBoundsException
13/02/2012
SmallSet
DRY Principle
Dont Repeat Yourself
A nice goal is to have each piece of
knowledge live in one place
But dont go crazy over it
DRYing up at any cost can increase dependencies
between code
3 strikes and you refactor (i.e., clean up)
Simple Refactoring
Renaming variables, methods, classes for readability.
Explicitly defining constants:
public double weight(double mass) {
return mass * 9.80665;
}
Extract Method
A comment explaining what is being done
usually indicates the need to extract a method
Extract Method
Simplifying conditionals with Extract
Method
before
if (date.before(SUMMER_START) || date.after(SUMMER_END)) {
charge = quantity * _winterRate + _winterServiceCharge;
}
else {
charge = quantity * _summerRate;
}
after
if (isSummer(date)) {
charge = summerCharge(quantity);
}
else {
charge = winterCharge(quantity);
}
13/02/2012
Review
Started with a to do list of tests / features
could have been expanded
as we thought of more tests / features
Is testing obligatory?
When you write code in professional settings
with teammates, definitely!
In such settings, failing to test your code just means
you are inflicting errors you could have caught on
teammates!
People get fired for this sort of thing!
So in industry test or perish!
Fixing a Bug
What if after releasing we found a bug?
13/02/2012