Complex classes like CodeDictionary 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 CodeDictionary, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
38 | class CodeDictionary |
||
39 | { |
||
40 | use SingleInstanceTrait; |
||
41 | |||
42 | |||
43 | const COL_CODE = 'code'; |
||
44 | |||
45 | const COL_TITLE = 'title'; |
||
46 | |||
47 | |||
48 | /** |
||
49 | * Columns name, should not be empty |
||
50 | * |
||
51 | * @var array |
||
52 | */ |
||
53 | protected $columns = [self::COL_CODE, self::COL_TITLE]; |
||
54 | |||
55 | /** |
||
56 | * Dictionary data array |
||
57 | * |
||
58 | * @var array |
||
59 | */ |
||
60 | protected $dictionary = []; |
||
61 | |||
62 | /** |
||
63 | * Primary key column name |
||
64 | * |
||
65 | * Primary key column is used to get or search, MUST exist in $column. |
||
66 | * |
||
67 | * @var string |
||
68 | */ |
||
69 | protected $primaryKey = self::COL_CODE; |
||
70 | |||
71 | /** |
||
72 | * Code table name in db |
||
73 | * |
||
74 | * If table name is empty, getSql() will return empty. |
||
75 | * |
||
76 | * @var string |
||
77 | */ |
||
78 | protected $table = 'code_dictionary'; |
||
79 | |||
80 | |||
81 | /** |
||
82 | * Constructor |
||
83 | */ |
||
84 | public function __construct() |
||
99 | |||
100 | |||
101 | /** |
||
102 | * Fix dictionary array index |
||
103 | * |
||
104 | * Use primary key value as index of first dimension, and column name as |
||
105 | * index of second dimension(column value array). |
||
106 | */ |
||
107 | protected function fixDictionaryIndex() |
||
114 | |||
115 | |||
116 | /** |
||
117 | * Get value for given key |
||
118 | * |
||
119 | * If $columns is array, will use directly without parseColumns(). |
||
120 | * |
||
121 | * Child class can simplify this method to improve speed by avoid parse |
||
122 | * columns, get columns data by index. |
||
123 | * |
||
124 | * @param int|string|array $key |
||
125 | * @param string|array $columns |
||
126 | * @return int|string|array |
||
127 | */ |
||
128 | public function get($key, $columns = '') |
||
149 | |||
150 | |||
151 | /** |
||
152 | * Getter of $dictionary |
||
153 | * |
||
154 | * @return array |
||
155 | */ |
||
156 | public function getAll() |
||
160 | |||
161 | |||
162 | /** |
||
163 | * @return array |
||
164 | */ |
||
165 | public function getColumns() |
||
169 | |||
170 | |||
171 | /** |
||
172 | * Get value for given keys |
||
173 | * |
||
174 | * @param array $keys |
||
175 | * @param string|array $columns |
||
176 | * @return array |
||
177 | */ |
||
178 | public function getMultiple(array $keys, $columns = '') |
||
194 | |||
195 | |||
196 | /** |
||
197 | * @return string |
||
198 | */ |
||
199 | public function getPrimaryKey() |
||
203 | |||
204 | |||
205 | /** |
||
206 | * Get key-value map of a single column |
||
207 | * |
||
208 | * The key of result is same, single column value as result value. |
||
209 | * |
||
210 | * @param string $column |
||
211 | * @return array |
||
212 | * @throws InvalidColumnException |
||
213 | */ |
||
214 | public function getSingleColumn($column) |
||
229 | |||
230 | |||
231 | /** |
||
232 | * Get SQL for write dictionary data to db |
||
233 | * |
||
234 | * @param Adodb $dbConn |
||
235 | * @param boolean $withTruncate |
||
236 | * @return string |
||
237 | * @throws \Exception |
||
238 | */ |
||
239 | public function getSql(Adodb $dbConn, $withTruncate = true) |
||
288 | |||
289 | |||
290 | /** |
||
291 | * Get SQL for write dictionary data to db, truncate part. |
||
292 | * |
||
293 | * @param object $dbConn Fwlib\Bridge\Adodb |
||
294 | * @return string |
||
295 | */ |
||
296 | public function getSqlTruncate($dbConn) |
||
308 | |||
309 | |||
310 | /** |
||
311 | * @return string |
||
312 | */ |
||
313 | public function getTable() |
||
317 | |||
318 | |||
319 | /** |
||
320 | * Parse columns you want to query |
||
321 | * |
||
322 | * If $column not assigned, assign as first col which is not primary key. |
||
323 | * |
||
324 | * Use '*' for all columns. |
||
325 | * |
||
326 | * @param string|array $column |
||
327 | * @return array |
||
328 | */ |
||
329 | protected function parseColumns($column = '') |
||
353 | |||
354 | |||
355 | /** |
||
356 | * Search for data fit given condition |
||
357 | * |
||
358 | * $checkMethod is a function take $row as parameter and return boolean |
||
359 | * value, can be anonymous function or other callable. |
||
360 | * |
||
361 | * @param callable $checkMethod |
||
362 | * @param string|array $columns |
||
363 | * @return array |
||
364 | */ |
||
365 | public function search($checkMethod, $columns = '*') |
||
383 | |||
384 | |||
385 | /** |
||
386 | * Set dictionary value |
||
387 | * |
||
388 | * @param array $data 1 or 2-dim data array. |
||
389 | * @return CodeDictionary |
||
390 | * @throws \Exception |
||
391 | */ |
||
392 | public function set(array $data) |
||
440 | |||
441 | |||
442 | /** |
||
443 | * Setter of $columns |
||
444 | * |
||
445 | * @param array $columns |
||
446 | * @return CodeDictionary |
||
447 | */ |
||
448 | public function setColumns(array $columns) |
||
454 | |||
455 | |||
456 | /** |
||
457 | * Setter of $primaryKey |
||
458 | * |
||
459 | * @param string|array $primaryKey |
||
460 | * @return CodeDictionary |
||
461 | */ |
||
462 | public function setPrimaryKey($primaryKey) |
||
468 | |||
469 | |||
470 | /** |
||
471 | * Setter of $table |
||
472 | * |
||
473 | * @param string $table |
||
474 | * @return CodeDictionary |
||
475 | */ |
||
476 | public function setTable($table) |
||
482 | } |
||
483 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.