1st CI&T Lightning Talks: Writing better code with Object Calisthenics
-
Upload
lucas-arruda -
Category
Technology
-
view
664 -
download
0
description
Transcript of 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.
Calis...what?!
7 code qualitiescohesion
loose coupling
no redundancy
encapsulation
testability
readability
focus
9 rules of thumb
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();
}
}
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”); }}
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;}
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();' ); } } }}
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();' ); } }}
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();' ); }}
2. Don’t use the ELSE keyword
if (status == DONE) {
doSomething();
} else {
…
}
YOUMUST BE JOKING!!!
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(); } } ...}
2. Don’t use the ELSE keyword
class Board { ... String board(StringBuffer buf) { if (!buf.length()) { collectRows(buf); }
return buf.toString(); } ...}
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');
}
}
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);
}
3. Wrap all primitives and Strings
If the primitive type has a behavior it should be encapsulated
3. Wrap all primitives and Strings
class UIComponent{ // ... public function repaint($animate = true) { // … } // ... $component->repaint(false);}
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));
4. First class collections
Any class that contains a collection/array should not contain any other member
variables
Java Collections follow this rule
4. First class collections
Transversable
Countable
Iterator
Filtering
Mapping
Combining
5. One dot/arrow per line
Sign of misplaced responsibilities
The Law of Demeter“Only talk to your friends”
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(); }}
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(); }}
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
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
8. No classes with more than two/five instance variables
Improve cohesion
Split on more entities
9. No getters/setters/properties
Improve encapsulation
“Tell, don’t ask”
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
THANKS FOR
BEINGHERE!
ciandt.com
@lunascarruda
google.com/+LucasArruda
fb.com/lucasnarruda
linkedin.com/in/larruda
github.com/larruda
coderbits.com/larruda
drupal.org/user/1009514