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 DB2Platform 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 DB2Platform, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
40 | class DB2Platform extends AbstractPlatform |
||
41 | { |
||
42 | /** |
||
43 | * {@inheritdoc} |
||
44 | */ |
||
45 | public function getCharMaxLength() : int |
||
49 | |||
50 | /** |
||
51 | * {@inheritdoc} |
||
52 | */ |
||
53 | public function getBinaryMaxLength() |
||
57 | |||
58 | /** |
||
59 | * {@inheritdoc} |
||
60 | */ |
||
61 | public function getBinaryDefaultLength() |
||
65 | |||
66 | /** |
||
67 | * {@inheritDoc} |
||
68 | */ |
||
69 | public function getVarcharTypeDeclarationSQL(array $field) |
||
78 | |||
79 | /** |
||
80 | * {@inheritDoc} |
||
81 | */ |
||
82 | public function getBlobTypeDeclarationSQL(array $field) |
||
87 | |||
88 | /** |
||
89 | * {@inheritDoc} |
||
90 | */ |
||
91 | public function initializeDoctrineTypeMappings() |
||
111 | |||
112 | /** |
||
113 | * {@inheritdoc} |
||
114 | */ |
||
115 | public function isCommentedDoctrineType(Type $doctrineType) |
||
125 | |||
126 | /** |
||
127 | * {@inheritDoc} |
||
128 | */ |
||
129 | protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) |
||
134 | |||
135 | /** |
||
136 | * {@inheritdoc} |
||
137 | */ |
||
138 | protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) |
||
142 | |||
143 | /** |
||
144 | * {@inheritDoc} |
||
145 | */ |
||
146 | public function getClobTypeDeclarationSQL(array $field) |
||
151 | |||
152 | /** |
||
153 | * {@inheritDoc} |
||
154 | */ |
||
155 | public function getName() |
||
159 | |||
160 | /** |
||
161 | * {@inheritDoc} |
||
162 | */ |
||
163 | public function getBooleanTypeDeclarationSQL(array $columnDef) |
||
167 | |||
168 | /** |
||
169 | * {@inheritDoc} |
||
170 | */ |
||
171 | public function getIntegerTypeDeclarationSQL(array $columnDef) |
||
175 | |||
176 | /** |
||
177 | * {@inheritDoc} |
||
178 | */ |
||
179 | public function getBigIntTypeDeclarationSQL(array $columnDef) |
||
183 | |||
184 | /** |
||
185 | * {@inheritDoc} |
||
186 | */ |
||
187 | public function getSmallIntTypeDeclarationSQL(array $columnDef) |
||
191 | |||
192 | /** |
||
193 | * {@inheritDoc} |
||
194 | */ |
||
195 | protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) |
||
204 | |||
205 | /** |
||
206 | * {@inheritdoc} |
||
207 | */ |
||
208 | public function getBitAndComparisonExpression($value1, $value2) |
||
212 | |||
213 | /** |
||
214 | * {@inheritdoc} |
||
215 | */ |
||
216 | public function getBitOrComparisonExpression($value1, $value2) |
||
220 | |||
221 | /** |
||
222 | * {@inheritdoc} |
||
223 | */ |
||
224 | protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) |
||
240 | |||
241 | /** |
||
242 | * {@inheritdoc} |
||
243 | */ |
||
244 | public function getDateDiffExpression($date1, $date2) |
||
248 | |||
249 | /** |
||
250 | * {@inheritDoc} |
||
251 | */ |
||
252 | public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) |
||
260 | |||
261 | /** |
||
262 | * {@inheritDoc} |
||
263 | */ |
||
264 | public function getDateTypeDeclarationSQL(array $fieldDeclaration) |
||
268 | |||
269 | /** |
||
270 | * {@inheritDoc} |
||
271 | */ |
||
272 | public function getTimeTypeDeclarationSQL(array $fieldDeclaration) |
||
276 | |||
277 | /** |
||
278 | * {@inheritdoc} |
||
279 | */ |
||
280 | public function getTruncateTableSQL($tableName, $cascade = false) |
||
286 | |||
287 | /** |
||
288 | * This code fragment is originally from the Zend_Db_Adapter_Db2 class, but has been edited. |
||
289 | * |
||
290 | * @license New BSD License |
||
291 | * |
||
292 | * @param string $table |
||
293 | * @param string $database |
||
|
|||
294 | * |
||
295 | * @return string |
||
296 | */ |
||
297 | public function getListTableColumnsSQL($table, $database = null) |
||
344 | |||
345 | /** |
||
346 | * {@inheritDoc} |
||
347 | */ |
||
348 | public function getListTablesSQL() |
||
352 | |||
353 | /** |
||
354 | * {@inheritDoc} |
||
355 | */ |
||
356 | public function getListViewsSQL($database) |
||
360 | |||
361 | /** |
||
362 | * {@inheritDoc} |
||
363 | */ |
||
364 | public function getListTableIndexesSQL($table, $currentDatabase = null) |
||
384 | |||
385 | /** |
||
386 | * {@inheritDoc} |
||
387 | */ |
||
388 | public function getListTableForeignKeysSQL($table) |
||
418 | |||
419 | /** |
||
420 | * {@inheritDoc} |
||
421 | */ |
||
422 | public function getCreateViewSQL($name, $sql) |
||
426 | |||
427 | /** |
||
428 | * {@inheritDoc} |
||
429 | */ |
||
430 | public function getDropViewSQL($name) |
||
434 | |||
435 | /** |
||
436 | * {@inheritDoc} |
||
437 | */ |
||
438 | public function getCreateDatabaseSQL($database) |
||
442 | |||
443 | /** |
||
444 | * {@inheritDoc} |
||
445 | */ |
||
446 | public function getDropDatabaseSQL($database) |
||
450 | |||
451 | /** |
||
452 | * {@inheritDoc} |
||
453 | */ |
||
454 | public function supportsCreateDropDatabase() |
||
458 | |||
459 | /** |
||
460 | * {@inheritDoc} |
||
461 | */ |
||
462 | public function supportsReleaseSavepoints() |
||
466 | |||
467 | /** |
||
468 | * {@inheritdoc} |
||
469 | */ |
||
470 | public function supportsCommentOnStatement() |
||
474 | |||
475 | /** |
||
476 | * {@inheritDoc} |
||
477 | */ |
||
478 | public function getCurrentDateSQL() |
||
482 | |||
483 | /** |
||
484 | * {@inheritDoc} |
||
485 | */ |
||
486 | public function getCurrentTimeSQL() |
||
490 | |||
491 | /** |
||
492 | * {@inheritDoc} |
||
493 | */ |
||
494 | public function getCurrentTimestampSQL() |
||
498 | |||
499 | /** |
||
500 | * {@inheritDoc} |
||
501 | */ |
||
502 | public function getIndexDeclarationSQL($name, Index $index) |
||
507 | |||
508 | /** |
||
509 | * {@inheritDoc} |
||
510 | */ |
||
511 | protected function _getCreateTableSQL($tableName, array $columns, array $options = []) |
||
526 | |||
527 | /** |
||
528 | * {@inheritDoc} |
||
529 | */ |
||
530 | public function getAlterTableSQL(TableDiff $diff) |
||
632 | |||
633 | /** |
||
634 | * Gathers the table alteration SQL for a given column diff. |
||
635 | * |
||
636 | * @param Table $table The table to gather the SQL for. |
||
637 | * @param ColumnDiff $columnDiff The column diff to evaluate. |
||
638 | * @param array $sql The sequence of table alteration statements to fill. |
||
639 | * @param array $queryParts The sequence of column alteration clauses to fill. |
||
640 | */ |
||
641 | private function gatherAlterColumnSQL(Table $table, ColumnDiff $columnDiff, array &$sql, array &$queryParts) |
||
663 | |||
664 | /** |
||
665 | * Returns the ALTER COLUMN SQL clauses for altering a column described by the given column diff. |
||
666 | * |
||
667 | * @param ColumnDiff $columnDiff The column diff to evaluate. |
||
668 | * |
||
669 | * @return array |
||
670 | */ |
||
671 | private function getAlterColumnClausesSQL(ColumnDiff $columnDiff) |
||
710 | |||
711 | /** |
||
712 | * {@inheritDoc} |
||
713 | */ |
||
714 | protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) |
||
743 | |||
744 | /** |
||
745 | * {@inheritdoc} |
||
746 | */ |
||
747 | View Code Duplication | protected function getRenameIndexSQL($oldIndexName, Index $index, $tableName) |
|
756 | |||
757 | /** |
||
758 | * {@inheritDoc} |
||
759 | */ |
||
760 | public function getDefaultValueDeclarationSQL($field) |
||
774 | |||
775 | /** |
||
776 | * {@inheritDoc} |
||
777 | */ |
||
778 | public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) |
||
782 | |||
783 | /** |
||
784 | * {@inheritDoc} |
||
785 | */ |
||
786 | public function getCreateTemporaryTableSnippetSQL() |
||
790 | |||
791 | /** |
||
792 | * {@inheritDoc} |
||
793 | */ |
||
794 | public function getTemporaryTableName($tableName) |
||
798 | |||
799 | /** |
||
800 | * {@inheritDoc} |
||
801 | */ |
||
802 | protected function doModifyLimitQuery($query, $limit, $offset = null) |
||
825 | |||
826 | /** |
||
827 | * {@inheritDoc} |
||
828 | */ |
||
829 | View Code Duplication | public function getLocateExpression($str, $substr, $startPos = false) |
|
837 | |||
838 | /** |
||
839 | * {@inheritDoc} |
||
840 | */ |
||
841 | View Code Duplication | public function getSubstringExpression($value, $from, $length = null) |
|
849 | |||
850 | /** |
||
851 | * {@inheritDoc} |
||
852 | */ |
||
853 | public function supportsIdentityColumns() |
||
857 | |||
858 | /** |
||
859 | * {@inheritDoc} |
||
860 | */ |
||
861 | public function prefersIdentityColumns() |
||
865 | |||
866 | /** |
||
867 | * {@inheritDoc} |
||
868 | * |
||
869 | * DB2 returns all column names in SQL result sets in uppercase. |
||
870 | */ |
||
871 | public function getSQLResultCasing($column) |
||
875 | |||
876 | /** |
||
877 | * {@inheritDoc} |
||
878 | */ |
||
879 | public function getForUpdateSQL() |
||
883 | |||
884 | /** |
||
885 | * {@inheritDoc} |
||
886 | */ |
||
887 | public function getDummySelectSQL() |
||
893 | |||
894 | /** |
||
895 | * {@inheritDoc} |
||
896 | * |
||
897 | * DB2 supports savepoints, but they work semantically different than on other vendor platforms. |
||
898 | * |
||
899 | * TODO: We have to investigate how to get DB2 up and running with savepoints. |
||
900 | */ |
||
901 | public function supportsSavepoints() |
||
905 | |||
906 | /** |
||
907 | * {@inheritDoc} |
||
908 | */ |
||
909 | protected function getReservedKeywordsClass() |
||
913 | } |
||
914 |
This check looks for
@param
annotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive.
Most often this is a case of a parameter that can be null in addition to its declared types.