Objectives: On completion of this project the student should be able to:

Similar documents
Refactoring. Chen Tang March 3, 2004

Refactoring, Part 2. Kenneth M. Anderson University of Colorado, Boulder CSCI 4448/5448 Lecture 27 12/01/09. University of Colorado, 2009

Refactoring. Software Engineering, DVGC18 Faculty of Economic Sciences, Communication and IT Eivind Nordby

AntiPatterns. EEC 421/521: Software Engineering. AntiPatterns: Structure. AntiPatterns: Motivation

Refactoring 101. By: Adam Culp

Refactoring. In essence we improve the design of the code after it has been written. That's an odd turn of phrase.

Introduction to Refactoring

Refactoring Exercise

Understading Refactorings

Course December Adrian Iftene

Refactoring with Eclipse

Software Design COSC 4353/6353 D R. R A J S I N G H

Credit where Credit is Due. Lecture 25: Refactoring. Goals for this lecture. Last Lecture

Lecture 12, part 2: Refactoring. NCCU Fall 2005 Dec. 13, 2005

More on Design. CSCI 5828: Foundations of Software Engineering Lecture 23 Kenneth M. Anderson

void printowing(double amount) { printbanner(); printdetails(); void printdetails(double amount) {

Refactoring, 2nd Ed. A love story. Michael Hunger

CS247. Today s topics. Design matters. What is refactoring?

Refactoring: Improving the Design of Existing Code

DAT159 Refactoring (Introduction)

McCa!"s Triangle of Quality

MSO Refactoring. Hans Philippi. October 2, Refactoring 1 / 49

Test Driven Development and Refactoring. CSC 440/540: Software Engineering Slide #1

COURSE 11 DESIGN PATTERNS

Software Engineering Refactoring

Evolving Software. CMSC 433 Programming Language Technologies and Paradigms Spring Example. Some Motivations for This Refactoring

Refactorings. Refactoring. Refactoring Strategy. Demonstration: Refactoring and Reverse Engineering. Conclusion

Refactoring. Refactoring Techniques

Administrivia. Programming Language Fall Example. Evolving Software. Project 3 coming out Midterm October 28. Refactoring October 14, 2004

Overview of Eclipse Lectures. Module Road Map

Refactoring. Paul Jackson. School of Informatics University of Edinburgh

Refactoring. George Dinwiddie idia Computing, LLC

Refactoring. Section (JIA s) OTHER SOURCES

Kerievsky_book.fm Page 355 Thursday, July 8, :12 PM. Index

Implementing evolution: Refactoring

Small changes to code to improve it

Designing with patterns - Refactoring. What is Refactoring?

Analysis of the Test Driven Development by Example

Refactoring. Kenneth M. Anderson University of Colorado, Boulder CSCI 4448/5448 Lecture 27 11/29/11. University of Colorado, 2011

Imagine you ve written a piece of code but then accidentally deleted and lost it.

Outline. Logistics. Logistics. Principles of Software (CSCI 2600) Spring Logistics csci2600/

Living and Working with Aging Software. Ralph Johnson. University of Illinois at Urbana-Champaign

Hugbúnaðarverkefni 2 - Static Analysis

Software Design and Analysis CSCI 2040

Patterns in Software Engineering

Implementing evolution: Refactoring

Code Refactoring. CS356 Object-Oriented Design and Programming November 21, 2014

Detecting Structural Refactoring Conflicts Using Critical Pair Analysis

Metaprogramming and Reflection Refactoring

This course supports the assessment for Scripting and Programming Applications. The course covers 4 competencies and represents 4 competency units.

CS 351 Design of Large Programs Coding Standards

11/2/09. Code Critique. What goal are we designing to? What is the typical fix for code smells? Refactoring Liskov Substitution Principle

Example of OO Design Refactoring

CS 315 Software Design Homework 3 Preconditions, Postconditions, Invariants Due: Sept. 29, 11:30 PM

Project #1 rev 2 Computer Science 2334 Fall 2013 This project is individual work. Each student must complete this assignment independently.

Refactoring and other small animals

Abstract: Refactorings are used to improve the internal structure of software without changing its external behavior.

Reengineering II. Transforming the System

Tutorial 02: Writing Source Code

A Catalog and Classification of Fortran Refactorings

Lecture 3. COMP1006/1406 (the Java course) Summer M. Jason Hinek Carleton University

CMPSCI 187 / Spring 2015 Hangman

CSSE2002/7023 The University of Queensland

Basic Keywords Practice Session

Proceedings of the 8 th International Conference on Applied Informatics Eger, Hungary, January 27 30, Vol. 2. pp Virtuoso Virtuality

Chapter01.fm Page 1 Monday, August 23, :52 PM. Part I of Change. The Mechanics. of Change

SAFEREFACTOR Tool for Checking Refactoring Safety

Introduction to Object-Oriented Programming

Refactoring and Rearchitecturing

B. What strategy (order of refactorings) would you use to improve the code?

CHAPTER 11 Refactoring

CMPSCI 187 / Spring 2015 Postfix Expression Evaluator

CHAPTER 11 Refactoring

Introduction to Extreme Programming. Extreme Programming is... Benefits. References: William Wake, Capital One Steve Metsker, Capital One Kent Beck

CSCE 156 Computer Science II

Refactoring. Kenneth M. Anderson University of Colorado, Boulder CSCI 4448/5448 Lecture 27 04/19/11. University of Colorado, 2011

Design Patterns. CSC207 Fall 2017

SOFTWARE ENGINEERING SOFTWARE EVOLUTION. Saulius Ragaišis.

CS ) PROGRAMMING ASSIGNMENT 11:00 PM 11:00 PM

Making Program Refactoring Safer

Introduction to Extreme Programming

Outline. Software Rots

Assignment 8: Sokoban

Tutorials. Tutorial every Friday at 11:30 AM in Toldo 204 * discuss the next lab assignment

San José State University Department of Computer Science CS151, Section 04 Object Oriented Design Spring 2018

How We Refactor, and How We Know It

On the automation of challenging refactorings through advanced method extraction techniques

Levels of Testing Testing Methods Test Driven Development JUnit. Testing. ENGI 5895: Software Design. Andrew Vardy

The Object Recursion Pattern

Tool Support for Complex Refactoring to Design Patterns

Design Patterns. CSC207 Winter 2017

HOW AND WHEN TO FLATTEN JAVA CLASSES?

CPS122 Lecture: Detailed Design and Implementation

Carrera: Analista de Sistemas/Licenciatura en Sistemas. Asignatura: Programación Orientada a Objetos

JAVA MOCK TEST JAVA MOCK TEST II

CSE115 / CSE503 Introduction to Computer Science I Dr. Carl Alphonce 343 Davis Hall Office hours:

Understanding How Java Programs Work

Inheritance and Substitution (Budd chapter 8, 10)

Testing and Debugging

Source Code Rejuvenation is not Refactoring

Transcription:

ENGI-0655/5232 Software Construction and Evolution Project 1 Reverse Engineering Refactoring & Object Oriented Design Due date November 10, 2009-4:00 pm 1. Aims The aim of this project is to give you more experience with refactoring, and especially refactoring that relate to multiple classes. Some of the refactoring that we ll do here could be justified well in a larger system. However, the only way to get good at refactoring is to practice, and smaller examples are easier to begin with. You will also learn how to recover system design from the code. Objectives: On completion of this project the student should be able to: a) carry out a variety of refactoring, including: renaming variables, extracting and moving methods closer to home, and creating classes and interfaces. b) Develop a strategy where refactoring is carried out in small steps, with the tests being run after each change so that one can quickly recover from any faults that are introduced as part of the refactoring process. c) Introduce changes as part of the refactoring process to enhance the softwaredesign from an object-oriented point of view. d) Develop an understanding that there is often a tension between the different ways that code can be structured, and it s not always obvious that a planned refactoring will lead to an improvement. 2. Background In software engineering, "refactoring" source code means modifying it without changing its behavior, and is sometimes informally referred to as "cleaning it up". Refactoring neither fixes bugs nor adds new functionality, though it might precede either activity. Rather it improves the understandability of the code and changes its internal structure and design, and removes dead code, to make it easier to comprehend, more maintainable and amenable to change. Refactoring is usually motivated by the difficulty of adding new functionality to a program or fixing a bug in it. In extreme programming and other agile methodologies, refactoring is an integral part of the software development cycle: developers first write tests, then write code to make the tests pass, and finally refactor the code to improve its internal consistency and clarity. Automatic unit testing ensures that refactoring preserves correctness. Code smells (i.e. any symptom in the source code that indicates something may be wrong) are a heuristic to indicate when to refactor, and what specific refactoring techniques to use. An example of a trivial refactoring is to change a variable name into

