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 Dismissible_Notices_Handler 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 Dismissible_Notices_Handler, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
24 | final class Dismissible_Notices_Handler { |
||
25 | |||
26 | /** |
||
27 | * @var Dismissible_Notices_Handler Holds the unique instance of the handler |
||
28 | * @since 1.0 |
||
29 | */ |
||
30 | private static $instance; |
||
31 | |||
32 | /** |
||
33 | * Library version |
||
34 | * |
||
35 | * @since 1.0 |
||
36 | * @var string |
||
37 | */ |
||
38 | public $version = '1.2.2'; |
||
39 | |||
40 | /** |
||
41 | * Required version of PHP. |
||
42 | * |
||
43 | * @since 1.0 |
||
44 | * @var string |
||
45 | */ |
||
46 | public $php_version_required = '5.5'; |
||
47 | |||
48 | /** |
||
49 | * Minimum version of WordPress required to use the library |
||
50 | * |
||
51 | * @since 1.0 |
||
52 | * @var string |
||
53 | */ |
||
54 | public $wordpress_version_required = '4.7'; |
||
55 | |||
56 | /** |
||
57 | * @var array Holds all our registered notices |
||
58 | * @since 1.0 |
||
59 | */ |
||
60 | private $notices; |
||
61 | |||
62 | /** |
||
63 | * Instantiate and return the unique Dismissible_Notices_Handler object |
||
64 | * |
||
65 | * @since 1.0 |
||
66 | * @return object Dismissible_Notices_Handler Unique instance of the handler |
||
67 | */ |
||
68 | public static function instance() { |
||
78 | |||
79 | /** |
||
80 | * Initialize the library |
||
81 | * |
||
82 | * @since 1.0 |
||
83 | * @return void |
||
84 | */ |
||
85 | private function init() { |
||
118 | |||
119 | /** |
||
120 | * Check if the current WordPress version fits the requirements |
||
121 | * |
||
122 | * @since 1.0 |
||
123 | * @return boolean |
||
124 | */ |
||
125 | private function is_wp_compatible() { |
||
134 | |||
135 | /** |
||
136 | * Check if the version of PHP is compatible with this library |
||
137 | * |
||
138 | * @since 1.0 |
||
139 | * @return boolean |
||
140 | */ |
||
141 | private function is_php_compatible() { |
||
150 | |||
151 | /** |
||
152 | * Load the script |
||
153 | * |
||
154 | * @since 1.0 |
||
155 | * @return void |
||
156 | */ |
||
157 | public function load_script() { |
||
161 | |||
162 | /** |
||
163 | * Display all the registered notices |
||
164 | * |
||
165 | * @since 1.0 |
||
166 | * @return void |
||
167 | */ |
||
168 | public function display() { |
||
200 | |||
201 | /** |
||
202 | * Spits an error message at the top of the admin screen |
||
203 | * |
||
204 | * @since 1.0 |
||
205 | * |
||
206 | * @param string $error Error message to spit |
||
207 | * |
||
208 | * @return void |
||
209 | */ |
||
210 | protected function spit_error( $error ) { |
||
217 | |||
218 | /** |
||
219 | * Sanitize a notice ID and return it |
||
220 | * |
||
221 | * @since 1.0 |
||
222 | * |
||
223 | * @param string $id |
||
224 | * |
||
225 | * @return string |
||
226 | */ |
||
227 | public function get_id( $id ) { |
||
230 | |||
231 | /** |
||
232 | * Get available notice types |
||
233 | * |
||
234 | * @since 1.0 |
||
235 | * @return array |
||
236 | */ |
||
237 | public function get_types() { |
||
252 | |||
253 | /** |
||
254 | * Get the default arguments for a notice |
||
255 | * |
||
256 | * @since 1.0 |
||
257 | * @return array |
||
258 | */ |
||
259 | private function default_args() { |
||
271 | |||
272 | /** |
||
273 | * Register a new notice |
||
274 | * |
||
275 | * @since 1.0 |
||
276 | * |
||
277 | * @param string $id Notice ID, used to identify it |
||
278 | * @param string $type Type of notice to display |
||
279 | * @param string $content Notice content |
||
280 | * @param array $args Additional parameters |
||
281 | * |
||
282 | * @return bool |
||
283 | */ |
||
284 | public function register_notice( $id, $type, $content, $args = array() ) { |
||
320 | |||
321 | /** |
||
322 | * Notice dismissal triggered by Ajax |
||
323 | * |
||
324 | * @since 1.0 |
||
325 | * @return void |
||
326 | */ |
||
327 | public function dismiss_notice_ajax() { |
||
345 | |||
346 | /** |
||
347 | * Dismiss a notice |
||
348 | * |
||
349 | * @since 1.0 |
||
350 | * |
||
351 | * @param string $id ID of the notice to dismiss |
||
352 | * |
||
353 | * @return bool |
||
354 | */ |
||
355 | public function dismiss_notice( $id ) { |
||
370 | |||
371 | /** |
||
372 | * Dismiss notice for the current user |
||
373 | * |
||
374 | * @since 1.0 |
||
375 | * |
||
376 | * @param string $id Notice ID |
||
377 | * |
||
378 | * @return int|bool |
||
379 | */ |
||
380 | private function dismiss_user( $id ) { |
||
393 | |||
394 | /** |
||
395 | * Dismiss notice globally on the site |
||
396 | * |
||
397 | * @since 1.0 |
||
398 | * |
||
399 | * @param string $id Notice ID |
||
400 | * |
||
401 | * @return bool |
||
402 | */ |
||
403 | private function dismiss_global( $id ) { |
||
416 | |||
417 | /** |
||
418 | * Restore a dismissed notice |
||
419 | * |
||
420 | * @since 1.0 |
||
421 | * |
||
422 | * @param string $id ID of the notice to restore |
||
423 | * |
||
424 | * @return bool |
||
425 | */ |
||
426 | public function restore_notice( $id ) { |
||
438 | |||
439 | /** |
||
440 | * Restore a notice dismissed by the current user |
||
441 | * |
||
442 | * @since 1.0 |
||
443 | * |
||
444 | * @param string $id ID of the notice to restore |
||
445 | * |
||
446 | * @return bool |
||
447 | */ |
||
448 | View Code Duplication | private function restore_user( $id ) { |
|
471 | |||
472 | /** |
||
473 | * Restore a notice dismissed globally |
||
474 | * |
||
475 | * @since 1.0 |
||
476 | * |
||
477 | * @param string $id ID of the notice to restore |
||
478 | * |
||
479 | * @return bool |
||
480 | */ |
||
481 | View Code Duplication | private function restore_global( $id ) { |
|
504 | |||
505 | /** |
||
506 | * Get all dismissed notices |
||
507 | * |
||
508 | * This includes notices dismissed globally or per user. |
||
509 | * |
||
510 | * @since 1.0 |
||
511 | * @return array |
||
512 | */ |
||
513 | public function dismissed_notices() { |
||
521 | |||
522 | /** |
||
523 | * Get user dismissed notices |
||
524 | * |
||
525 | * @since 1.0 |
||
526 | * @return array |
||
527 | */ |
||
528 | private function dismissed_user() { |
||
539 | |||
540 | /** |
||
541 | * Get globally dismissed notices |
||
542 | * |
||
543 | * @since 1.0 |
||
544 | * @return array |
||
545 | */ |
||
546 | private function dismissed_global() { |
||
549 | |||
550 | /** |
||
551 | * Check if a notice has been dismissed |
||
552 | * |
||
553 | * @since 1.0 |
||
554 | * |
||
555 | * @param string $id Notice ID |
||
556 | * |
||
557 | * @return bool |
||
558 | */ |
||
559 | public function is_dismissed( $id ) { |
||
570 | |||
571 | /** |
||
572 | * Get all the registered notices |
||
573 | * |
||
574 | * @since 1.0 |
||
575 | * @return array|null |
||
576 | */ |
||
577 | public function get_notices() { |
||
580 | |||
581 | /** |
||
582 | * Return a specific notice |
||
583 | * |
||
584 | * @since 1.0 |
||
585 | * |
||
586 | * @param string $id Notice ID |
||
587 | * |
||
588 | * @return array|false |
||
589 | */ |
||
590 | public function get_notice( $id ) { |
||
601 | |||
602 | } |
||
603 | |||
605 |
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.