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:
Complex classes like Table often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Table, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
41 | class Table |
||
42 | { |
||
43 | /** |
||
44 | * @var string |
||
45 | */ |
||
46 | protected $name; |
||
47 | |||
48 | /** |
||
49 | * @var array |
||
50 | */ |
||
51 | protected $options = []; |
||
52 | |||
53 | /** |
||
54 | * @var AdapterInterface |
||
55 | */ |
||
56 | protected $adapter; |
||
57 | |||
58 | /** |
||
59 | * @var array |
||
60 | */ |
||
61 | protected $columns = []; |
||
62 | |||
63 | /** |
||
64 | * @var array |
||
65 | */ |
||
66 | protected $indexes = []; |
||
67 | |||
68 | /** |
||
69 | * @var ForeignKey[] |
||
70 | */ |
||
71 | protected $foreignKeys = []; |
||
72 | |||
73 | /** |
||
74 | * @var array |
||
75 | */ |
||
76 | protected $data = []; |
||
77 | |||
78 | /** |
||
79 | * Class Constuctor. |
||
80 | * |
||
81 | * @param string $name Table Name |
||
82 | * @param array $options Options |
||
83 | * @param AdapterInterface $adapter Database Adapter |
||
84 | 239 | */ |
|
85 | public function __construct($name, $options = [], AdapterInterface $adapter = null) |
||
94 | |||
95 | /** |
||
96 | * Sets the table name. |
||
97 | * |
||
98 | * @param string $name Table Name |
||
99 | * @return Table |
||
100 | 239 | */ |
|
101 | public function setName($name) |
||
106 | |||
107 | /** |
||
108 | * Gets the table name. |
||
109 | * |
||
110 | * @return string |
||
111 | 215 | */ |
|
112 | public function getName() |
||
116 | |||
117 | /** |
||
118 | * Sets the table options. |
||
119 | * |
||
120 | * @param array $options |
||
121 | * @return Table |
||
122 | 239 | */ |
|
123 | public function setOptions($options) |
||
128 | |||
129 | /** |
||
130 | * Gets the table options. |
||
131 | * |
||
132 | * @return array |
||
133 | 189 | */ |
|
134 | public function getOptions() |
||
138 | |||
139 | /** |
||
140 | * Sets the database adapter. |
||
141 | * |
||
142 | * @param AdapterInterface $adapter Database Adapter |
||
143 | * @return Table |
||
144 | 231 | */ |
|
145 | public function setAdapter(AdapterInterface $adapter) |
||
150 | |||
151 | /** |
||
152 | * Gets the database adapter. |
||
153 | * |
||
154 | * @return AdapterInterface |
||
155 | 225 | */ |
|
156 | public function getAdapter() |
||
160 | |||
161 | /** |
||
162 | * Does the table exist? |
||
163 | * |
||
164 | * @return boolean |
||
165 | 195 | */ |
|
166 | public function exists() |
||
170 | |||
171 | /** |
||
172 | * Drops the database table. |
||
173 | * |
||
174 | * @return void |
||
175 | 1 | */ |
|
176 | public function drop() |
||
180 | |||
181 | /** |
||
182 | * Renames the database table. |
||
183 | * |
||
184 | * @param string $newTableName New Table Name |
||
185 | * @return Table |
||
186 | 3 | */ |
|
187 | public function rename($newTableName) |
||
193 | |||
194 | /** |
||
195 | * Sets an array of columns waiting to be committed. |
||
196 | * Use setPendingColumns |
||
197 | * |
||
198 | * @deprecated |
||
199 | * @param array $columns Columns |
||
200 | * @return Table |
||
201 | */ |
||
202 | public function setColumns($columns) |
||
206 | |||
207 | /** |
||
208 | * Gets an array of the table columns. |
||
209 | * |
||
210 | * @return Column[] |
||
211 | 10 | */ |
|
212 | public function getColumns() |
||
216 | |||
217 | /** |
||
218 | * Sets an array of columns waiting to be committed. |
||
219 | * |
||
220 | * @param array $columns Columns |
||
221 | * @return Table |
||
222 | 196 | */ |
|
223 | public function setPendingColumns($columns) |
||
228 | |||
229 | /** |
||
230 | * Gets an array of columns waiting to be committed. |
||
231 | * |
||
232 | * @return Column[] |
||
233 | 204 | */ |
|
234 | public function getPendingColumns() |
||
238 | |||
239 | /** |
||
240 | * Sets an array of columns waiting to be indexed. |
||
241 | * |
||
242 | * @param array $indexes Indexes |
||
243 | * @return Table |
||
244 | 196 | */ |
|
245 | public function setIndexes($indexes) |
||
250 | |||
251 | /** |
||
252 | * Gets an array of indexes waiting to be committed. |
||
253 | * |
||
254 | * @return array |
||
255 | 191 | */ |
|
256 | public function getIndexes() |
||
260 | |||
261 | /** |
||
262 | * Sets an array of foreign keys waiting to be commited. |
||
263 | * |
||
264 | * @param ForeignKey[] $foreignKeys foreign keys |
||
265 | * @return Table |
||
266 | 196 | */ |
|
267 | public function setForeignKeys($foreignKeys) |
||
272 | |||
273 | /** |
||
274 | * Gets an array of foreign keys waiting to be commited. |
||
275 | * |
||
276 | * @return array|ForeignKey[] |
||
277 | 192 | */ |
|
278 | public function getForeignKeys() |
||
282 | |||
283 | /** |
||
284 | * Sets an array of data to be inserted. |
||
285 | * |
||
286 | * @param array $data Data |
||
287 | * @return Table |
||
288 | 196 | */ |
|
289 | public function setData($data) |
||
294 | |||
295 | /** |
||
296 | * Gets the data waiting to be inserted. |
||
297 | * |
||
298 | * @return array |
||
299 | 197 | */ |
|
300 | public function getData() |
||
304 | |||
305 | /** |
||
306 | * Resets all of the pending table changes. |
||
307 | * |
||
308 | * @return void |
||
309 | 196 | */ |
|
310 | public function reset() |
||
317 | |||
318 | /** |
||
319 | * Add a table column. |
||
320 | * |
||
321 | * Type can be: string, text, integer, float, decimal, datetime, timestamp, |
||
322 | * time, date, binary, boolean. |
||
323 | * |
||
324 | * Valid options can be: limit, default, null, precision or scale. |
||
325 | * |
||
326 | * @param string|Column $columnName Column Name |
||
327 | * @param string $type Column Type |
||
328 | * @param array $options Column Options |
||
329 | * @throws \RuntimeException |
||
330 | * @throws \InvalidArgumentException |
||
331 | * @return Table |
||
332 | 210 | */ |
|
333 | public function addColumn($columnName, $type = null, $options = []) |
||
362 | |||
363 | /** |
||
364 | * Add a table column with a custom type definition. |
||
365 | * |
||
366 | * Type can be any string that you expect your DBMS to understand |
||
367 | * |
||
368 | 1 | * Valid options can be: default or null. |
|
369 | * |
||
370 | 1 | * For widely supported types @see addColumn |
|
371 | 1 | * |
|
372 | * @param string|CustomColumn $columnName Column Name |
||
373 | * @param string $type Column Type |
||
374 | * @param array $options Column Options |
||
375 | * @return Table |
||
376 | */ |
||
377 | public function addCustomColumn($columnName, $type = null, $options = array()) |
||
392 | |||
393 | /** |
||
394 | * Remove a table column. |
||
395 | 17 | * |
|
396 | * @param string $columnName Column Name |
||
397 | * @return Table |
||
398 | 17 | */ |
|
399 | 4 | public function removeColumn($columnName) |
|
404 | |||
405 | /** |
||
406 | * Rename a table column. |
||
407 | 17 | * |
|
408 | 15 | * @param string $oldName Old Column Name |
|
409 | 15 | * @param string $newName New Column Name |
|
410 | * @return Table |
||
411 | 17 | */ |
|
412 | 17 | public function renameColumn($oldName, $newName) |
|
417 | |||
418 | /** |
||
419 | * Change a table column type. |
||
420 | * |
||
421 | 89 | * @param string $columnName Column Name |
|
422 | * @param string|Column $newColumnType New Column Type |
||
423 | 89 | * @param array $options Options |
|
424 | * @return Table |
||
425 | */ |
||
426 | public function changeColumn($columnName, $newColumnType, $options = []) |
||
445 | 28 | ||
446 | 1 | /** |
|
447 | * Checks to see if a column exists. |
||
448 | * |
||
449 | 29 | * @param string $columnName Column Name |
|
450 | 29 | * @return boolean |
|
451 | */ |
||
452 | public function hasColumn($columnName) |
||
456 | |||
457 | /** |
||
458 | * Add an index to a database table. |
||
459 | 1 | * |
|
460 | * In $options you can specific unique = true/false or name (index name). |
||
461 | 1 | * |
|
462 | 1 | * @param string|array|Index $columns Table Column(s) |
|
463 | * @param array $options Index Options |
||
464 | * @return Table |
||
465 | */ |
||
466 | public function addIndex($columns, $options = []) |
||
483 | |||
484 | 12 | /** |
|
485 | * Removes the given index from a table. |
||
486 | 12 | * |
|
487 | * @param array $columns Columns |
||
488 | * @return Table |
||
489 | */ |
||
490 | public function removeIndex($columns) |
||
495 | |||
496 | /** |
||
497 | * Removes the given index identified by its name from a table. |
||
498 | * |
||
499 | * @param string $name Index name |
||
500 | * @return Table |
||
501 | 8 | */ |
|
502 | public function removeIndexByName($name) |
||
507 | 8 | ||
508 | /** |
||
509 | * Checks to see if an index exists. |
||
510 | 8 | * |
|
511 | * @param string|array $columns Columns |
||
512 | 8 | * @param array $options Options |
|
513 | 8 | * @return boolean |
|
514 | 8 | */ |
|
515 | 8 | public function hasIndex($columns) |
|
519 | |||
520 | /** |
||
521 | * Add a foreign key to a database table. |
||
522 | * |
||
523 | * In $options you can specify on_delete|on_delete = cascade|no_action .., |
||
524 | * on_update, constraint = constraint name. |
||
525 | * |
||
526 | * @param string|array $columns Columns |
||
527 | 1 | * @param string|Table $referencedTable Referenced Table |
|
528 | * @param string|array $referencedColumns Referenced Columns |
||
529 | 1 | * @param array $options Options |
|
530 | 1 | * @return Table |
|
531 | 1 | */ |
|
532 | 1 | public function addForeignKey($columns, $referencedTable, $referencedColumns = ['id'], $options = []) |
|
550 | 1 | ||
551 | /** |
||
552 | * Removes the given foreign key from the table. |
||
553 | * |
||
554 | * @param string|array $columns Column(s) |
||
555 | * @param null|string $constraint Constraint names |
||
556 | * @return Table |
||
557 | */ |
||
558 | public function dropForeignKey($columns, $constraint = null) |
||
571 | |||
572 | 15 | /** |
|
573 | * Checks to see if a foreign key exists. |
||
574 | 15 | * |
|
575 | * @param string|array $columns Column(s) |
||
576 | * @param null|string $constraint Constraint names |
||
577 | * @return boolean |
||
578 | */ |
||
579 | public function hasForeignKey($columns, $constraint = null) |
||
583 | |||
584 | /** |
||
585 | * Add timestamp columns created_at and updated_at to the table. |
||
586 | * |
||
587 | * @param string $createdAtColumnName |
||
588 | * @param string $updatedAtColumnName |
||
589 | 17 | * |
|
590 | * @return Table |
||
591 | */ |
||
592 | 17 | public function addTimestamps($createdAtColumnName = 'created_at', $updatedAtColumnName = 'updated_at') |
|
607 | 196 | ||
608 | /** |
||
609 | 196 | * Insert data into the table. |
|
610 | 196 | * |
|
611 | 196 | * @param $data array of data in the form: |
|
612 | 196 | * array( |
|
613 | * array("col1" => "value1", "col2" => "anotherValue1"), |
||
614 | * array("col2" => "value2", "col2" => "anotherValue2"), |
||
615 | * ) |
||
616 | * or array("col1" => "value1", "col2" => "anotherValue1") |
||
617 | * |
||
618 | * @return Table |
||
619 | */ |
||
620 | 46 | public function insert($data) |
|
632 | 6 | ||
633 | 46 | /** |
|
634 | * Creates a table from the object instance. |
||
635 | 46 | * |
|
636 | 3 | * @return void |
|
637 | 46 | */ |
|
638 | public function create() |
||
644 | |||
645 | /** |
||
646 | * Updates a table from the object instance. |
||
647 | * |
||
648 | 196 | * @throws \RuntimeException |
|
649 | * @return void |
||
650 | 196 | */ |
|
651 | 196 | public function update() |
|
673 | 12 | ||
674 | /** |
||
675 | * Commit the pending data waiting for insertion. |
||
676 | * |
||
677 | * @return void |
||
678 | */ |
||
679 | public function saveData() |
||
705 | |||
706 | /** |
||
707 | * Truncates the table. |
||
708 | * |
||
709 | * @return void |
||
710 | */ |
||
711 | public function truncate() |
||
712 | { |
||
713 | $this->getAdapter()->truncateTable($this->getName()); |
||
714 | } |
||
715 | |||
716 | /** |
||
717 | * Commits the table changes. |
||
718 | * |
||
719 | * If the table doesn't exist it is created otherwise it is updated. |
||
720 | * |
||
721 | * @return void |
||
722 | */ |
||
723 | public function save() |
||
733 | } |
||
734 |
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.