something more meaningful, such as from a single letter 'i' to 'interestrate'. A more complex refactoring is to turn the code within an if block into a subroutine. An even more complex refactoring is to replace an if conditional with polymorphism. While "cleaning up" code has happened for decades, the key insight in refactoring is to intentionally "clean up" code separately from adding new functionality, using a known catalogue of common useful refactoring methods, and then separately testing the code, to ensure that existing behavior is preserved. The aim is to improve an existing design without altering its intent or behavior. List of refactoring techniques: Here is a very incomplete list of code refactorings. A longer list can be found in Fowler's Refactoring book and in Fowler's Refactoring Website (see references). Techniques that allow for more abstraction o Encapsulate Field - force code to access the field with getter and setter methods o Generalize Type - create more general types to allow for more code sharing o Replace type-checking code with State/Strategy o Replace conditional with polymorphism Techniques for breaking code apart into more logical pieces o Extract Method, to turn part of a larger method into a new method. By breaking down code in smaller pieces, it is more easily understandable. This is also applicable to functions. o Extract Class moves part of the code from an existing class into a new class. Techniques for improving names and location of code o Move Method or Move Field - move to a more appropriate Class or source file o Rename Method or Rename Field - changing the name into a new one that better reveals its purpose o Pull Up - in OOP, move to a superclass o o 3. Project Description Push Down - in OOP, move to a subclass Shotgun surgery - in OOP, when a single change affects many classes. In this case we keep all affecting code in a single class so that we make changes only at one place. You are supplied with the Java classes Movie, Rental and Customer. A Movie is one of three types: CHILDRENS, REGULAR and NEW RELEASE. The type determines the charge for the rental and the number of frequent-renter points for that movie. A Rental is of a Movie for a number of days. A Customer may make several Rentals. The Customer

