0% found this document useful (0 votes)
270 views98 pages

T9 - Refactoring, Design Patterns & Anti-Patterns

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
270 views98 pages

T9 - Refactoring, Design Patterns & Anti-Patterns

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 98

T09 – Refactoring, Design

Patterns & Antipatterns

Design & Tests 1


In this lesson

22
Contents

• Previously on DP1…
• Refactoring
– “Movie rental” case study
– Refactoring steps
• Extract Method
• Move Method
• Remove OneToOne association
• Applying a design pattern
– Other Design Patterns of interest

• Anti-patterns & Bad Smells

3
Previously on DP1…

4
Our goal is to design applications

• Organized into different modules


• Each module should hide details on how it is implemented to others so that
changes in the module do not affect others
• Modules should have a high cohesion (single responsibility)
• Modules should have a low coupling (should depend on just a few other
modules)
• The architecture, structure and code is as simple as possible (Keep It Simple,
Stupid, KISS)
• There is no code duplication but reuse (Don’t Repeat Yourself, DRY)

5
To help us on designing applications we (re-)use

ARCHITECTURAL DESIGN PATTERNS SOFTWARE


STYLES FRAMEWORKS

6
We have mostly focused on architectural design

• We split our architecture in three layers: resources, business logic and


presentation
• We use the MVC, the front controller, and the template view pattern to
implement the presentation layer
• We use the domain model and the service layer pattern to implement the
business logic layer
• We use the meta-data mapper pattern and repositories to implement the
resources layer.

7
Now, we want to focus on the detailed design:
How should I organize my code?
In which method/class should I put my code?

8
The technical debt

9
Why is this important?
Why should I care about how the code is organized?
If it works… Isn’t it what matters?
The importance of a good code base

When adding a new feature you need to know how it fits in the
application and understand the existing code.

But it’s very easy for software to get hard to understand

11
Cruft: The difference between the current code and how it would ideally be

12
https://www.martinfowler.com/bliki/TechnicalDebt.html
The cruft quadrant

Reckless Prudent
Deliberate “We don’t have time to “We must release now and
design” accept the consequences
(later)”
Inadvertent “What is a controller?” “Now we know how we
should have done it”

13
Technical debt

Concept that represents the cost of the additional work caused


for choosing a quick solution now instead of an approach that
would have taken more time

14
Technical debt
We should pay our technical debt while we evolve the code so
that it doesn’t get too high
Three questions now

How can I pay my technical debt?


How can I identify what should I change?
How can I properly design from the beginning?
How can I pay my technical debt?

Refactoring

18
How can we remove the cruft? REFACTORING!

• Refactoring is about improving the


design of existing code.

• It is the process of changing a


software system in such a way that it
does not alter the external behavior
of the code, yet improves its internal
structure.

• Refactoring you can even take a bad


design and rework it into a good one.

19
“Movie Rental” Case Study

• To develop a statement view for


each customer, showing:
– customer name
– All his rental records including:
• Movie title
• Amount owed for the rent
depending on the days rented and
the movie type that infers on the
price
– Total amount owed for the
customer
– Frequent renter points earned
with all rental records

20
GET /customer/1/statement/
Our first solution

https://github.com/gii-is-DP1/react-petclinic/commit/b4026e98c21550f30cb8ed918311a76bb34d9c1f
22
23
New Feature!!!

• To develop a statement view for


each customer, showing:
– customer name
– All his rental records including:
• Movie title
• Amount owed for the rent
depending on the days rented and
the movie type that infers on the
price
– Total amount owed for the
customer
– Frequent renter points earned
with all rental records

• The users want to make changes to the way they classify movies, but they
haven't yet decided on the change they are going to make. These changes will
affect both the way renters are charged for movies and the way that frequent
renter points are calculated.
24
The program may not be
broken, but it does hurt.
It is making your life
more difficult because
you find it hard to make
the changes your users
want

25
When you find you have to add a feature to a program, and the
program's code is not structured in a convenient way to add the
feature, first refactor the program to make it easy to add the
feature, then add the feature.
In other words: Remove cruft!!

26
But before, the first step is adding tests

https://github.com/gii-is-DP1/react-
petclinic/commit/76b67f758fc497c2166
43587f8f47d441f65c065 27
What could we do first?

28
Extract Method
Code fragment that can be grouped
Converts the fragment in a method with a clear name

