Object calisthenics
9 Steps to Better OO Code
Warsaw, 06.07.2016
the purpose of this meetinG
Learn how to make our code more:
-
Readable,
-
Reusable,
-
Testable,
- Maintainable.
Calisthenics
Cal • is • then • ics - /ˌkaləsˈTHeniks/
"Calisthenics are exercises consisting of a variety of gross motor movements; often rhythmical and generally without equipment or apparatus."
Wikipedia
object calisthenics
Jeff Bay, "ThoughtWorks Anthology"
but Why bother?
"Code is read more than it is written"
"You need to write code that minimizes the time it would take someone else to understand it - even if that someone else is you."
"Art of Readable Code"
Dustin Boswell, Trevor Foucher
Rule #1
Only one level of indentation per method
class Board { public String board() { StringBuilder buf = new StringBuilder(); // 0 for (int i = 0; i < 10; i++) { // 1 for (int j = 0; j < 10; j++) { // 2 buf.append(data[i][j]); } buf.append("\n"); } return buf.toString(); } }
class Board { public String board() { StringBuilder buf = new StringBuilder(); collectRows(buf); return buf.toString(); } private void collectRows(StringBuilder buf) { for (int i = 0; i < 10; i++) { collectRow(buf, i); } } private void collectRow(StringBuilder buf, int row) { for (int i = 0; i < 10; i++) { buf.append(data[row][i]); } buf.append("\n"); } }
Benefits of rule #1
- Single Responsibility Principle,
- Readability,
- Maintainability,
- Testability,
- Reusability,
- Better naming.
Rule #2
Do not use else keyword
public void login(String username, String password) { if (userRepository.isValid(username, password)) { redirect("homepage"); } else { addFlash("error", "Bad credentials"); redirect("login"); } }
public void login(String username, String password) { if (userRepository.isValid(username, password)) { return redirect("homepage"); } addFlash("error", "Bad credentials"); return redirect("login"); }
Benefits of rule #2
- Readability,
- Clean code,
- Avoids code duplication.
Rule #3
Wrap primitive types if it has behaviour
Benefits of rule #3
- Encapsulation,
- Type hinting (PHP),
- Attracts similar behaviour.
Rule #4
Only one dot per line
class Location { public Piece current; } class Piece { public String representation; } class Board { public String boardRepresentation() { StringBuilder buf = new StringBuilder(); for (Location loc : squares()) { buf.append(loc.current.representation.substring(0, 1)); } return buf.toString(); } }
class Location { private Piece current; public void addTo(StringBuilder buf) { current.addTo(buf); } } class Piece { private String representation; public String character() { return representation.substring(0, 1); } public void addTo(StringBuilder buf) { buf.append(character()); } } class Board { public String boardRepresentation() { StringBuilder buf = new StringBuilder(); for (Location location : squares()) { location.addTo(buf); } return buf.toString(); } }
benefits of rule #4
- Readability,
- Encapsulation,
- Easier to debug,
- Demeter's law,
- Open/Closed Principle.
Rule #5
Do not abbreviate
Why abbreviate?
Typing the same word over and over again?
Perhaps your method is used too heavily and you are missing opportunities to remove duplication.
Are method names getting long?
Might be a sign of a misplaced responsibility or a missing class.
Benefits of rule #5
- Clear intentions,
- Indicate underlying problems.
Rule #6
Keep your entities small
Benefits of rule #6
- Single Responsibility Principle,
- Objective methods,
- Slimmer namespaces.
Rule #7
No more than 2 instances variable per class
benefits of rule #7
- High cohesion,
- Encapsulation,
- Fewer dependencies,
- Easier to test.
Rule #8
First class collections
Rule #9
Do not use setters/getters
private int score; public void setScore(int score) { this.score = score; } public int getScore() { return score; } // Usage game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);
public void addScore(int delta) { score += delta; } // Usage game.addScore(ENEMY_DESTROYED_SCORE);
benefits of rule #9
- Open/Closed Principle
Catch 'em all!
- Only one level of indentation per method,
- Do not use else keyword,
- Wrap primitive types if it has behavior,
- Only one dot per line,
- Don’t abbreviate,
- Keep your entities small,
- No more than two instance variable per class,
- First Class Collections,
- Do not use accessors
- ???
- PROFIT!
Homework
Create new project up to 1000 lines long,
and apply presented rules as strictly as possible.
Final thoughts
These are not best practices or even
guidelines for production code.
Use with caution!
Thank you!
Object Calisthenics
By Paweł Lewtak
Object Calisthenics
9 Steps To Better OOP Code
- 438