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 MySql 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 MySql, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 19 | class MySql extends AbstractConnection { |
||
| 20 | |||
| 21 | /** |
||
| 22 | * Copy a flat array. Aids copying fetched results without the mysqlnd |
||
| 23 | * extension installed without retaining references to array elements. |
||
| 24 | * |
||
| 25 | * Who knew references could be so awkward to get rid of? |
||
| 26 | * |
||
| 27 | * @param array $array |
||
| 28 | * @return array |
||
| 29 | */ |
||
| 30 | protected static function copyArray($array) { |
||
| 39 | |||
| 40 | /** |
||
| 41 | * Fetch result data from the given MySQLi statement. |
||
| 42 | * |
||
| 43 | * Expects the statement to have been executed. |
||
| 44 | * |
||
| 45 | * Attempts to use mysqli_stmt::get_result() and mysqli_result::fetch_all(), |
||
| 46 | * but falls back to fetching from the statement directly if get_result() |
||
| 47 | * isn't found (mysqlnd isn't installed). |
||
| 48 | * |
||
| 49 | * @param mysqli_stmt $statement |
||
| 50 | * @return array array($data, $fields, $count) |
||
| 51 | */ |
||
| 52 | protected function fetchResult(mysqli_stmt $statement) { |
||
| 69 | |||
| 70 | /** |
||
| 71 | * Method for fetching the same information in a way that doesn't require |
||
| 72 | * mysqlnd to be installed. |
||
| 73 | * |
||
| 74 | * Fetches directly from the statement with variable binding instead. |
||
| 75 | * |
||
| 76 | * @param mysqli_stmt $statement |
||
| 77 | * @return array |
||
| 78 | */ |
||
| 79 | protected function fetchResultWithoutNativeDriver(mysqli_stmt $statement) { |
||
| 107 | |||
| 108 | /** |
||
| 109 | * Retrieve the type of a variable for binding mysqli parameters. |
||
| 110 | * |
||
| 111 | * @param mixed $parameter |
||
| 112 | * @return string |
||
| 113 | */ |
||
| 114 | protected function prepareType($parameter) { |
||
| 125 | |||
| 126 | /** |
||
| 127 | * Prepares an array of values as an array of references to those values. |
||
| 128 | * |
||
| 129 | * Required for PHP 5.3+ to prevent warnings when dynamically invoking |
||
| 130 | * mysqli_stmt::bind_param(). |
||
| 131 | * |
||
| 132 | * @param array $parameters |
||
| 133 | * @return array |
||
| 134 | */ |
||
| 135 | protected function prepareReferences(array $parameters) { |
||
| 144 | |||
| 145 | /** |
||
| 146 | * Prepare the given query and parameters as a mysqli statement. |
||
| 147 | * |
||
| 148 | * @param string $query |
||
| 149 | * @param array $parameters [optional] |
||
| 150 | * @return \mysqli_stmt |
||
| 151 | */ |
||
| 152 | protected function prepareStatement($query, $parameters = array()) { |
||
| 178 | |||
| 179 | /** |
||
| 180 | * Prepare a result array using the given mysqli statement. |
||
| 181 | * |
||
| 182 | * @param mysqli_stmt $statement |
||
| 183 | * @return array |
||
| 184 | */ |
||
| 185 | protected function prepareStatementResult(mysqli_stmt $statement) { |
||
| 200 | |||
| 201 | /** |
||
| 202 | * Initiate the connection. |
||
| 203 | * |
||
| 204 | * @return bool |
||
| 205 | */ |
||
| 206 | public function connect() { |
||
| 225 | |||
| 226 | /** |
||
| 227 | * Determine whether the connection is currently active. |
||
| 228 | * |
||
| 229 | * @return bool |
||
| 230 | */ |
||
| 231 | public function connected() { |
||
| 234 | |||
| 235 | /** |
||
| 236 | * Close the connection. |
||
| 237 | */ |
||
| 238 | public function disconnect() { |
||
| 242 | |||
| 243 | /** |
||
| 244 | * Retrieve the query translator. |
||
| 245 | * |
||
| 246 | * @return Translator |
||
| 247 | */ |
||
| 248 | public function translator() { |
||
| 255 | |||
| 256 | /** |
||
| 257 | * Query the database with the given query and optional parameters. |
||
| 258 | * |
||
| 259 | * TODO: Simplify this. |
||
| 260 | * |
||
| 261 | * @param Query|string $query |
||
| 262 | * @param array $parameters [optional] |
||
| 263 | * @return Result |
||
| 264 | */ |
||
| 265 | public function query($query, array $parameters = array()) { |
||
| 324 | |||
| 325 | /** |
||
| 326 | * Escape the given string for a MySQL query. |
||
| 327 | * |
||
| 328 | * @param string $string |
||
| 329 | * @return string |
||
| 330 | */ |
||
| 331 | public function escape($string) { |
||
| 336 | |||
| 337 | /** |
||
| 338 | * Retrieve error information regarding the last query or connection |
||
| 339 | * attempt. |
||
| 340 | * |
||
| 341 | * Returns null if there is no error. |
||
| 342 | * |
||
| 343 | * @return Error |
||
| 344 | */ |
||
| 345 | public function error() { |
||
| 358 | |||
| 359 | /** |
||
| 360 | * Retrieve error information from the mysqli connection object. |
||
| 361 | * |
||
| 362 | * Checks for general errors first, then connection errors. |
||
| 363 | * |
||
| 364 | * Returns null if there is no error. |
||
| 365 | * |
||
| 366 | * @return Error |
||
| 367 | */ |
||
| 368 | protected function connectionError() { |
||
| 383 | |||
| 384 | } |
||
| 385 |
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.