mirror of
https://github.com/jupeter/clean-code-php.git
synced 2025-10-03 09:21:56 +02:00
Merge pull request #81 from Slamdunk/patch-1
Convert method-chaining/fluent-interfaces to be an anti-pattern
This commit is contained in:
196
README.md
196
README.md
@@ -31,8 +31,8 @@
|
||||
* [Use getters and setters](#use-getters-and-setters)
|
||||
* [Make objects have private/protected members](#make-objects-have-privateprotected-members)
|
||||
5. [Classes](#classes)
|
||||
* [Use method chaining](#use-method-chaining)
|
||||
* [Prefer composition over inheritance](#prefer-composition-over-inheritance)
|
||||
* [Avoid fluent interfaces](#avoid-fluent-interfaces)
|
||||
6. [SOLID](#solid)
|
||||
* [Single Responsibility Principle (SRP)](#single-responsibility-principle-srp)
|
||||
* [Open/Closed Principle (OCP)](#openclosed-principle-ocp)
|
||||
@@ -1202,99 +1202,6 @@ echo 'Employee name: '.$employee->getName(); // Employee name: John Doe
|
||||
|
||||
## Classes
|
||||
|
||||
### Use method chaining
|
||||
|
||||
This pattern is very useful and commonly used in many libraries such
|
||||
as PHPUnit and Doctrine. It allows your code to be expressive, and less verbose.
|
||||
For that reason, use method chaining and take a look at how clean your code
|
||||
will be. In your class functions, simply use `return $this` at the end of every `set` function,
|
||||
and you can chain further class methods onto it.
|
||||
|
||||
**Bad:**
|
||||
|
||||
```php
|
||||
class Car
|
||||
{
|
||||
private $make = 'Honda';
|
||||
private $model = 'Accord';
|
||||
private $color = 'white';
|
||||
|
||||
public function setMake($make)
|
||||
{
|
||||
$this->make = $make;
|
||||
}
|
||||
|
||||
public function setModel($model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function setColor($color)
|
||||
{
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
public function dump()
|
||||
{
|
||||
var_dump($this->make, $this->model, $this->color);
|
||||
}
|
||||
}
|
||||
|
||||
$car = new Car();
|
||||
$car->setColor('pink');
|
||||
$car->setMake('Ford');
|
||||
$car->setModel('F-150');
|
||||
$car->dump();
|
||||
```
|
||||
|
||||
**Good:**
|
||||
|
||||
```php
|
||||
class Car
|
||||
{
|
||||
private $make = 'Honda';
|
||||
private $model = 'Accord';
|
||||
private $color = 'white';
|
||||
|
||||
public function setMake($make)
|
||||
{
|
||||
$this->make = $make;
|
||||
|
||||
// NOTE: Returning this for chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setModel($model)
|
||||
{
|
||||
$this->model = $model;
|
||||
|
||||
// NOTE: Returning this for chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setColor($color)
|
||||
{
|
||||
$this->color = $color;
|
||||
|
||||
// NOTE: Returning this for chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dump()
|
||||
{
|
||||
var_dump($this->make, $this->model, $this->color);
|
||||
}
|
||||
}
|
||||
|
||||
$car = (new Car())
|
||||
->setColor('pink')
|
||||
->setMake('Ford')
|
||||
->setModel('F-150')
|
||||
->dump();
|
||||
```
|
||||
|
||||
**[⬆ back to top](#table-of-contents)**
|
||||
|
||||
### Prefer composition over inheritance
|
||||
|
||||
As stated famously in [*Design Patterns*](https://en.wikipedia.org/wiki/Design_Patterns) by the Gang of Four,
|
||||
@@ -1391,6 +1298,107 @@ class Employee
|
||||
|
||||
**[⬆ back to top](#table-of-contents)**
|
||||
|
||||
### Avoid fluent interfaces
|
||||
A [Fluent interface](https://en.wikipedia.org/wiki/Fluent_interface) is an object
|
||||
oriented API that aims to improve the readability of the source code by using
|
||||
[Method chaining](https://en.wikipedia.org/wiki/Method_chaining).
|
||||
|
||||
While there can be some contexts, frequently builder objects, where this
|
||||
pattern reduces the verbosity of the code (for example the [PHPUnit Mock Builder](https://phpunit.de/manual/current/en/test-doubles.html)
|
||||
or the [Doctrine Query Builder](http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html)),
|
||||
more often it comes at some costs:
|
||||
|
||||
1. Breaks [Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_%28object-oriented_programming%29)
|
||||
2. Breaks [Decorators](https://en.wikipedia.org/wiki/Decorator_pattern)
|
||||
3. Is harder to [mock](https://en.wikipedia.org/wiki/Mock_object) in a test suite
|
||||
4. Makes diffs of commits harder to read
|
||||
|
||||
For more informations you can read the full [blog post](https://ocramius.github.io/blog/fluent-interfaces-are-evil/)
|
||||
on this topic written by [Marco Pivetta](https://github.com/Ocramius).
|
||||
|
||||
**Bad:**
|
||||
```php
|
||||
class Car
|
||||
{
|
||||
private $make = 'Honda';
|
||||
private $model = 'Accord';
|
||||
private $color = 'white';
|
||||
|
||||
public function setMake($make)
|
||||
{
|
||||
$this->make = $make;
|
||||
|
||||
// NOTE: Returning this for chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setModel($model)
|
||||
{
|
||||
$this->model = $model;
|
||||
|
||||
// NOTE: Returning this for chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setColor($color)
|
||||
{
|
||||
$this->color = $color;
|
||||
|
||||
// NOTE: Returning this for chaining
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dump()
|
||||
{
|
||||
var_dump($this->make, $this->model, $this->color);
|
||||
}
|
||||
}
|
||||
|
||||
$car = (new Car())
|
||||
->setColor('pink')
|
||||
->setMake('Ford')
|
||||
->setModel('F-150')
|
||||
->dump();
|
||||
```
|
||||
|
||||
**Good:**
|
||||
```php
|
||||
class Car
|
||||
{
|
||||
private $make = 'Honda';
|
||||
private $model = 'Accord';
|
||||
private $color = 'white';
|
||||
|
||||
public function setMake($make)
|
||||
{
|
||||
$this->make = $make;
|
||||
}
|
||||
|
||||
public function setModel($model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
public function setColor($color)
|
||||
{
|
||||
$this->color = $color;
|
||||
}
|
||||
|
||||
public function dump()
|
||||
{
|
||||
var_dump($this->make, $this->model, $this->color);
|
||||
}
|
||||
}
|
||||
|
||||
$car = new Car();
|
||||
$car->setColor('pink');
|
||||
$car->setMake('Ford');
|
||||
$car->setModel('F-150');
|
||||
$car->dump();
|
||||
```
|
||||
|
||||
**[⬆ back to top](#table-of-contents)**
|
||||
|
||||
## SOLID
|
||||
|
||||
**SOLID** is the mnemonic acronym introduced by Michael Feathers for the first five principles named by Robert Martin, which meant five basic principles of object-oriented programming and design.
|
||||
|
Reference in New Issue
Block a user