module 3. smells between classes course: refactoring

34
Module 3. Smells Between Classes Course: Refactoring

Upload: florence-wheeler

Post on 17-Jan-2016

217 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Module 3. Smells Between Classes Course: Refactoring

Module 3. Smells Between Classes

Course: Refactoring

Page 2: Module 3. Smells Between Classes Course: Refactoring

Overview: Smells Between Classes

Data

Inheritance

Responsibility

Accommodating Change

Library Classes

Page 3: Module 3. Smells Between Classes Course: Refactoring

Lesson: Data

Primitive Obsession

Data Class

Data Clump

Temporary Field

Page 4: Module 3. Smells Between Classes Course: Refactoring

Primitive Obsession

Symptoms Uses of the primitive or near-primitive types (int, float, String, etc.) Constants and enumerations representing small integers String constants representing field names

Causes Missing class Simulated types Simulated field accessors

What to Do Replace Data Value with Object

Replace Type Code with Class; Replace Type Code with Subclass; Replace Type Code with State/Strategy; Replace Conditional with Polymorphism

Replace Array with Object

Payoff Improves communication.

Page 5: Module 3. Smells Between Classes Course: Refactoring

Data Class

Symptoms

class consists only of public data members

depend on the mutability and representation of the class

Causes

realize that some data is part of an independent object

What to Do

Encapsulate Field

Remove Setting Methods

Encapsulate Collection

Look at each client of the object.

Payoff

Improves communication.

Page 6: Module 3. Smells Between Classes Course: Refactoring

Data Clump

Symptoms the same items frequently appear together in classes and parameter

lists. there are groups of fields and methods together within the class groups of field names start or end with similar substrings.

Causes The items are typically part of some other entity

What to Do Extract Class. Introduce Parameter Object Preserve Whole Object Move Method, etc

Payoff Improves communication. May expose duplication. Usually reduces

size.

Page 7: Module 3. Smells Between Classes Course: Refactoring

Temporary Field

Symptoms

A field is set only at certain times, and it is null (or unused) at other times.

Causes

an algorithm that passes around information through the fields

What to Do

Extract Class

Payoff

Improves communication and clarity.

Page 8: Module 3. Smells Between Classes Course: Refactoring

Exercise:

• Alternative Representations• Proper Names (Challenging)

Page 9: Module 3. Smells Between Classes Course: Refactoring

Lesson: Inheritance

Refused Bequest

Inappropriate Intimacy (Subclass Form)

Lazy Class

See also these other smells related to inheritance:

Simulated Inheritance (Switch Statement) Parallel Inheritance Hierarchies Combinatorial Explosion

Page 10: Module 3. Smells Between Classes Course: Refactoring

Refused Bequest

Symptoms honest refusal implicit refusal through a handle to the subclasses. Inheritance doesn't really make sense

Causes a class may inherit without really intending the class to be

substitutable a conscious decision to let subclasses deny use of some

features

What to Do you might decide to leave it as is. Replace Inheritance with Delegation. Extract Subclass, Push Down Field, and Push Down Method

Page 11: Module 3. Smells Between Classes Course: Refactoring

Inappropriate Intimacy (Subclass Form)

Symptoms

A class accesses internal (should-be-private) parts of its parent.

Causes

Parent and child classes be more coupled together

What to Do

Self Encapsulate Field.

Form Template Method.

Replace Inheritance with Delegation.

Payoff

Reduces duplication.

Often improves communication.

May reduce size.

Page 12: Module 3. Smells Between Classes Course: Refactoring

Lazy Class

Symptoms

A class isn't doing.

Causes

all responsibilities have been moved to other places

What to Do

Collapse Hierarchy.

Inline Class.

Payoff

Reduces size. Improves communication. Improves simplicity.

Page 13: Module 3. Smells Between Classes Course: Refactoring

Exercise:

Collection classes

Real application

Page 14: Module 3. Smells Between Classes Course: Refactoring

Lesson: Responsibility

Feature Envy

Inappropriate Intimacy (General Form)

Message Chains

Middle Man

Page 15: Module 3. Smells Between Classes Course: Refactoring

Feature Envy

Symptoms

A method seems to be focused on manipulating the data of other classes rather than its own.

Causes

This is very common among clients of current and former data classes, but you can see it for any class and its clients.

What to Do

Move Method

Extract Method

Page 16: Module 3. Smells Between Classes Course: Refactoring

