Improving code quality with Object Calisthenics

I’m always looking for new challenges where the main aim is to improve and become a better engineer. Today I’m going to illustrate what I’ve discovered some time ago, a new toolset called Object Calisthenics

Object Calisthenics has been introduced the first time by Jeff Bay in Thought Works Anthology published by The Pragmatic Programmers.

Why Object Calisthenics

The motivation comes directly from Jeff Bay as a way to implement and apply SOLID design principles, Design Patterns and improve code quality in our software projects.

Too often is happening that our software projects’ quality is going down and it’s really difficult to manage our codebase. The project become unmaintainable, bugs start bumping out and it’s difficult to understand what’s going on in the project. Even more the code in untestable (assumed that you have tests). I personally think and see that that’s also due to the wrong approach we have on Object Oriented Design. We design our software system like we were implementing procedural C code but wrapping it into PHP classes. And that’s not what OOP is all about.

You could easily recognize in your project, God classes, high coupling, too many dependencies, inheritance hell and many many more horrible things

It’s quite clear the way how Jeff Bay explains Object Calisthenics, he just wrote down a simple and ready to use list of rules, where if applied makes you more difficult to write bad code

1. Only one level of indentation per method

First rule, it’s not that crazy. Just try to keep your method as simple and understandable as you can

<?php
class InsertionSort {
public function sort(array $array) {
// 1 level
for ($i = 0; $i < count($array); $i++) {
// 2 level
$x = $array[$i];
for ($j = $i - 1; $j >= 0; $j--) {
// 3 level
if ($array[$j] > $x) {
$array[$j + 1] = $array[$j];
$array[$j] = $x;
}
}
}
return $array;
}
}

That’s a common example when you can easily spot multiple indentation levels into a method. That’s bad. Bottom line.

You can fix this most of the time, using the Extract Method pattern or in others, composing your objects in order to don’t aggregate all logic in one method. This is also somehow related with Single Responsibility Principle and High Cohesion which are valid as well for methods. If your method has multiple indentation levels, then maybe is not doing only one thing

<?php
class InsertionSort {
public function sort(array $array) {
for ($i = 0; $i < count($array); $i++) {
$array = $this->insert($array, $i);
}
return $array;
}
protected function insert(array $array, $i) {
$x = $array[$i];
for ($j = $i - 1; $j >= 0; $j--) {
$array = $this->swap($array, $x, $j);
}
return $array;
}
protected function swap(array $array, $x, $j) {
if ($array[$j] > $x) {
$array[$j + 1] = $array[$j];
$array[$j] = $x;
}
return $array;
}
}

2. Do not use “else” keyword

Many of you could already know this concept, but many others maybe not. Some others could be confused from this statement. Let’s have a look on this quick example

<?php
class HomeController
{
protected function indexAction()
{
if ($this->security->isGranted('ADMIN')) {
$view = 'admin/index.html.twig';
} else {
$view = 'home/access_denied.html.twig';
}
return $this->render($view);
}
}

We can easily remove the superfluous else statements and assuming which should be the default flow, in this case we assume by default we must have an access denied, which will be overridden by the subsequential if condition in case that’s not true

You can also use early returns, assuming always a default workflow

<?php
class HomeController
{
protected function indexAction()
{
if ($this->security->isGranted('ADMIN')) {
return $this->render('admin/index.html.twig');
}
return $this->render('home/access_denied.html.twig');
}
}

Anyway you always have a way to avoid this if-else nested statements which are not fun to read. In certain other more complex situations, you can implement practices like State or Strategy Design Patterns which will help you to handle state flow using objects composition.

3. Wrap primitive types and strings

Primitive types are indeed in this case to be PHP scalars, where we can’t ensure, given PHP to be a weakly typed programming language, that those are going to be what we expect. The thing is a bit different in PHP7 where the typing system is gradual but either we need to ensure domain validation for our primitive types. So then each time you need to ensure a value range and the type (in PHP5) you have to explicitly do it, like in this example

