120 likes | 267 Vues
In modern software development, rapid prototyping and extreme programming are essential for creating skeletal versions of applications. This document discusses the importance of refactoring—improving existing code design while revisiting it—by utilizing techniques such as consolidating redundant code and abstracting similar functionalities into superclasses. Examples include restructuring stack classes to enhance maintainability and efficiency without compromising functionality. A well-designed object-oriented system implements standard interfaces, leverages inheritance, and focuses on eliminating code redundancy through refactoring.
E N D
Computer Science 209 Software Development Refactoring
Design vs Redesign • Modern software is developed via rapid prototyping, also known as extreme programming (cf. Beck, Extreme Programming Explained Boston: Addison-Wesley, 2000). • Set up a skeletal version without full functionality, try it out, then refine and add detail • Rare to have a compete design before implementation
Redesign by Refactoring • Whenever you revisit code, try to improve its design by refactoring (cf. Fowler, Refactoring: Improving the Design of Existing Code, Boston: Addison-Wesley, 2000) • Examples • two or more redundant pieces of code can be placed in a single method definition • Similar data variables and methods in two or more different classes can be moved up to a common superclass
Refactoring the Stack Classes <<Interface>> TrueStack Abstract Collection LinkedStack ArrayStack LinkedList ArrayList Similar data variables: list, modCount Similar methods: add, size, iterator, equals, toString, push
Put ‘Em in AbstractStack <<Interface>> TrueStack Abstract Collection If these methods are written well, there should be no changes to them! Abstract Stack LinkedStack ArrayStack LinkedList ArrayList Similar data variables: list, modCount Similar methods: add, size, iterator, equals, toString, push
Put ‘Em in AbstractStack <<Interface>> TrueStack Abstract Collection Abstract Stack LinkedStack ArrayStack LinkedList ArrayList AbstractStack is declared Abstract, so it will never be instantiated
Put ‘Em in AbstractStack <<Interface>> TrueStack Abstract Collection Abstract Stack LinkedStack ArrayStack LinkedList ArrayList AbstractStack extends AbstractCollection and implements TrueStack The concrete stack classes just extend AbstractStack
Put ‘Em in AbstractStack <<Interface>> TrueStack Abstract Collection Abstract Stack LinkedStack ArrayStack LinkedList ArrayList The variables list and modCount are declared protected in AbstractStack, so they will be visible there and in subclasses but not anywhere else
Put ‘Em in AbstractStack <<Interface>> TrueStack Abstract Collection Abstract Stack LinkedStack ArrayStack LinkedList ArrayList The constructors and the methods pop and peek are still specialized in the stack implementations, so they remain where they were pop and peek are declared as abstract methods in AbstractStack
AbstractStack - Responsibilities abstract public AbstractStack<E> extends AbstractCollection<E> implements TrueStack<E>{ protected List<E> list; protected int modCount; public AbstractStack(){ // Defers instantiation of modCount = 0; // list to subclasses } abstract public E peek(); abstract public E pop(); // All other required methods (complete implementations) }
ArrayStack - Responsibilities public ArrayStack<E> extends AbstractStack<E>{ public ArrayStack(){ // Run the constructor of super(); // the superclass first list = new ArrayList<E>(); } public ArrayStack(Collection<E> col){ // Run my default this(); // constructor first this.addAll(col); } // Implementations of peek and pop go here }
A Well-Designed OO System • Uses standard interfaces • Implements standard interfaces • Leverages existing code via inheritance • Refactors code to eliminate redundancies