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 PdoOci8Statement 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 PdoOci8Statement, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class PdoOci8Statement extends \PDOStatement |
||
15 | { |
||
16 | /** @var Oci8ConnectionInterface */ |
||
17 | private $connection; |
||
18 | |||
19 | /** @var Oci8StatementInterface */ |
||
20 | private $statement; |
||
21 | |||
22 | /** @var string */ |
||
23 | private $sqlText = ''; |
||
24 | |||
25 | /** @var array */ |
||
26 | private $boundParameters = array(); |
||
27 | |||
28 | /** @var array */ |
||
29 | private $options; |
||
30 | |||
31 | /** @var \ArrayIterator */ |
||
32 | private $iterator; |
||
33 | |||
34 | 44 | public function __construct(Oci8ConnectionInterface $connection, $sqlText, $options = array()) |
|
35 | { |
||
36 | 44 | if (!is_string($sqlText)) { |
|
37 | throw new PdoOci8Exception('$sqlText is not a string'); |
||
38 | } |
||
39 | |||
40 | 44 | $this->connection = $connection; |
|
41 | 44 | $this->sqlText = $sqlText; |
|
42 | //TODO assign value to queryString |
||
43 | //$this->queryString = $sqlText; |
||
|
|||
44 | |||
45 | 44 | $this->options = array( |
|
46 | 44 | \PDO::ATTR_AUTOCOMMIT => true, |
|
47 | 44 | \PDO::ATTR_CASE => \PDO::CASE_NATURAL, |
|
48 | 44 | \PDO::ATTR_ERRMODE => \PDO::ERRMODE_SILENT, |
|
49 | 44 | \PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL, |
|
50 | 44 | \PDO::ATTR_PREFETCH => 100, |
|
51 | 44 | \PDO::ATTR_TIMEOUT => 600, |
|
52 | 44 | \PDO::ATTR_STRINGIFY_FETCHES => false, |
|
53 | 44 | \PDO::ATTR_STATEMENT_CLASS => null, |
|
54 | 44 | \PDO::ATTR_EMULATE_PREPARES => false, |
|
55 | 44 | \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_BOTH, |
|
56 | 44 | \PDO::ATTR_FETCH_TABLE_NAMES => false, |
|
57 | 44 | \PDO::ATTR_FETCH_CATALOG_NAMES => false, |
|
58 | 44 | \PDO::ATTR_MAX_COLUMN_LEN => 0, |
|
59 | 44 | PdoOci8::OCI_ATTR_RETURN_LOBS => false, |
|
60 | ); |
||
61 | |||
62 | 44 | View Code Duplication | foreach ($options as $option => $value) { |
63 | 44 | if (array_key_exists($option, $this->options)) { |
|
64 | 44 | $this->options[$option] = $value; |
|
65 | 44 | } |
|
66 | 44 | } |
|
67 | |||
68 | 44 | foreach ($options as $attribute => $value) { |
|
69 | 44 | $this->setAttribute($attribute, $value); |
|
70 | 44 | } |
|
71 | |||
72 | try { |
||
73 | 44 | $this->statement = $connection->parse($sqlText); |
|
74 | 44 | } catch (\Exception $ex) { |
|
75 | throw new PdoOci8Exception($ex->getMessage(), $ex->getCode(), $ex); |
||
76 | } |
||
77 | 44 | } |
|
78 | |||
79 | /** |
||
80 | * @param int|string $column |
||
81 | * @param mixed $param |
||
82 | * @param int $type |
||
83 | * @param int $maxlen |
||
84 | * @param mixed $driverdata |
||
85 | * |
||
86 | * @link http://php.net/manual/en/pdostatement.bindcolumn.php |
||
87 | * @return bool |
||
88 | */ |
||
89 | 2 | public function bindColumn($column, &$param, $type = null, $maxlen = null, $driverdata = null) |
|
101 | |||
102 | /** |
||
103 | * @param string $parameter |
||
104 | * @param mixed $variable |
||
105 | * @param int $data_type |
||
106 | * @param int $length |
||
107 | * @param mixed $driver_options |
||
108 | * |
||
109 | * @link http://php.net/manual/en/pdostatement.bindparam.php |
||
110 | * @return bool |
||
111 | */ |
||
112 | 8 | public function bindParam( |
|
139 | |||
140 | /** |
||
141 | * @param string $parameter |
||
142 | * @param $value |
||
143 | * @param int $data_type |
||
144 | * |
||
145 | * @link http://php.net/manual/en/pdostatement.bindvalue.php |
||
146 | * @return bool |
||
147 | */ |
||
148 | 3 | public function bindValue($parameter, $value, $data_type = \PDO::PARAM_STR) |
|
152 | |||
153 | /** |
||
154 | * @link http://php.net/manual/en/pdostatement.closecursor.php |
||
155 | * @return bool |
||
156 | */ |
||
157 | 1 | public function closeCursor() |
|
161 | |||
162 | /** |
||
163 | * @link http://php.net/manual/en/pdostatement.columncount.php |
||
164 | * @return int |
||
165 | */ |
||
166 | 1 | public function columnCount() |
|
170 | |||
171 | /** |
||
172 | * @link http://php.net/manual/en/pdostatement.debugdumpparams.php |
||
173 | */ |
||
174 | 2 | public function debugDumpParams() |
|
210 | |||
211 | /** |
||
212 | * @link http://php.net/manual/en/pdostatement.errorcode.php |
||
213 | * @return string |
||
214 | */ |
||
215 | 2 | View Code Duplication | public function errorCode() |
227 | |||
228 | /** |
||
229 | * @link http://php.net/manual/en/pdo.errorinfo.php |
||
230 | * @return array |
||
231 | */ |
||
232 | 3 | public function errorInfo() |
|
252 | |||
253 | /** |
||
254 | * @param array $input_parameters |
||
255 | * |
||
256 | * @link http://php.net/manual/en/pdostatement.execute.php |
||
257 | * @return bool |
||
258 | */ |
||
259 | 21 | public function execute($input_parameters = array()) |
|
287 | |||
288 | /** |
||
289 | * @param int $fetch_style |
||
290 | * @param int $cursor_orientation |
||
291 | * @param int $cursor_offset |
||
292 | * |
||
293 | * @link http://php.net/manual/en/pdostatement.fetch.php |
||
294 | * @return mixed |
||
295 | */ |
||
296 | 10 | public function fetch( |
|
362 | |||
363 | /** |
||
364 | * @param int $fetch_style |
||
365 | * @param mixed $fetch_argument |
||
366 | * @param array $ctor_args |
||
367 | * |
||
368 | * @link http://php.net/manual/en/pdostatement.fetchall.php |
||
369 | * @return array |
||
370 | */ |
||
371 | 4 | public function fetchAll($fetch_style = null, $fetch_argument = null, $ctor_args = array()) |
|
402 | |||
403 | /** |
||
404 | * @param int $column_number |
||
405 | * |
||
406 | * @link http://php.net/manual/en/pdostatement.fetchcolumn.php |
||
407 | * @return mixed |
||
408 | */ |
||
409 | 3 | public function fetchColumn($column_number = 0) |
|
423 | |||
424 | |||
425 | /** |
||
426 | * @param string $class_name |
||
427 | * @param array $ctor_args |
||
428 | * |
||
429 | * @link http://php.net/manual/en/pdostatement.fetchobject.php |
||
430 | * @return bool|object |
||
431 | */ |
||
432 | 2 | public function fetchObject($class_name = "stdClass", $ctor_args = array()) |
|
448 | |||
449 | /** |
||
450 | * @param int $attribute |
||
451 | * |
||
452 | * @link http://php.net/manual/en/pdostatement.getattribute.php |
||
453 | * @return mixed |
||
454 | */ |
||
455 | 24 | public function getAttribute($attribute) |
|
463 | |||
464 | /** |
||
465 | * @param int $column |
||
466 | * |
||
467 | * @throws PdoOci8Exception |
||
468 | * |
||
469 | * @link http://php.net/manual/en/pdostatement.getcolumnmeta.php |
||
470 | * @return bool|array |
||
471 | */ |
||
472 | 4 | public function getColumnMeta($column) |
|
507 | |||
508 | /** |
||
509 | * @link http://php.net/manual/en/pdostatement.nextrowset.php |
||
510 | * @return bool |
||
511 | */ |
||
512 | public function nextRowset() |
||
516 | |||
517 | /** |
||
518 | * @link http://php.net/manual/en/pdostatement.rowcount.php |
||
519 | * @return int |
||
520 | */ |
||
521 | 3 | public function rowCount() |
|
525 | |||
526 | |||
527 | /** |
||
528 | * @param $attribute |
||
529 | * @param $value |
||
530 | * |
||
531 | * @link http://php.net/manual/en/pdostatement.setattribute.php |
||
532 | * @return bool |
||
533 | */ |
||
534 | 44 | public function setAttribute($attribute, $value) |
|
549 | |||
550 | /** |
||
551 | * @param int $mode |
||
552 | * @param string|int|object $target |
||
553 | * @param array $ctor_args |
||
554 | * |
||
555 | * @link http://php.net/manual/en/pdostatement.setfetchmode.php |
||
556 | * @return bool |
||
557 | */ |
||
558 | 1 | public function setFetchMode($mode, $target = null, $ctor_args = array()) |
|
568 | |||
569 | /** |
||
570 | * @return string |
||
571 | */ |
||
572 | 3 | protected function getTableName() |
|
595 | |||
596 | /** |
||
597 | * @param string $data_type The data type name |
||
598 | * |
||
599 | * @return int |
||
600 | */ |
||
601 | 3 | protected function getPDODataType($data_type) |
|
626 | |||
627 | /** |
||
628 | * @param int $type |
||
629 | * @throws PdoOci8Exception |
||
630 | * @return int |
||
631 | */ |
||
632 | 10 | protected function getDriverDataType($type) |
|
663 | |||
664 | /** |
||
665 | * @return Oci8ConnectionInterface |
||
666 | */ |
||
667 | 3 | protected function getConnection() |
|
671 | |||
672 | /** |
||
673 | * @return \Traversable |
||
674 | */ |
||
675 | 1 | protected function getInternalIterator() |
|
691 | |||
692 | /** |
||
693 | * @return array |
||
694 | */ |
||
695 | public function current() |
||
701 | |||
702 | public function next() |
||
708 | |||
709 | /** |
||
710 | * @return int|null |
||
711 | */ |
||
712 | public function key() |
||
718 | |||
719 | /** |
||
720 | * @return bool |
||
721 | */ |
||
722 | 1 | public function valid() |
|
728 | |||
729 | public function rewind() |
||
735 | } |
||
736 |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.