<?php
if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
throw new InvalidEmailException;
}
$emailDnsServiceProvider->verfiy($email);

This is the calisthenic way

<?php
class Email {
public function __construct(string $email) {
// validate email
}
}
$emailDnsServiceProvider->verify(new Email($email));

In this example we can introduce another common concept that can help us every time we have to wrap primitive types with Objects, the Value Object. In this example we’ve created a Value Object Email.

4. First class collections

A class that has an array collection in its properties should not have any other property, so in case of PHP a class like this

<?php
class Bucket {
protected $products = [];
// many other things...
}

Would be written like this using the calisthenic approach

<?php
class Bucket {
/** @var ProductCollection */
protected $products;
// many other things...
}
class ProductCollection implements Iterator { // ... }

The aim is to adhere to Single Responsibility Principle and High Cohesion thanks to ProductCollection class, making it responsible only for the collection and not for anything else. In this case if you need to add filtering, validation or other operations related to your product collection, you have the right place where to implement them. Not like before crunching all together into the Bucket class.

5. Only one object operator per line

This is the direct example of the Law of Demeter, only talk to your friends, where you should never use more than one object operator. The exception exists for Fluent Interface for example, which is another approach and doesn’t belong to this rule.

6. Don’t abbreviate

As we saw in the previous example we’ve a sorting algorithm which uses that syntax with the variables $i, $j, $x so that’s the point where we should not abbreviate, and also in methods like

<php
function delTmpFiles($p) { ... }
function sort(array $a) {
for ($i = 0; $i < count($a); $i++) { ... }
}

This is outrageous and should avoid it as much as you can as described in Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin) chapter 2: “Meaningful names”

<?php
function deleteTemporaryFiles($path) { ... }
function sort(array $array) {
for ($index = 0; $index < count($array); $index++) { ... }
}

Some extracts and rules from that chapter are for example: Use Intention-Revealing Names, Add Meaningful Context, Pick One Word per Concept, Use Pronounceable Names, Use Searchable Names.

7. Keep classes small

The original rule says we must have not more than 50 lines per class, which in PHP is really easy to reach even with a small entities, due to code styles and PHPDoc comments. But anyway, what we should do it’s to keep them as small as possible. The aim here is also to avoid the God Object anti-pattern

8. No classes with more than two instance variables

We don’t even need an example here, the rule is so extreme and simple,no more than two instance variable per class, this ensure you’re respecting the High Cohesion and the Single Responsibility Principle. If it contains more than two variables, then maybe your class it’s doing too much

9. No getter/setters

Also here is hard to grasp. But i totally agree with this, let’s say we have a class like this

<?php
class Car {
protected $speed;
protected $people;
public function getSpeed() { ... }
public function setSpeed($speed) { ... }
public function setPeople($people) { ... }
public function getPeople() { ... }
}

So then, this is something called Anemic Domain Model which is for me just a dumb data object which contains two fields and doesn’t contain any other logic operation related to what the object actually is. Here an example on how you could fix it

<?php
class Car {
protected $speed;
protected $people;

public function onBoardPerson() { ... }

public function dropOffPerson()
{
if ($this->people === 0) {
throw new CarEmptyException;
}
$this->people--;
}

public function accelerate($speed)
{
$this->speed += $speed;
}
    public function decelerate($speed) { ... }
}

That’s the purpose of No getters/setters rule, to enrich the entity with more valuable and meaningful logic and methods, not just using it as a dumb data bag

Conclusion

For those who want to try and apply those rules, you can also find online a lot of tools like this PHP Code sniffer https://github.com/object-calisthenics/phpcs-calisthenics-rules in order to get a validation against Calisthenics rules in your code base. I know many of those could sound extreme, but that’s a good way on how you could drastically improve the quality of your code and make it suck less.

Hope you got the basic concepts and a good inspiration from here to improve your code quality to the best!

Thanks for reading