Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 19 | class DevicesBinding extends AbstractBinding |
||
| 20 | { |
||
| 21 | use DevicesBindingTrait, LogsBindingTrait; |
||
| 22 | |||
| 23 | const INCLUDE_LOGS = 'logs'; |
||
| 24 | |||
| 25 | /** |
||
| 26 | * Construct a device binding from a database connector |
||
| 27 | * |
||
| 28 | * @param PDO $database |
||
| 29 | * |
||
| 30 | * @throws BindingException If `$database` is not an instance of PDO |
||
| 31 | */ |
||
| 32 | public function __construct(PDO $database) |
||
| 33 | { |
||
| 34 | parent::__construct($database, 'devices', Device::class); |
||
| 35 | } |
||
| 36 | |||
| 37 | /** |
||
| 38 | * Retrieve all devices |
||
| 39 | * |
||
| 40 | * By default, devices include the list of logs sub-object |
||
| 41 | * |
||
| 42 | * @param array $params |
||
| 43 | * |
||
| 44 | * @return Device[] |
||
| 45 | */ |
||
| 46 | public function all($params = [self::SCOPE_INCLUDE => [self::INCLUDE_LOGS]]) |
||
| 47 | { |
||
| 48 | return parent::all($params); |
||
| 49 | } |
||
| 50 | |||
| 51 | /** |
||
| 52 | * Configure ordering of list of bound objects |
||
| 53 | * |
||
| 54 | * Devices are ordered alphabetically by manufacturer, model, name and then creation date (most recent first). |
||
| 55 | * |
||
| 56 | * @see AbstractBinding::listOrder() |
||
| 57 | * |
||
| 58 | * @return string |
||
| 59 | */ |
||
| 60 | protected function listOrder() |
||
| 61 | { |
||
| 62 | return '`manufacturer` ASC, `model` ASC, `name` ASC, `created` DESC'; |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * Retrieve a specific device by ID |
||
| 67 | * |
||
| 68 | * Devices default to include a list of logs sub-object |
||
| 69 | * |
||
| 70 | * @param int|string $id |
||
| 71 | * @param array $params |
||
| 72 | * |
||
| 73 | * @return Device|null |
||
| 74 | */ |
||
| 75 | public function get($id, $params = [self::SCOPE_INCLUDE => [self::INCLUDE_LOGS]]) |
||
| 76 | { |
||
| 77 | return parent::get($id, $params); |
||
| 78 | } |
||
| 79 | |||
| 80 | /** |
||
| 81 | * Instantiate bound device when retrieved via `get()` |
||
| 82 | * |
||
| 83 | * This will process the `'includes'` field of `$params` (an array) and, if it contains the term `'logs'`, the list |
||
| 84 | * of logs sub-object will be included in this device object. |
||
| 85 | * |
||
| 86 | * @see AbstractBinding::SCOPE_INCLUDE |
||
| 87 | * |
||
| 88 | * @used-by DevicesBinding::instantiateListedObject() |
||
| 89 | * |
||
| 90 | * @param array $databaseRow |
||
| 91 | * @param array $params |
||
| 92 | * |
||
| 93 | * @return Device |
||
| 94 | */ |
||
| 95 | protected function instantiateObject($databaseRow, $params) |
||
| 96 | { |
||
| 97 | $logs = Device::SUPPRESS_LOGS; |
||
| 98 | View Code Duplication | if (self::parameterValueExists($params, self::SCOPE_INCLUDE, self::INCLUDE_LOGS)) { |
|
|
|
|||
| 99 | $params = self::consumeParameterValue($params, self::SCOPE_INCLUDE, self::INCLUDE_LOGS); |
||
| 100 | $params = self::consumeParameterValue($params, self::SCOPE_INCLUDE, LogsBinding::INCLUDE_DEVICE); |
||
| 101 | $logs = $this->logs()->listByDevice($databaseRow['id'], $params); |
||
| 102 | } |
||
| 103 | return $this->object($databaseRow, $logs); |
||
| 104 | } |
||
| 105 | |||
| 106 | /** |
||
| 107 | * Instantiate bound device when retrieved via `all()` |
||
| 108 | * |
||
| 109 | * This will process the `'includes'` field of `$params` (an array) and, if it contains the term `'logs'`, the list |
||
| 110 | * of logs sub-object will be included in this device object. |
||
| 111 | * @param array $databaseRow |
||
| 112 | * @param array $params |
||
| 113 | * |
||
| 114 | * @uses DevicesBinding::instantiateObject() |
||
| 115 | * |
||
| 116 | * @return Device |
||
| 117 | */ |
||
| 118 | protected function instantiateListedObject($databaseRow, $params) |
||
| 122 | } |
||
| 123 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.