void printOwing() {
printBanner();

//print details
System.out.println ("name: " + _name);
System.out.println ("amount " + getOutstanding());
}

void printOwing() {
printBanner();
printDetails(getOutstanding());
}

void printDetails (double outstanding) {


System.out.println ("name: " + _name);
System.out.println ("amount " + outstanding);
}
Step 1: Extract method amount For

https://github.com/gii-is-DP1/react-
petclinic/commit/75643bfaa18db1d8a6358ecea583
a3cdffbbb0d6?diff=split
30
Refactoring changes the programs in small steps. If you make a
mistake, it is easy to find the bug.
What now?
Step 2: Rename variables in amountFor

https://github.com/gii-is-DP1/react-petclinic/commit/328d75357fc1d8664fab95a2b5a47dfbbf44779d 33
Is refactoring worth the effort?

Absolutely. Good code should communicate what it is doing


clearly, and variable names are a key to clear code. Never be
afraid to change the names of things to improve clarity.

34
What next?

35
Move Method

A method is used or will be used more by other classes than its own class

Create a new method with the code of the original method in the class that uses the
code more. Remove the original method or just delegate in the new one

Class1 Class1 Class1


+ unMetodo() + unMetodo()

or
Class2 Class2 Class2
+ unMetodo() + unMetodo()
Step 3: Move method amountFor to Rental as getCharge

https://github.com/gii-is-DP1/react- 37
petclinic/commit/24f183614357ca57637ace2e26c313fd14c712f0
State of classes after moving the method

38
Step 4: Removing OneToOne association (1)

https://github.com/gii-is-DP1/react-
petclinic/commit/f18ac9b46d239ff268b5c7fd40bb8e
2ba9f9c453 39
Step 4: Removing OneToOne association (2)

40
Step 4: Removing OneToOne association (3)

41
State of classes after moving the method

42
What else?

43
Step 5: Extract method getFrequentRenterPoints to Rental

44
https://github.com/gii-is-DP1/react-petclinic/commit/89107ee0d974b981ef602852150224eddb7362b0
State of classes

45
What else?

46
Step 6: Extract getTotalCharge and getTotalFrequentRenterPoints to
Customer (1)

https://github.com/gii-is-DP1/react-petclinic/commit/20b22f9eb013b2e9ce7f908141bbc181ce7bb485
47
Step 6: Extract getTotalCharge and getTotalFrequentRenterPoints to
Customer (and 2)

48
Wait a minute. What about the performance of this?

(1) You do less in each loop


(2) The general criteria is to refactor so that the code is easy to
understand, and then, you can optimize if necessary

49
State of classes

50
What else?

51
We are moving what changes (the type of movie) to the class
that owns it (Movie)

52
Step 7: Move getCharge to Movie

https://github.com/gii-is-DP1/react-
petclinic/commit/5233a5220ca9398f68f888d859892
ac8499bff5c 53
Step 8: Move getFrequentRenterPoints to Movie

https://github.com/gii-is-DP1/react-petclinic/commit/2ae9fc60109bf232e13aa40abf6692410557f24d
54
State of classes

55
What else? Let’s look at the class Movie
We have several types of movie that have different ways of answering the same
question. This sounds like a job for subclasses. We can have three subclasses
of movie, each of which can have its own version of charge

56
Could this be a solution?

57
The solution is to use the state/strategy pattern

58
Step 9: Replace if-else with state/strategy for getCharge (1)

https://github.com/gii-is-DP1/react- 59
petclinic/commit/769a4b7d93a68de4e43a7027fb1470db3f5574fd
Step 9: Replace if-else with state/strategy for getCharge (2)

60
Step 9: Replace if-else with state/strategy for getCharged (and 3)

61
Step 10: Replace if-else with state/strategy for getFrequentRenterPoints (1)

https://github.com/gii-is-DP1/react-
petclinic/commit/f24ecf4a8827ccb9fefa0d182da0d0
41a63e2a4b
62
Step 10: Replace if-else with state/strategy for getFrequentRenterPoints (2)

63
The final result

64
The power of Design Patterns

• Design Patterns give you a shared


vocabulary with other developers.
– Patterns allow you to say more with
less

• Design patterns also elevate your


thinking about software by letting you
think at the pattern level, not the nitty-
gritty object/ or source code level.

• Design patterns are tools for Design


