9 steps to better OO code
Learn how to make our code more:
"Calisthenics are exercises consisting of a variety of gross motor movements; often rhythmical and generally without equipment or apparatus."
Wikipedia
class Board {
public function __construct(array $data) {
$buf = '';
// 0
for ($i=0; $i<10; $i++) {
// 1
for ($j=0; $j<10; $j++) {
// 2
$buf .= $data[$i][$j]
}
}
return $buf;
}
}
class Board {
public function __construct(array $data) {
$buf = '';
collectRows($buf);
return $buf;
}
private function collectRows($buf) {
for ($i=0; $i<10; $i++) {
collectRow($buf, $i);
}
}
private function collectRow($buf, $row) {
for ($i=0; $i<10; $i++) {
$buf .= $data[$row][$i];
}
}
}
if (...) {
...
} elseif (...) {
...
} elseif (...) {
...
} elseif (...) {
...
} elseif (...) {
...
} elseif (...) {
...
} else {
...
}
public function login($username, $password) {
if ($this->userRepository->isValid($username, $password)) {
redirect("homepage");
} else {
addFlash("error", "Bad credentials");
redirect("login");
}
}
public function login($username, $password) {
if ($this->userRepository->isValid($username, $password)) {
return redirect("homepage");
}
addFlash("error", "Bad credentials");
return redirect("login");
}
public function checkDate(int $year, int $month, int $day)
{
...
}
// 10th of December or 12th of October?
$validator->checkDate(2016, 10, 12);
public function checkDate(Year $year,
Month $month,
Day $day)
{
...
}
$validator->checkDate(new Year(2016),
new Month(10),
new Day(12)
);
$validator->addFilter(new EmailFilter())
->addFilter(new NotEmptyFilter());
$token = $this->getService(Service::AUTH)
->authUser($user, $password)
->getResult()
->getToken();
// 1. What if non object is returned?
// 2. How about exceptions handling?
class Location {
/** @var Piece */
public current;
}
class Piece {
/** @var string */
public representation;
}
class Board {
public function boardRepresentation(array $board) {
$buf = '';
foreach ($board as $field) {
$buf .= substring($field->current->representation, 0, 1);
}
return $buf;
}
}
class Location {
/** @var Piece */
private $current;
public function addTo($buf) {
return $this->current->addTo($buf);
}
}
class Piece {
/** @var string */
private $representation;
public function character() {
return substring(representation, 0, 1);
}
public function addTo($buf) {
return $buf . $this->character();
}
}
class Board {
public function boardRepresentation(array $board) {
$buf = '';
/** @var Location $field */
foreach ($board as $field) {
$field->addTo($buf);
}
return $buf;
}
}
class CartService {
private $userService;
private $logger;
private $cart;
private $translationService;
private $entityManager;
private $authService;
// ...
}
class Game {
/** @var int */
private score;
public function setScore(score) {
$this->score = score;
}
public function getScore() {
return $this->score;
}
}
// Usage
$game->setScore($game->getScore() + ENEMY_DESTROYED_SCORE);
class Game {
/** @var int */
private score;
public function addScore($delta) {
$this->score += $delta;
}
}
// Usage
$game->addScore(ENEMY_DESTROYED_SCORE);