1st ci&t lightning talks: writing better code with object calisthenics

33
Writing better code with Object Calisthenics Lucas Arruda [email protected] github.com/larruda Adapted from Jeff Bay’s paper from The ThoughtWorks Anthology” and Guilherme Blanco’s presentation.

Upload: lucas-arruda

Post on 10-May-2015

664 views

Category:

Technology


0 download

DESCRIPTION

"We’ve all seen poorly written code that’s hard to understand, test, and maintain. Object-oriented programming promised to save us from our old procedural code, allowing us to write software incrementally, reusing as we go along. But sometimes it seems like we’re just chasing down the same old complex, coupled designs in Java that we had in C. Good object-oriented design is hard to learn. Transitioning from procedural development to object-oriented design requires a major shift in thinking that is more difficult than it seems. Many developers assume they’re doing a good job with OO design, when in reality they’re unconsciously stuck in old habits that are hard to break. It doesn’t help that many examples and best practices (even Sun’s code in the JDK) encourage poor OO design in the name of performance or simple weight of history." -- Jeff Bay Here are some key rules which are going to improve your OO designing skills and make you a better programmer. Some are harder to implement but will open your mind for new ways of coding. Happy coding! :)

TRANSCRIPT

Page 1: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

Writing better code withObject Calisthenics

Lucas [email protected]/larruda

Adapted from Jeff Bay’s paper from “The ThoughtWorks Anthology” and Guilherme Blanco’s presentation.

Page 2: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

Calis...what?!

Page 3: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics
Page 4: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

7 code qualitiescohesion

loose coupling

no redundancy

encapsulation

testability

readability

focus

Page 5: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

9 rules of thumb

Page 6: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

1. One level of indentation per method

class Board {

...

String board() {

StringBuffer buf = new StringBuffer();

for (int i = 0; i < 10; i++) {

for (int j = 0; j < 10; j++)

buf.append(data[i][j]);

buf.append(“\n”);

}

return buf.toString();

}

}

Page 7: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

1. One level of indentation per method

class Board { ... String Board() { StringBuffer buf = new StringBuffer(); collectRows(buf); return buf.toString(); } void collectRows(StringBuffer buf) { for (int i = 0; i < 10; i++) collectRow(buf, i); } void collectRow(StringBuffer buf, int row) { for (int i = 0; i < 10; i++) Buf.append(data[row][i]); buf.append(“\n”); }}

Page 8: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

1. One level of indentation per method

public function validateForm($filters='', $validators='', $options=''){ $data = $_POST; $input = new Zend_Filter_Input($filters, $validators, $data); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ($input->hasInvalid() || $input->hasMissing()) { foreach ($input->getMessages() as $field => $messageList) { foreach ($messageList as $message) { if (strpos($message, "empty")) { throw new Tss_FormException( "The field {$field} cannot be empty!", 3, 'javascript:history.back();' ); } else { throw new Tss_FormException( "{$message}", 3, 'javascript:history.back();' ); } } } } return $input;}

Page 9: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

1. One level of indentation per method

public function validateForm($filters='', $validators='', $options=''){ $data = $_POST;

$input = new Zend_Filter_Input($filters, $validators, $data); $input->setDefaultEscapeFilter(new Zend_Filter_StringTrim()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } foreach ($input->getMessages() as $field => $messageList) { foreach ($messageList as $message) { if (strpos($message, "empty")) { throw new Tss_FormException( "The field {$field} cannot be empty!", 3, 'javascript:history.back();' ); } else { throw new Tss_FormException( "{$message}", 3, 'javascript:history.back();' ); } } }}

Page 10: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

1. One level of indentation per method