method statement() provides a summary of the rented movies, charges and frequentrenter points. The class TestMovieRental has some simple unit tests. The last unit test is commented out; we ll make use of that in a later step. The aim is to add an HTML summary to the program. However, the program as provided is very smelly it appears that the author of the program doesn t understand object-orientation. So we will first refactor the code step by step to make it easier to add the new code. We then try to recover part of the system design by drawing the class diagram of the Movie rental system. 4. Required Tasks The source code for this project is available as project1.zip under Resources for Project 1 on WebCT. If you wish, you may start by converting the program to use JDK under eclipse. This project consists of 17 refactoring steps as described below. You will need to understand the code you modify, by the end of the series of changes. After finishing refactoring the software, you will draw the class diagram of the software. You are to work in groups of no more than 3 people. Step 1: Extract method chargeforrental() The method statement() in Customer is rather long and unwieldy. We should be able to use some of this code for generating HTML, but we would end up with a lot of duplication if we simply copied and altered it as it is. Extract out a private double method chargeforrental() that is responsible for calculating the charge for a particular Rental. Step 2: Rename variables If you haven t already done so, improve the names of the two variables in the code you extracted into chargeforrental(), because they need to be more specific and helpful. Eg, change each to rental, and change thisamount to charge. Make sure that the tests still pass. Step 3: Move method costforrental() Now that we have chargeforrental() extracted, it s clear that all of the logic is concerned with the Rental and Movie and it does not depend on the Customer. So move the method chargeforrental() into the class Rental, rename it charge() and make it public. In doing so, the code changes to take account of its new context (eg, so that a reference to rental.getdaysrented() changes to this.getdaysrented() and then to getdaysrented()). The statement calling this method in Customer changes from: to charge = chargeforrental(rental); charge = rental.charge();