Toolbox, that allow you to create
flexible designs that are
maintainable and can cope with
change
65
Other design patterns of interest

66
Other design patterns of interest

• To create the game board, and or the Cards, and or the card
initial delivery .
• https://refactoring.guru/es/design-patterns/builder

• When you have modifying cards that infers in other cards.


• https://refactoring.guru/es/design-patterns/decorator

• When you have different elements that perform the same


action.
• https://refactoring.guru/es/design-patterns/command
67
Are there more refactoring operations?

68
Catalog: Moving features between objects

Extract Class
When one class does the work of two,
Create a class and move relevant fields and methods

Person PhoneNumber
Person
- name 1 - prefix
- prefix - name
- number
- number
+ getPhoneNumber() + getPhoneNumber()
+ getPhoneNumber()
Catalog: Organizing data

Replace Type Code with Subclasses


A coded type directly affects program behaviour
Replace the type with subclasses

Employee Employee
- ENGINEER: int
- SALESMAN: int
- type: int

Engineer Salesman
Catalog: Simplifying method calls

Introduce Parameter Object


A group of parameters usually go together
Replace the group of parameters with an object

Customer Customer

+ amountInvoicedIn(Date start, Date end) + amountInvoicedIn(DateRange range)


+ amountReceivedIn(Date start, Date end) + amountReceivedIn(DateRange range)

DateRange
- start : Date
- end : Date
And many more…
Check: https://refactoring.com/catalog/ and
https://refactoring.guru/refactoring/techniques

72
How can I identify what I should change?

Anti-patterns and Bad smells

73
Software antipatterns

• An AntiPattern describes a commonly occurring solution to a problem/cause


that generates decidedly negative consequences.

• AntiPatterns, like their design pattern counterparts, define a vocabulary for


the common defective designs and implementations within organizations.

• AntiPatterns present actions for reversing these underlying problems


(recommended refactorings) and improve the developing of applications.

74
What is Clean code?

75
The first source of cruft/dirt is… naming

Use intention-revealing names:

What is the purpose of this code?

We can go a bit further, and refactor this code creating a class for the cells of the game board:

76
https://www.commitstrip.com/en/2016/09/01/keep-it-simple-stupid/ 77
Another source of cruft/dirt is … Magic Numbers

• Magic Number: Unique literal value with unexplained meaning,


that usually have multiple occurrences along the codebase, which
could (preferably) be replaced with named constants defined in a
single point of the codebase.

78
Bad smells
Duplicated code / Copy&Paste programming
Bad smell: Same code structure in more than one place
Common solution: Move duplicated code into a new method, a new class, or just put
it in one class and call it from the other

This is a real-world
Example taken from
a student group
project (DP1 2020)

79
Bad smells

Comments
Bad smell: comments that are stating the obvious instead of providing value
// Add one to i.
i+=1;

// Lock to protect against concurrent access.


SpinLock mutex;

// This method swaps the panels.


void swapPanels(panel1, panel2)

“Don’t comment bad code—rewrite it.”


—Brian W. Kernighan and P. J. Plaughe

80
More about comments

• Comments should provide higher


// Good Comment:
level information // Scan the array to see if the symbol exists
// Bad comment:
// Loop through every array index, get the
// third value of the list in the content to Dead variable
// determine if it has the symbol we are looking
// for. Set the result to the symbol if we
// find it.

• Never comment source code. Either


the code is needed (and used/invoked
somewhere, otherwise it is dead code)
or not. Git is there for you if you need it
in the future.

81
https://geekandpoke.typepad.com/geekandpoke/2008/07/good-comments.html 82
Antipattern: Boat Anchor

• A Boat Anchor is a piece of software that serves no useful purpose on


the current project.

• The consequences for software developers are that significant effort


is required for making the product work.

• After a significant investment of time and resources, the technical


staff realizes that the code/product is useless (or is unable to
modify/update it) in the current context, and abandons it for
another technical approach (or is maintained as a hidden legacy).

• Usually, boat anchors are dead code in your code base

83
The worst type of Anchor: the required one

84
https://geekandpoke.typepad.com/geekandpoke/2009/07/
Bad smells
Long method
Bad smell: methods that are too long (more than one page rule)
Common solution: extract chunks of code from the long method into new methods

Continue… ➔

