Title: COS 315
1COS 315 SOFTWARE ENGINEERING 16.
Implementation
2Remember if it's not understandable, it's no
good. "Every moron can write a program that a
computer can understand.It takes a wise man to
write a program that a human can understand."
Anon.
3The Purpose of Implementation
Transforms a design model into executable code
- Need to
- Implement the design classes and subsystems found
during design - Plan the system integration required in each
iteration - Integrate design classes and subsystems by
compiling them and linking them together into one
or more executable components - Distribute the executable components onto nodes
in the deployment model
4Subsystem Implementation
- An implementation subsystem organizes the
artifacts of the implementation model into more
manageable pieces - can consist of components, interfaces and other
subsystems
Each design subsystem is implemented by an
implementation subsystem
- Need a packaging mechanism in the
implementation environment - Examples package in Java
- solution in Visual Basic
- directory of files in a C project
5Object Reusability
- Code may be reused within a project (shared
implementation) or from previously developed
projects - When planning for reuse, keep methods
- Coherent
- Small
- Consistent
- Inheritance can be used to facilitate reuse by
factoring out common code in a method placed in a
superclass
6Extensibility
- Systems may be extended in unforeseen ways.
- To facilitate extensibility
- Encapsulate classes
- Hide data structures
- Use delegation among classes
- Distinguish public and private operations
- private methods increase modularity - limit the
impact of changes on other methods/classes
Note a class is said to delegate to another
class if it implements an operation by resending
a message to another class.
7Robustness
- Code efficiency must not compromise robustness
- To increase robustness
- Protect against errors
- Application (user) and System errors
- Optimise working code - refactor
- Validate arguments
- Avoid predefined limits for data structures
8Coding Conventions Why?
- 80 of the lifetime cost of a piece of software
is in maintenance - Hardly any software is maintained for its whole
life by the original author - Code conventions improve readability
- maintainers can understand new code more quickly
and thoroughly
9Some examples of code conventions (styles)
Indentation and White Space
- Keep lines shorter than 80 characters
- Wrapping lines
- Break after a comma, before an operator
- Align new line with expression on previous line
- Otherwise indent 8 spaces
- Two blank lines to separate
- Sections of a source file
- Between class and interface definitions
- One blank line to separate
- Between methods
- Between local variables and first statement
- Before a block or single-line comment
- Logical sections of a method
10- A blank space should appear
- Between keywords and parentheses
- After commas in argument lists
- Between binary operands
- Between expressions in for statement
- After a cast
Naming Conventions
- Rules for writing identifier name (e.g. classes,
interfaces, variables) - Improve readability
- Provide visual cues to the reader about the role
of the identifier
11Declarations
- Prefer one declaration per line to encourage
commenting - Dont mix types on the same line
- Initialize local variables when they are
declared, if possible - Put declarations at the beginning of a block
- Dont reuse variable names
Statements
- One statement per line
- Preferred indenting for compound statements,
conditionals, iteration, switch,
12Programming Practice
- Provide access to instance and class variables
via setter/getter methods - Numerical constants should not be coded directly
except for 1, 0 and 1 - One variable assignment per line
- Dont confuse and
- Use parentheses for clarity
- Minimize the scope of local variables
- Declare at start of block where used
- Initialize immediately
- Keep methods small and focused
- Know and use the libraries
- Standard libraries have big advantages!
- Important recent additions
13Code Comments
- Comments should be relevant to reading/understandi
ng the program (versus how to build, etc.)
How Much is Too Much?
- Dont comment something that is obvious from the
code. - If you have the urge to write a comment can you
rewrite the code to make it clearer?
(self-evident). Also see Refactoring later - Too many comments can be a sign of poor code
14Refactoring
15What is Refactoring?
- Changing (i.e. rearranging) the structure of the
code in a series of small transformations without
changing its observable behavior to allow for
easier maintenance and modification. - Increase human understandability of code
- You need to have unit tests to prove the code
still works correctly!
16Refactoring
- Basic philosophy
- Start with an existing code base and make it
better. - Change the internal structure (in-the-small to
in-the-medium) while preserving the overall
semantics - i.e. rearrange the factors but end up with the
same final product - The idea is that refactoring should improve the
code in some significant way. For example - Reducing near-duplicate code
- Improved cohesion, lessened coupling
- Improved parameterization, understandability,
maintainability, flexibility, abstraction,
efficiency, etc.
17When to refactor
- You should refactor
- Any time that you see a better way to do things
- Better means making the code easier to
understand and to modify in the future - You can do so without breaking the code
- Unit tests are essential for this
18When to Refactor?
- Third time rule In any program, write some
code, replicate code once, but refactor the next
time - Adding new functions
- Fixing bugs
- Code reviews
- Improve understanding
- Breaking up complexity
- Pros easier to understand, ties design intention
to implementation, isolate changes, encode
conditional logic - Cons more things to manage and understand
19When Not to Refactor
- Databases
- Published interfaces (APIs)
- When code is too broken
- Must rewrite
- Code must work correctly before refactoring!
- When too close to a deadline
- Refactoring requires overhead!
20What to Refactor?
- Bad smells in code (due to Fowler and Beck)
- Anything that is
- Duplicated (Replicated)
- Long
- Complex
- Does very little
- Similar to something else
- Requires sets of changes to different things
- Conditional control flow
- Speculative generality
- There in case you need to have it someday!
- Excessive indirection
- Requires unnecessary knowledge about other
objects - Child classes without necessary parent class
functionality
21Safe Refactoring Test constantly! 1. Ensure
you have an adequate set of tests before
refactoring 2. Make sure you are 100 compliant
with tests before refactoring 3. Refactor 4.
Make sure you are 100 compliant with tests after
refactoring 5. If program fails a test, you
know about it straight away
22An example Refactoring
- Encapsulate Class Data Variable
- To make clients of an object use methods to
access a class variable rather than the variable
directly - Encapsulate Variable
- Create accessor and mutator methods for the
variable - Locate all references to the variable and replace
all accesses to variable with appropriate calls
to accessor and mutator methods. - Compile and test after changing each reference
- Declare the variale as private
- Compile and test
- Refactoring always works in tiny steps
23Original Code public class Person public String
name Original Client ... Person
person person.name Joe Bloggs assertEquals(
Joe Bloggs, person.name) ...
Available in C, C and Java NUnit C and
C JUnit - Java
24Step 1 Create accessors and mutators public
class Person public String name public
String getName() return name public void
setName(String n) name n Client ... Person
person person.name Joe Bloggs assertEquals
(Joe Bloggs, person.name) ...
Compile and Test
25Step 2 Replace direct references with accessors
and mutators public class Person public
String name public String getName() return
name public void setName(String n) name
n New Client ... Person person person.setNam
e(Joe Bloggs) assertEquals(Joe Bloggs,
person.name) ...
Compile and Test
26Step 3 Make variable private public class
Person private String name public String
getName() return name public void
setName(String n) name n New
Client ... Person person person.setName(Joe
Bloggs) assertEquals(Joe Bloggs,
person.getName()) ...
Compile and Test
27New Code
public class Person private String
name public String getName() return
name public void setName(String n) name
n ... Person person person.setName(Joe
Bloggs) assertEquals(Joe Bloggs,
person.getName()) ...
New Client
http//msdn.microsoft.com/msdnmag/issues/04/04/Ext
remeProgramming/default.aspx http//www-128.ibm.co
m/developerworks/library/os-ecref/
28Some Common Refactoring Techniques
- Extract Method
- Replace Temporary Variables with Call Method
- Move Method
29Extract Method
- When?
- Duplicate Code
- Extract common code into separate method
- Long Method
- Extract a number of smaller, more cohesive
methods - Comments
- Extract individually commented blocks to a
separate method
30Extract Method - Example
public double correlation(double x, double
y, int len) // calculate sum of xy
products int i 0 double sumProd 0 while
(i lt len) sumProd sumProd
xiyi ... // calculate sum of squares
x i 0 double sumSquaresX 0 while (i lt
len) sumSquaresX sumSquaresX
xixi // calculate sum of squares y i
0 double sumSquaresY 0 while (i lt len)
sumSquaresY sumSquaresY
yiyi ...
31Extract Methods
- Smells, Symptoms and Refactorings
- Comments in code commenting blocks
- extract method ? extract separate methods for
each block - Duplicate Code
- extract method ? extract common code to a single
method
32public double correlation(double x, double
y, int len) // calculate sum of xy
products int i 0 double sumProd 0 while
(i lt len) sumProd sumProd
xiyi ... // calculate sum of squares
x i 0 double sumSquaresX 0 while (i lt
len) sumSquaresX sumSquaresX
xixi // calculate sum of squares y i
0 double sumSquaresY 0 while (i lt len)
sumSquaresY sumSquaresY
yiyi ...
individually commented blocks
duplicate code
33Original Commented Code Block
// calculate sum of xy products int i 0 double
sumProd 0 while (i lt len) sumProd sumProd
xiyi
public double sumProd( double x,double y,
int len ) int i 0 double sumProd 0
while (i lt len) sumProd sumProdxiyi
return sumProd double sumProd
sumProd(x,y,len)
Refactored Code
34Original Duplicate Code
// calculate sum of squares x i 0 double
sumSquaresX 0 while (i lt len)
sumSquaresXsumSquaresXxixi //
calculate sum of squares y i 0 double
sumSquaresY 0 while (i lt len)
sumSquaresYsumSquaresYyiyi
35Refactored Duplicate Code
public double sumSquares(double a, int len )
int i 0 double sumSquares 0 while (i
lt len) sumSquaressumSquaresaiai
return sumSquares double
sumSquaresXsumSquares(x,len) double
sumSquaresYsumSquares(y,len)
36Refactored Code
- public double correlation(double x, double
y, int len) -
- ...
- double sumProd sumProd(x,y,len)
- double sumSquaresX sumSquares(x,len)
- double sumSquaresY sumSquares(y,len)
- ...
37Long Method
- Symptoms
- Large number of lines in a method (some people
say over 5 to 10 is too many!) - Causes
- Doing more than one cohesive task in a method
- Refactoring
- Extract Method to break up method to smaller
methods
38Long Method Example
public static void report(Writer out, List
machines, Robot robot)throws IOException
out.write("FACTORY REPORT\n") Iterator line
machines.iterator() while (line.hasNext())
Machine machine (Machine)
line.next() out.write("Machine "
machine.name()) if (machine.bin() !
null) out.write(" bin"
machine.bin()) out.write("\n")
out.write("\n") out.write("Robot") if
(robot.location() ! null) out.write("
location" robot.location().name()) if
(robot.bin() ! null) out.write(" bin"
robot.bin()) out.write("\n")
out.write("\n")
39public static void report(Writer out, List
machines, Robot robot)throws IOException
out.write("FACTORY REPORT\n") Iterator line
machines.iterator() while (line.hasNext())
Machine machine (Machine)
line.next() out.write("Machine "
machine.name()) if (machine.bin() !
null) out.write(" bin"
machine.bin()) out.write("\n")
out.write("\n") out.write("Robot") if
(robot.location() ! null) out.write("
location" robot.location().name()) if
(robot.bin() ! null) out.write(" bin"
robot.bin()) out.write("\n")
out.write("\n")
4 distinct parts
40Refactored public static void report(Writer out,
List machines, Robot robot) throws IOException
reportHeader(out) reportMachines(out,
machines) reportRobot(out, robot)
reportFooter(out)
41Long Parameter List
- Symptoms
- A method has many parameters (some say more than
one or two!) - Causes
- Attempt to minimize coupling
- Generalized algorithm
- Refactoring
- If parameter can be obtained from another object
already known to this one, Replace Parameter with
Method. - If the parameters come from a single object, try
Preserve Whole Object - If the data is not from one logical object, maybe
group them with Introduced Parameter
42Long Parameter List - Example
- public void paintComponent(Graphics gr, Component
renderer, Container parent, int x, int y, int
width, int height, Boolean shouldValidate) ...
- Introduce Parameter Object
- public void paintComponent(Graphics gr, Component
renderer, Container parent, Rectangle rect,
Boolean shouldValidate) ...
43Replace Temporary Variable with Call to Method
- Symptoms
- Using temporary variable to hold result of
calculation (expression) - Refactoring
- Extract expression to method and replace all
references to temporary variable with call to
method.
44Replace Temp with Call
public double correlation(double x, double
y, int len) ... double sumProd
sumProd(x,y,len) double sumSquaresX
sumSquares(x,len) double sumSquaresY
sumSquares(y,len) ... return (lensumProd
sumXsumY) / (squareRoot( (lensumSquareX
square(sumX))
(lensumSquareY square(sumY) ))
45Replace Temp with Call - Refactoring
public double correlation(double x, double
y, int len) return (lensumProd(x,y,len)
sum(x,len)sum(y,len)) /
(squareRoot( (lensumSquare(x,len)-
square(sum(x,len))) (lensumSquare(y,len
)- square(sum(y,len))) ))
46Move Method
- Symptoms
- A method is using more features (attributes and
operations) of another class than the class in
which it is defined - Causes
- Often caused as a result of other refactoring
- Refactoring
- Create a new method with a similar body in the
class it uses most. - Either turn the old method into a simple
delegation, or remove it altogether
47Move Method Example
public class Report public static void
report(Writer out, List machines, Robot
robot)throws IOException reportHeader(out)
reportMachines(out, machines) reportRobot(out,
robot) reportFooter(out) ... private
void reportRobot(Writer out, Robot robot)
out.write("Robot") if (robot.location() !
null) out.write(" location"
robot.location().name()) if (robot.bin() !
null) out.write(" bin" robot.bin())
out.write("\n")
48Move Method Example
- Move method to Robot class
- public class Robot
- ...
- public void reportRobot(Writer out)
- out.write("Robot")
- if (location() ! null)
- out.write(" location"
- location().name())
- if (bin() ! null)
- out.write(" bin" bin())
- out.write("\n")
-
- ...
49Move Method Example
- Change call in client
- public class Report
- public static void report(Writer out, List
machines, Robot robot)throws IOException - reportHeader(out)
- reportMachines(out, machines)
- robot.reportRobot(out)
- reportFooter(out)
-
- ...
- private void reportRobot(Writer out, Robot
robot) - ...
50Move Method Example
- Remove method from client
- public class Report
- public static void report(Writer out, List
machines, Robot robot)throws IOException - reportHeader(out)
- reportMachines(out, machines)
- robot.reportRobot(out)
- reportFooter(out)
-
- ...
- private void reportRobot(Writer out, Robot
robot) - ...
51Replace Switch with Polymorphism
- Symptoms
- You have a switch statement that chooses
different behaviour depending on the type of an
object - Refactoring
- Move each branch of the switch to an
overriding method in a subclass. - Make the original method abstract
52Example
- switch statements are very rare in properly
designed object-oriented code - Therefore, a switch statement is a simple and
easily detected bad smell - Of course, not all uses of switch are bad
- A switch statement should not be used to
distinguish between various kinds of object - There are several well-defined refactorings for
this case - The simplest is the creation of subclasses
53class Animal final int MAMMAL 0, BIRD 1,
REPTILE 2 int myKind // set in
constructor ... String getSkin()
switch (myKind) case MAMMAL return
"hair" case BIRD return "feathers"
case REPTILE return "scales"
default return integument"
54Refactoring
Animal
getSkin( ) String
Mammal
Bird
Reptile
getSkin( ) String
getSkin( ) String
getSkin( ) String
55class Animal String getSkin() return
integument" class Mammal extends Animal
String getSkin() return "hair"
class Bird extends Animal String getSkin()
return "feathers" class Reptile extends
Animal String getSkin() return "scales"
56How is this an improvement?
- Adding a new animal type, such as Amphibian, does
not require revising and recompiling existing
code - Mammals, birds, and reptiles are likely to differ
in other ways, and have already separated them
out (so will not need more switch statements) - Have removed the flags needed to tell one kind of
animal from another - Basically, now using objects the way they were
meant to be used
57Refactoring in Visual Studio
58Refactoring http//www.xp123.com/xplor/xp0002b/in
dex.shtml http//www.refactoring.com/ http//www
.knowdotnet.com/articles/examplesandtutorial.html
http//www.techtutorials.info/refactor.html