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 HackedProject 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 HackedProject, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class HackedProject |
||
19 | { |
||
20 | const STATUS_UNCHECKED = 1; |
||
21 | |||
22 | const STATUS_PERMISSION_DENIED = 2; |
||
23 | |||
24 | const STATUS_HACKED = 3; |
||
25 | |||
26 | const STATUS_DELETED = 4; |
||
27 | |||
28 | const STATUS_UNHACKED = 5; |
||
29 | |||
30 | /** |
||
31 | * @var Project |
||
32 | */ |
||
33 | protected $project; |
||
34 | |||
35 | /** |
||
36 | * @var string |
||
37 | */ |
||
38 | protected $name = ''; |
||
39 | |||
40 | /** |
||
41 | * @var array |
||
42 | */ |
||
43 | protected $project_info = array(); |
||
44 | |||
45 | /** |
||
46 | * @var HackedProjectWebDownloader |
||
47 | */ |
||
48 | protected $remote_files_downloader; |
||
49 | |||
50 | /** |
||
51 | * @var HackedFileGroup |
||
52 | */ |
||
53 | protected $remote_files; |
||
54 | |||
55 | /** |
||
56 | * @var HackedFileGroup |
||
57 | */ |
||
58 | protected $local_files; |
||
59 | |||
60 | /** |
||
61 | * @var string |
||
62 | */ |
||
63 | protected $local_folder; |
||
64 | |||
65 | /** |
||
66 | * @var string |
||
67 | */ |
||
68 | protected $project_type = ''; |
||
69 | |||
70 | /** |
||
71 | * @var string |
||
72 | */ |
||
73 | protected $existing_version = ''; |
||
74 | |||
75 | /** |
||
76 | * @var array |
||
77 | */ |
||
78 | protected $result = array(); |
||
79 | |||
80 | /** |
||
81 | * @var bool |
||
82 | */ |
||
83 | protected $project_identified = false; |
||
84 | |||
85 | /** |
||
86 | * @var bool |
||
87 | */ |
||
88 | protected $remote_downloaded = false; |
||
89 | |||
90 | /** |
||
91 | * @var bool |
||
92 | */ |
||
93 | protected $remote_hashed = false; |
||
94 | |||
95 | /** |
||
96 | * @var bool |
||
97 | */ |
||
98 | protected $local_hashed = false; |
||
99 | |||
100 | /** |
||
101 | * Constructor. |
||
102 | * @param Project $project |
||
103 | * @param string $local_folder |
||
104 | */ |
||
105 | public function __construct(Project $project, $local_folder = null) |
||
115 | |||
116 | /** |
||
117 | * @return Project |
||
118 | */ |
||
119 | public function getProject() |
||
123 | |||
124 | /** |
||
125 | * Get the Human readable title of this project. |
||
126 | */ |
||
127 | public function getTitle() |
||
133 | |||
134 | /** |
||
135 | * Identify the project from the name we've been created with. |
||
136 | * |
||
137 | * We leverage the update (status) module to get the data we require about |
||
138 | * projects. We just pull the information in, and make descisions about this |
||
139 | * project being from CVS or not. |
||
140 | */ |
||
141 | public function identifyProject() |
||
162 | |||
163 | /** |
||
164 | * Downloads the remote project to be hashed later. |
||
165 | */ |
||
166 | public function downloadRemoteProject() |
||
176 | |||
177 | /** |
||
178 | * Hashes the remote project downloaded earlier. |
||
179 | */ |
||
180 | View Code Duplication | public function hashRemoteProject() |
|
202 | |||
203 | /** |
||
204 | * Locate the base directory of the local project. |
||
205 | */ |
||
206 | public function locateLocalProject() |
||
215 | |||
216 | /** |
||
217 | * Hash the local version of the project. |
||
218 | */ |
||
219 | View Code Duplication | public function hashLocalProject() |
|
236 | |||
237 | /** |
||
238 | * Compute the differences between our version and the canonical version of the project. |
||
239 | */ |
||
240 | public function computeDifferences() |
||
268 | |||
269 | /** |
||
270 | * Return a nice report, a simple overview of the status of this project. |
||
271 | */ |
||
272 | public function computeReport() |
||
319 | |||
320 | /** |
||
321 | * Return a nice detailed report. |
||
322 | * @return array |
||
323 | */ |
||
324 | public function computeDetails() |
||
348 | |||
349 | /** |
||
350 | * @param string $file |
||
351 | * |
||
352 | * @return bool |
||
353 | */ |
||
354 | public function fileIsDiffable($file) |
||
361 | |||
362 | /** |
||
363 | * @param string $storage |
||
364 | * @param string $file |
||
365 | * |
||
366 | * @return string|false |
||
367 | */ |
||
368 | public function getFileLocation($storage = 'local', $file) |
||
383 | |||
384 | /** |
||
385 | * @param string $status |
||
386 | * @return string |
||
387 | */ |
||
388 | public static function getStatusLabel($status) |
||
404 | } |
||
405 |
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.