public function validateForm($filters='', $validators='', ...{ $data = $_POST;

$input = new Zend_Filter_Input ($filters, $validators, $data); $input->setDefaultEscapeFilter( new Zend_Filter_StringTrim ()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } foreach ($input->getMessages() as $field => $messageList) { foreach ($messageList as $message) { $errorMessage = (strpos($message, "empty") === false) ? "The field {$field} cannot be empty!" : "{$message}";

throw new Tss_FormException ( $errorMessage, 3, 'javascript:history.back();' ); } }}

Page 11: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

1. One level of indentation per method

public function validateForm($filters='', $validators='', ...{ $data = $_POST;

$input = new Zend_Filter_Input ($filters, $validators, $data); $input->setDefaultEscapeFilter( new Zend_Filter_StringTrim ()); if ( ! ($input->hasInvalid() || $input->hasMissing())) { return $input; } foreach ($input->getMessages() as $field => $messageList) { $messageKey = key($message); $message = $message[$messageKey]; $errorMessage = (strpos($message, "empty") === false) ? "The field {$field} cannot be empty!" : "{$message}";

throw new Tss_FormException ( $errorMessage, 3, 'javascript:history.back();' ); }}

Page 12: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

2. Don’t use the ELSE keyword

if (status == DONE) {

doSomething();

} else {

}

Page 13: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

YOUMUST BE JOKING!!!

Page 14: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

2. Don’t use the ELSE keyword

class Board { ... String board(StringBuffer buf) { if (buf.length()) { return buf.toString(); } else { collectRows(buf); return buf.toString(); } } ...}

Page 15: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

2. Don’t use the ELSE keyword

class Board { ... String board(StringBuffer buf) { if (!buf.length()) { collectRows(buf); }

return buf.toString(); } ...}

Page 16: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

2. Don’t use the ELSE keyword

function login() {

$login = $this->input->post('email', true);

$password = $this->input->post('password', true);

$reference = $this->input->post('reference', true);

if ($this->clients_model->login($login, $password)) {

redirect($reference);

} else {

$this->session->set_flashdata(

'error', 'User or password invalid.'

);

$this->session->set_flashdata('reference', $reference);

redirect('clients');

}

}

Page 17: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

2. Don’t use the ELSE keyword

function login() {

$login = $this->input->post('email', true);

$password = $this->input->post('password', true);

$reference = $this->input->post('reference', true);

if (!$this->clients_model->login($login, $password)) {

$this->session->set_flashdata(

'error' , 'User or password invalid.'

);

$this->session->set_flashdata('reference', $reference);

$reference = 'clients';

}

redirect($reference);

}

Page 18: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

3. Wrap all primitives and Strings

Page 19: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

If the primitive type has a behavior it should be encapsulated

Page 20: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

3. Wrap all primitives and Strings

class UIComponent{ // ... public function repaint($animate = true) { // … } // ... $component->repaint(false);}

Page 21: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

3. Wrap all primitives and Strings

class UIComponent{ // ... public function repaint(Animate $animate) { // ... } }

class Animate{ public $animate; public function __construct($animate = true) { $this->animate = $animate; }}

// ...$component->repaint(new Animate(false));

Page 22: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

4. First class collections

Any class that contains a collection/array should not contain any other member

variables

Java Collections follow this rule

Page 23: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

4. First class collections

Transversable

Countable

Iterator

Filtering

Mapping

Combining

Page 24: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

5. One dot/arrow per line

Sign of misplaced responsibilities

The Law of Demeter“Only talk to your friends”

Page 25: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

5. One dot/arrow per line

class Board { ...

class Piece { ... String representation; } class Location { ... Piece current; } String boardRepresentation () { StringBuffer buf = new StringBuffer(); for (Location l: squares()) buf.append(l.current.representation.substring(0, 1)); return buf.toString(); }}

Page 26: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

5. One dot/arrow per line

class Board { ...

class Piece { ... private String representation; String character() { return representation.substring(0, 1); }

void addTo(StringBuffer buf) { buf.append(character()); } } class Location { ... private Piece current; void addTo(StringBuffer buf) { current.addTo(buf); } } String boardRepresentation() { StringBuffer buf = new StringBuffer(); for (Location l: squares()) l.addTo(buf); return buf.toString(); }}

Page 27: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

6. Don’t abbreviate

Are you writing the same name repeatedly?method being used multiple times

sign of code duplication

Is the method name too long?class with multiple responsibilities

missing additional classredundancy

Page 28: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

7. Keep all entities small

JavaNo class over 50 lines

No packages over 10 files

PHPNo class over 100 lines

No packages over 15 files

Packages, like classes, should be cohesive and have a purpose

Page 29: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

8. No classes with more than two/five instance variables

Improve cohesion

Split on more entities

Page 30: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

9. No getters/setters/properties

Improve encapsulation

“Tell, don’t ask”

Page 31: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

Q&Aciandt.com

http://www.cs.helsinki.fi/u/luontola/tdd-2009/ext/ObjectCalisthenics.pdf

http://www.slideshare.net/guilhermeblanco/object-calisthenics-applied-to-php

https://www.youtube.com/watch?v=ftBUHrxfOcc

Page 32: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

THANKS FOR

BEINGHERE!

Page 33: 1st CI&T Lightning Talks: Writing better code with Object Calisthenics

ciandt.com

[email protected]

@lunascarruda

google.com/+LucasArruda

fb.com/lucasnarruda

linkedin.com/in/larruda

github.com/larruda

coderbits.com/larruda

drupal.org/user/1009514