Continue… ➔
This is a real-world example taken from a student group project (DP1 2020) 85
Bad smells
Primitive obsession
Bad smell: overuse of primitive types (string, int…) instead of using value objects
(Money, Address…)
Common solution: Create value objects to ease the handling and validation of these
types
public Collection<Vuelo> horarioSemanalConFecha(int id, int dia,
int mes, int anyo){
...
}

public Collection<Vuelo> horarioSemanalConFecha(


AuxiliarVuelo auxiliar,
Date fecha){
...
}

This is a real-world example taken from a student group project (DP1 2020) 86
Bad smells

Message chains
Bad smell: a client asks one object for another object, which the client then asks for
yet another object… You find this as a long line of getThis methods

Common solution: extract part of the code of the method and move it to other object
in the chain

Money amount = sell.getPayment().getPayAmount():


// Class coupled with sell and payment

Money amount = sell.getAmountInPayment();


// Class coupled only with sell

87
Wrapping up

88
Wrapping up

• What is cruft and technical debt?


• What is refactoring?
• Applying refactoring to “Movie Rental” case study
– Extract Method
– Move Method
– Applying Strategy Design Pattern
• Object-Oriented Design Patterns of interest in your projects
– Builder
– Command
– Decorator
• Anti-patterns & Bad smells
– Copy & paste programming and comments stating the obvious
– Magic Numbers
– Primitive obsession
– Long method/God class
– Message chain

89
A+ Criteria published

90
Sneak peak on some A+ criteria: an easy one
@StatePattern
“Specification of the application of public class StatePatternApplication {
the design patterns in the project @StatePattern.State
interface SpeedLevel {
using the jpatterns library” void rotate(FanWallControl fanWallControl);}

@StatePattern.Context
static class FanWallControl {
<dependency> private SpeedLevel current;
<groupId>org.jpatterns</groupId>
<artifactId>jpatterns</artifactId> @StatePattern.ConcreteState
<version>0.0.1</version> static class Off implements SpeedLevel {
</dependency> public void rotate(FanWallControl fanWallControl) {
fanWallControl.set_state(new SpeedLevel1());
}
}
@StatePattern.ConcreteState
You have several examples available at static class SpeedLevel1 implements SpeedLevel {
the japatterns branch of the template public void rotate(FanWallControl fanWallControl)
fanWallControl.set_state(new SpeedLevel2());
{

repository. Available at: }


}

@StatePattern.ConcreteState
https://github.com/gii-is-DP1/spring- static class SpeedLevel2 implements SpeedLevel {
public void rotate(FanWallControl fanWallControl) {
petclinic/tree/jpatterns/src/main/java/org/s fanWallControl.set_state(new SpeedLevel3());
pringframework/samples/petclinic/patterns }
}
@StatePattern.ConcreteState
static class SpeedLevel3 implements SpeedLevel {
public void rotate(FanWallControl fanWallControl) {
fanWallControl.set_state(new Off()); 91
} } }
Reminders

92
Sprint 2 Deadline

12 November 2024 08:30:00

93
References

94
Bibliography

Martin Fowler, David Rice. Patterns of Enterprise


Application Architecture. Addison-Wesley Professional. 3rd
edition. 2003 (Chapters 1, 4 & 14)

Design Patterns by Refactoring Guru


Available at: https://refactoring.guru/design-patterns/

95
Bibliography

Rober C. Martin. Clean Code: A Handbook of Agile Software


Craftsmanship. Prentice Hall. 2009 (Chapters 1 & 2)

Eric Freeman & Elisabeth Jonson. Head First: Design


Patterns. O’Reilly. 2014. (Chapters 1, 3, 6, 10 & Appendix A)

96
Bibliography

Martin Fowler. Refactoring: Improving the design of existing


code. Pearson Education. 2018

97
Disclaimer and Terms of Use

All material displayed on this presentation is for teaching and personal use only.

Many of the images that have been used in the presentation are Royalty Free images
taken from http://www.everystockphoto.com/. Other images have been sourced directly
from the Public domain, from where in most cases it is unclear whether copyright has
been explicitly claimed. Our intention is not to infringe any artist’s copyright, whether
written or visual. We do not claim ownership of any image that has been freely obtained
from the public domain. In the event that we have freely obtained an image or quotation
that has been placed in the public domain and in doing so have inadvertently used a
copyrighted image without the copyright holder’s express permission we ask that the
copyright holder writes to us directly, upon which we will contact the copyright holder to
request full written permission to use the quote or images.

You might also like