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 DBPreparedQuery 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 DBPreparedQuery, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
17 | class DBPreparedQuery extends DBQuery { |
||
18 | |||
19 | /** |
||
20 | * DB query template. |
||
21 | * |
||
22 | * @var string |
||
23 | */ |
||
24 | public $query = ""; |
||
25 | |||
26 | /** |
||
27 | * Parameters SQL types string ("idsb"). |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | public $types = ""; |
||
32 | |||
33 | /** |
||
34 | * List of the DB SQL query parameters. |
||
35 | * |
||
36 | * @var array |
||
37 | */ |
||
38 | public $params = []; |
||
39 | |||
40 | /** |
||
41 | * Creates and initialize DBPreparedQuery object. |
||
42 | * |
||
43 | * @param string $query DB SQL query template. |
||
44 | * @param string $types Parameters SQL types string ("idsb"). |
||
45 | * @param array $params List of the DB SQL query parameters. |
||
46 | */ |
||
47 | public function __construct($query = "", $types = "", $params = []) { |
||
57 | |||
58 | /** |
||
59 | * Verify if current DBPreparedQuery is have parameters for binding. |
||
60 | * |
||
61 | * @return bool |
||
62 | */ |
||
63 | public function isBindable() { |
||
66 | |||
67 | /** |
||
68 | * Verify if current DBPreparedQuery is valid for the execution. |
||
69 | * |
||
70 | * @return bool |
||
71 | */ |
||
72 | public function isValid() { |
||
77 | |||
78 | /** |
||
79 | * Adds conditions WHERE SQL string to the SQL query. |
||
80 | */ |
||
81 | public function prepareConditions() { |
||
87 | |||
88 | /** |
||
89 | * Adds ORDER SQL string to the SQL query. |
||
90 | */ |
||
91 | public function prepareOrder() { |
||
104 | |||
105 | /** |
||
106 | * Adds LIMIT SQL string to the SQL query. |
||
107 | * |
||
108 | * @return mixed Number of records will be selected or null. |
||
109 | * @throws DBCoreException If some error occurred. |
||
110 | */ |
||
111 | public function prepareLimit() { |
||
132 | |||
133 | /** |
||
134 | * Prepares SQL query to the execution. |
||
135 | * |
||
136 | * @param string $query Initial SQL query string. |
||
137 | * @param array $conditions Conditions list. |
||
138 | * @param array $order List of order conditions (fieldName => order), |
||
139 | * order may be 'ASC' OR 'DESC'. |
||
140 | * @param int $offset Limit offset value (or count if this is single |
||
141 | * parameter). |
||
142 | * @param int $count Number of records to select. |
||
143 | * |
||
144 | * @return DBPreparedQuery Oneself after modifications. |
||
145 | * @throws DBCoreException If some error occurred. |
||
146 | */ |
||
147 | public function prepare($query, $conditions = null, $order = null, $offset = null, $count = null) { |
||
177 | |||
178 | /** |
||
179 | * Executes SQL query. |
||
180 | * |
||
181 | * @param bool $debug Debug mode flag. |
||
182 | * |
||
183 | * @return mixed Statement object or FALSE if an error occurred if SELECT |
||
184 | * query executed or number of affected rows on success if other |
||
185 | * type of query executed. |
||
186 | */ |
||
187 | public function go($debug = false) { |
||
198 | |||
199 | /** |
||
200 | * Shows debug information for the SQL query without execution. |
||
201 | */ |
||
202 | public function debug() { |
||
205 | |||
206 | /** |
||
207 | * Checks query parameters types correspondence. |
||
208 | * |
||
209 | * @param array $params Parameters of the query. |
||
210 | * @param string $types Types of the parameters ("idsb"). |
||
211 | * |
||
212 | * @throws DBCoreException |
||
213 | */ |
||
214 | private static function checkParameterTypes($params, $types) { |
||
270 | |||
271 | /** |
||
272 | * Return qwestion marks string for IN(...) SQL construction. |
||
273 | * |
||
274 | * @param int $length Length of the result string. |
||
275 | * |
||
276 | * @return string |
||
277 | */ |
||
278 | public static function sqlQMString($length) { |
||
281 | |||
282 | /** |
||
283 | * Return fields and qwestion marks string for SET field1=?, ... SQL construction. |
||
284 | * |
||
285 | * @param array<mixed> $fieldsList List of the table fields (syntax: array[fieldName] = fieldValue) |
||
286 | * @param string $idFieldName Name of the primary key field. |
||
287 | * |
||
288 | * @return string |
||
289 | */ |
||
290 | public static function sqlQMValuesString($fieldsList, $idFieldName = "") { |
||
300 | |||
301 | /** |
||
302 | * Return fields and values string for SET field1=value1, ... SQL construction. |
||
303 | * |
||
304 | * @param array<mixed> $fieldsList List of the table fields (syntax: array[fieldName] = fieldValue) |
||
305 | * @param string $idFieldName Name of the primary key field. |
||
306 | * |
||
307 | * @return string |
||
308 | */ |
||
309 | public static function sqlValuesString($fieldsList, $idFieldName) { |
||
319 | |||
320 | /** |
||
321 | * Returns SQL types string. |
||
322 | * Type specification chars: |
||
323 | * i - corresponding variable has type integer |
||
324 | * d - corresponding variable has type double |
||
325 | * s - corresponding variable has type string |
||
326 | * b - corresponding variable is a blob and will be sent in packets. |
||
327 | * |
||
328 | * @param array<mixed> $fieldsList List of the table fields (syntax: array[fieldName] = fieldValue) |
||
329 | * @param string $idFieldName Name of the primary key field. |
||
330 | * @return string |
||
331 | */ |
||
332 | public static function sqlTypesString($fieldsList, $idFieldName = "") { |
||
348 | |||
349 | /** |
||
350 | * Returns SQL types string of single type. |
||
351 | * |
||
352 | * @param string $type SQL type. |
||
353 | * @param int $length Length of the SQL types string. |
||
354 | * |
||
355 | * @return string |
||
356 | * @throws DBFieldTypeException If invalid type passed. |
||
357 | */ |
||
358 | public static function sqlSingleTypeString($type, $length) { |
||
368 | |||
369 | /** |
||
370 | * Push values to the DBPreparedQuery SQL query field end. |
||
371 | * |
||
372 | * @param array $values List of pairs key => value or SQL query parts with |
||
373 | * parameters. |
||
374 | * @param string $separator Join separator. |
||
375 | */ |
||
376 | public function sqlPushValues($values, $separator = ", ") { |
||
400 | |||
401 | } |
||
402 |
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.