Inappropriate Intimacy (General Form)

Symptoms One class accesses internal (should-be-private) parts of another

class

Causes The two classes probably became intertwined a little at a time. There may be a missing class that should mediate between them.

What to Do Move Method and Move Field Extract Class and Hide Delegate Change Bidirectional Reference to Unidirectional If a subclass is too coupled to its parent

Self Encapsulate Field.

Form Template Method.

Replace Inheritance with Delegation.

Page 17: Module 3. Smells Between Classes Course: Refactoring

Message Chains

Symptoms

You see calls of the form:a.b().c().d()

Causes

the problem is that this couples both the objects and the path to get to them.

What to Do

Extract Method and Move Method

Use Hide Delegate

Page 18: Module 3. Smells Between Classes Course: Refactoring

Middle Man

Symptoms object:f()

{ delegate.f(); }

Causes result from applying Hide Delegate to address

Message Chains

What to Do Remove Middle Man Replace Delegation with Inheritance.

Payoff Reduces size.

Page 19: Module 3. Smells Between Classes Course: Refactoring

Exercise:

Middle Man

Account Cart

Page 20: Module 3. Smells Between Classes Course: Refactoring

Exercise: Hide delegate

Page 21: Module 3. Smells Between Classes Course: Refactoring

Lesson: Accommodating Change

Divergent Change

Shotgun Surgery

Parallel Inheritance Hierarchies

Combinatorial Explosion

Page 22: Module 3. Smells Between Classes Course: Refactoring

Divergent Change

Symptoms

You find yourself changing the same class for different reasons.

Causes

The class picks up more responsibilities as it evolves

What to Do

Extract Class

Extract Superclass or Extract Subclass

Page 23: Module 3. Smells Between Classes Course: Refactoring

Shotgun Surgery

Symptoms

Simple change requires to change several classes.

Causes

One responsibility is split among several classes.

Elimination Divergent Change.

What to Do

Extract Class

Move Field and Move Method.

Page 24: Module 3. Smells Between Classes Course: Refactoring

Parallel Inheritance Hierarchies

Symptoms

required subclass in another hierarchy.

subclasses have the same prefix

a special case of Shotgun Surgery

Causes

The hierarchies probably grew in parallel, a class and its pair being needed at the same time.

What to Do

Move Field and Move Method

Payoff

Reduces duplication. May improve communication. May reduce size.

Page 25: Module 3. Smells Between Classes Course: Refactoring

Combinatorial Explosion

Symptoms

you have to introduce multiple classes at various points of the hierarchy.

you notice that each layer of the hierarchy uses a common set of words

Causes

independent decisions instead get implemented via a hierarchy.

What to Do

Replace Inheritance with Delegation

Tease Apart Inheritance

Page 26: Module 3. Smells Between Classes Course: Refactoring

Exercise:

Divergent Changes (csv writer)

Shotgun Surgery

Documents

Page 27: Module 3. Smells Between Classes Course: Refactoring

Exercise: Shotgun Surgery

In code you have access to, find examples of this problem. Some frequent candidates:

Configuration information. Logging. Persistence. Sometimes it takes two calls on an object

to get something common done, and this two-step process is used in several places.

Page 28: Module 3. Smells Between Classes Course: Refactoring

Lesson: Library Classes

Incomplete Library Class

Page 29: Module 3. Smells Between Classes Course: Refactoring

Incomplete Library Class

Symptoms

library has no some features

Causes

the author of the library class didn't anticipate your need

What to Do

contact owner

Introduce Foreign Method

Introduce Local Extension

introduce a layer covering the library

Page 30: Module 3. Smells Between Classes Course: Refactoring

Exercise:

Page 31: Module 3. Smells Between Classes Course: Refactoring

Exercise:

Redraw this as a UML package diagram showing dependencies.

Explain how the bulk of your code does or does not depend on the library code in each of these situations.

What effects does this layering have in terms of:

Conceptual integrity?

Portability?

Performance?

Testing?

Page 32: Module 3. Smells Between Classes Course: Refactoring

Exercise:

Page 33: Module 3. Smells Between Classes Course: Refactoring

Review

Data

Inheritance

Responsibility

Accommodating Change

Library Classes

Page 34: Module 3. Smells Between Classes Course: Refactoring

Gen-A-Refactoring

(—) in combinations that don't make sense,

(+) in those that are in Fowler's Refactoring catalog

(*) in those that make sense but aren't in the catalog.