Step 4: Extract method charge() and move it Now we can see that the method charge() in class Rental is making use of the internals of Movie. So we need to extract most of it and move it into Movie. But the logic depends on the number of days rented, so this needs to be passed as a parameter. So the method in Rental turns into: public double charge() { return movie.charge(daysrented); Step 5: Extract method frequentrenterpoints() As with the previous two steps, there is still some code in Customer that doesn t belong there. Extract out a method frequentrenterpoints() and then move it into the class Rental. It is may be easier to do this kind of refactoring in two steps (first extract the method locally, then move it to the other class), running the tests in between. Make sure that the tests still pass. Step 6: Extract method isnewrelease() Now that we get it into Rental, we can see that it contains the price code test that s rather specific to Movie. Extract a boolean method isnewrelease() and place it in Movie, where it belongs. Step 7: Rename variable; Change to for loop Now we look at what s left, we can see that there is a variable in method statement() in Customer that could be improved. Change the Rental each to Rental rental. We also see that a while loop is used to process each of the rentals, but it would be clearer to use a for loop. Change that. Make sure that the tests still pass after each little change. Step 8: Write test case for HTML We can now introduce a test case for the HTML statement that we want to be produced. public void testhtmlcustomer() { customer.addrental(rentmatrix); customer.addrental(rentmatrix2); assertequals("<html><head><title>rentals: John Hood</title> </head><body>\n"+"<h1>rentals: John Hood</h1>\n"+ "<table border=1><tr><th>days</th><th>title</th><th> Charge</th></tr>\n"+"<tr><td align=right>4</td> <td> Matrix<td align=right>$5.0</td></tr>\n"+ "<tr><td align=right>5</td><td>matrix2<td align=right>$15.0</td> </tr>\n"+ "<tr><td></td><td><i>total</i><td align=right> $20.0</td></tr>\n"+ "</table><p>frequent renter points=3 </p>\n"+"</body></html>\n", customer.htmlstatement()); But don t uncomment it yet, as we need to do some refactoring before we can implement it in Step 17. Step 9: Extract method rentalline() To get closer to handling HTML, let s extract the display methods, and we ll then use them to generalize the output. First, introduce a private method rentalline() that takes three arguments and generates the string. So the code that used to be:

result += rental.getdaysrented() +" days of " + rental.getmovie().gettitle() +" $" + charge + "\n"; changes to: result += rentalline(rental.getdaysrented(), rental.getmovie().gettitle(),charge); Step 10: Move method rentalline() Now that we have extracted this method, it s clear that it depends entirely on the Rental. So let s move it to the class Rental and remove all of the arguments. So we end up in Customer with: result += rental.rentalline(); Notice that we can now remove the methods getdaysrented() and getmovie() from class Rental, as they are no longer needed. We can use the method charge() directly in the method rentalline() in class Rental. It doesn t matter that we end up calling this method twice (it s not worth losing simplicity unless we know that some code causes a performance problem). Step 11: Extract method headerline() We apply the same extraction to create headerline(), which takes one argument. So the code that used to be: String result = "Rentals: " + getname() + "\n"; changes to: String result = headerline(getname()); Step 12: Extract method footerline() We apply the same extraction to create footerline(), which takes two arguments. So the code that used to be: changes to: //add footer lines result += "Total = $" + totalamount + "\n"; result += "Frequent renter points ="+frequentrenterpoints + "\n"; return result + "---\n"; return result + footerline(totalamount, frequentrenterpoints); Step 13: Extract class Report Now we can create a new class Report and move methods headerline() and footerline() from Customer into it. So now inside statement, we replace:

by: String result = headerline(getname());... return result + footerline(totalamount, frequentrenterpoints); Report report = new Report(); String result = report.headerline(getname());... return Result+report.footerLine(totalAmount,frequentRenterPoints); Step 14: Extract part of rentalline() to Report The remaining part of the report is generated by rentalline() in class Rental. So we need to pass the Report to it. In class Customer, we end up with the call: result += rental.rentalline(report); and in class Rental, we end up with: public String rentalline(report report) { return report.rentalline(daysrented, movie.gettitle(), charge()); and, finally, Report contains the method: public String rentalline(int days, String title, double charge) { return days + " days of " + title +" $" + charge + "\n"; Step 15: Add Report parameter to statement() We want to have a different type of Report for generating HTML. So let s add a parameter of type Report to statement() in class Customer. That gives us: public String statement() { return statement(new Report()); public String statement(report report) {... Of course, we remove the declaration of the Report from inside the second statement() method. Step 16: Extract interface Report Before we can creates another type of report for HTML, we need to extract out an interface. Let s call that interface Report and the previous report class TextReport. That gives us: public interface Report { public String headerline(string name); public String rentalline(int days, String title, double charge); public String footerline(double totalcharge, int frequentrenterpoints)

and the new class: public class TextReport implements Report { public String headerline(string name) { return "Rentals: " + name + "\n"; public String rentalline(int days, String title, double charge) {... We need to alter the code in the statement() method (with no arguments) in class Customer, as changed in Step 15, so that a TextReport is created instead. Make sure that the tests still pass. Step 17: Extend with HTML So now we can define another class that implements Report to generate an HTML statement. It s time to uncomment the html test case method in class TestMovieRental, so that we can test it. Here s class HtmlReport: public class HtmlReport implements Report { public String headerline(string name) { return "<html><head><title>rentals: " + name + "</title> </head><body>\n"+ "<h1>rentals: " + name + "</h1>\n"+ "<table border=1><tr><th>days</th><th>title</th><th> Charge</th></tr>\n"; public String rentalline(int days, String title, double charge) { return "<tr><td align=right>"+days + "</td><td>" + title + "<td align=right>$" + charge + "</td></tr>\n"; public String footerline(double totalcharge, int frequentrenterpoints) { return "<tr><td></td><td><i>total</i><td align=right>$"+ totalcharge+"</td></tr>\n"+"</table><p>frequent renter points = " + frequentrenterpoints +"</p>\n</body></html>\n"; And then we can introduce a new method in class Customer to utilize this new class: public String htmlstatement() { return statement(new HtmlReport()); Make sure that the tests all pass. 5. Deliverables The completion criteria for this project are: 1- Complete all of the refactoring specified in steps 1 to 17. 2- Make sure that the resulting code has eliminated all of the smells that were identified in those steps. 3- Make sure that all unit tests pass. 4- Build a class diagram for the newly refactored software

So, you need to submit the following items: - Hardcopy of the refactored software (also email the instructor a softcopy). You need to properly document your software. - The class diagram of the system There will be a software demonstration session were all group members will be asked questions. So, all members of the group should be able to answer questions about the new program structure, and how it works. All students are reminded that acquiring solutions from other colleagues is a punishable academic offence. 6. Useful Resources and References Automated code refactoring CASE tools: Many software editors and IDEs have automated refactoring support. Here is a list of a few of these editors, or so-called refactoring browsers. IntelliJ IDEA for Java Eclipse's Java development kit (JDK) ( recommended for this project) NetBeans (for Java) Visual Studio 2008 (for.net) Further Reading Refactoring techniques in Fowler's refactoring Website http://www.refactoring.com/catalog/index.html Martin Fowler's book Refactoring: Improving the Design of Existing Code is the canonical reference. http://en.wikipedia.org/wiki/martin_fowler What Is Refactoring? (c2.com article) http://c2.com/cgi/wiki?whatisrefactoring Refactoring To Patterns Catalog (http://industriallogic.com/xp/refactoring/catalog.html ) Refactoring Java Code (http://www.methodsandtools.com/archive/archive.php?id=4 ) Wake, William C. (2003). Refactoring Workbook. Addison-Wesley. ISBN 0-321- 10929-5. Opdyke, William F.; Johnson, Ralph E. (September 1990). "Refactoring: An Aid in Designing Application Frameworks and Evolving Object-Oriented Systems". Proceedings of the Symposium on Object Oriented Programming Emphasizing Practical Applications (SOOPPA), ACM. Acknowledgement - The Java classes used in this project are based on an example by Martin Fowler: the refactoring differ. - The original version of this project was developed by Dr. Ian Warren, Auckland University. However, the text of this project has partly been modified to reflect the objectives of this course.