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 LogicalStatement 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 LogicalStatement, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Cornford\Logical; |
||
5 | class LogicalStatement implements LogicalStatementInterface |
||
6 | { |
||
7 | /** |
||
8 | * Array of custom logical statements |
||
9 | * |
||
10 | * @var array |
||
11 | */ |
||
12 | protected $customStatements = []; |
||
13 | |||
14 | /** |
||
15 | * Define a custom logical statement |
||
16 | * |
||
17 | * @param string $name The statement name |
||
18 | * @param callable $callback The callback method to execute |
||
19 | * |
||
20 | * @return void |
||
21 | */ |
||
22 | public function defineCustomStatement($name, callable $callback) |
||
26 | |||
27 | /** |
||
28 | * Checks that a custom logical statement exists |
||
29 | * |
||
30 | * @param string $name The statement name |
||
31 | * |
||
32 | * @return boolean |
||
33 | */ |
||
34 | public function customStatementExists($name) |
||
42 | |||
43 | /** |
||
44 | * Returns all custom logical statements |
||
45 | * |
||
46 | * @return array |
||
47 | */ |
||
48 | public function getCustomStatements() |
||
52 | |||
53 | /** |
||
54 | * Define a custom logical statement |
||
55 | * |
||
56 | * @param string $name The statement name |
||
57 | * @param string|integer|boolean $input The input value |
||
58 | * @param string|integer|boolean $expected The expected type |
||
59 | * |
||
60 | * @return boolean |
||
61 | */ |
||
62 | public function callCustomStatement($name, $input, $expected) |
||
66 | |||
67 | /** |
||
68 | * The input value equals the expected value |
||
69 | * |
||
70 | * @param string $input The input value |
||
71 | * @param string $expected The expected value |
||
72 | * |
||
73 | * @return boolean |
||
74 | */ |
||
75 | public function equals($input, $expected) |
||
83 | |||
84 | /** |
||
85 | * The input value doesn't equal the expected value |
||
86 | * |
||
87 | * @param string $input The input value |
||
88 | * @param string $expected The expected value |
||
89 | * |
||
90 | * @return boolean |
||
91 | */ |
||
92 | public function notEquals($input, $expected) |
||
96 | |||
97 | /** |
||
98 | * The input value has is the same length as the expected value |
||
99 | * |
||
100 | * @param string $input The input value |
||
101 | * @param integer $expected The expected length value |
||
102 | * |
||
103 | * @return boolean |
||
104 | */ |
||
105 | public function isLength($input, $expected) |
||
113 | |||
114 | /** |
||
115 | * The input value isn't the same length as the expected value |
||
116 | * |
||
117 | * @param string $input The input value |
||
118 | * @param integer $expected The expected length value |
||
119 | * |
||
120 | * @return boolean |
||
121 | */ |
||
122 | public function isNotLength($input, $expected) |
||
126 | |||
127 | /** |
||
128 | * The input value is of the expected type |
||
129 | * |
||
130 | * @param string $input The input value |
||
131 | * @param string $expected The expected type |
||
132 | * |
||
133 | * @return boolean |
||
134 | */ |
||
135 | public function is($input, $expected) |
||
147 | |||
148 | /** |
||
149 | * The input value doesn't equal the expected value |
||
150 | * |
||
151 | * @param string $input The input value |
||
152 | * @param string $expected The expected value |
||
153 | * |
||
154 | * @return boolean |
||
155 | */ |
||
156 | public function isNot($input, $expected) |
||
160 | |||
161 | /** |
||
162 | * The input value contains the expected value |
||
163 | * |
||
164 | * @param string $input The input value |
||
165 | * @param string $expected The expected value |
||
166 | * |
||
167 | * @return boolean |
||
168 | */ |
||
169 | public function contains($input, $expected) |
||
177 | |||
178 | /** |
||
179 | * The input value doesn't contain the expected value |
||
180 | * |
||
181 | * @param string $input The input value |
||
182 | * @param string $expected The expected value |
||
183 | * |
||
184 | * @return boolean |
||
185 | */ |
||
186 | public function notContains($input, $expected) |
||
190 | |||
191 | /** |
||
192 | * The input value is contained in the expected value array |
||
193 | * |
||
194 | * @param string $input The input value |
||
195 | * @param array $expected The expected value array |
||
196 | * |
||
197 | * @return boolean |
||
198 | */ |
||
199 | public function containedIn($input, $expected) |
||
209 | |||
210 | /** |
||
211 | * The input value is not contained in the expected value array |
||
212 | * |
||
213 | * @param string $input The input value |
||
214 | * @param array $expected The expected value array |
||
215 | * |
||
216 | * @return boolean |
||
217 | */ |
||
218 | public function notContainedIn($input, $expected) |
||
222 | |||
223 | /** |
||
224 | * The input value is in the expected value array |
||
225 | * |
||
226 | * @param string $input The input value |
||
227 | * @param array $expected The expected value array |
||
228 | * |
||
229 | * @return boolean |
||
230 | */ |
||
231 | public function in($input, $expected) |
||
239 | |||
240 | /** |
||
241 | * The input value is not in the expected value array |
||
242 | * |
||
243 | * @param string $input The input value |
||
244 | * @param array $expected The expected value array |
||
245 | * |
||
246 | * @return boolean |
||
247 | */ |
||
248 | public function notIn($input, $expected) |
||
252 | |||
253 | /** |
||
254 | * The input value is between expected values |
||
255 | * |
||
256 | * @param string $input The input value |
||
257 | * @param array $expected The expected values |
||
258 | * |
||
259 | * @return boolean |
||
260 | */ |
||
261 | public function between($input, $expected) |
||
269 | |||
270 | /** |
||
271 | * The input value is not between the expected values |
||
272 | * |
||
273 | * @param string $input The input value |
||
274 | * @param array $expected The expected values |
||
275 | * |
||
276 | * @return boolean |
||
277 | */ |
||
278 | public function notBetween($input, $expected) |
||
282 | |||
283 | /** |
||
284 | * The input value is null |
||
285 | * |
||
286 | * @param string $input The input value |
||
287 | * |
||
288 | * @return boolean |
||
289 | */ |
||
290 | public function null($input) |
||
298 | |||
299 | /** |
||
300 | * The input value is not null |
||
301 | * |
||
302 | * @param string $input The input value |
||
303 | * |
||
304 | * @return boolean |
||
305 | */ |
||
306 | public function notNull($input) |
||
310 | |||
311 | /** |
||
312 | * The input value is less than the expected value |
||
313 | * |
||
314 | * @param string $input The input value |
||
315 | * @param string $expected The expected value |
||
316 | * |
||
317 | * @return boolean |
||
318 | */ |
||
319 | public function lessThan($input, $expected) |
||
327 | |||
328 | /** |
||
329 | * The input value isn't less than the expected value |
||
330 | * |
||
331 | * @param string $input The input value |
||
332 | * @param string $expected The expected value |
||
333 | * |
||
334 | * @return boolean |
||
335 | */ |
||
336 | public function notLessThan($input, $expected) |
||
340 | |||
341 | /** |
||
342 | * The input value is greater than the expected value |
||
343 | * |
||
344 | * @param string $input The input value |
||
345 | * @param string $expected The expected value |
||
346 | * |
||
347 | * @return boolean |
||
348 | */ |
||
349 | public function greaterThan($input, $expected) |
||
357 | |||
358 | /** |
||
359 | * The input value isn't greater than the expected value |
||
360 | * |
||
361 | * @param string $input The input value |
||
362 | * @param string $expected The expected value |
||
363 | * |
||
364 | * @return boolean |
||
365 | */ |
||
366 | public function notGreaterThan($input, $expected) |
||
370 | |||
371 | /** |
||
372 | * The input value is less than or equal to the expected value |
||
373 | * |
||
374 | * @param string $input The input value |
||
375 | * @param string $expected The expected value |
||
376 | * |
||
377 | * @return boolean |
||
378 | */ |
||
379 | public function lessThanOrEqual($input, $expected) |
||
387 | |||
388 | /** |
||
389 | * The input value isn't less than or equal to the expected value |
||
390 | * |
||
391 | * @param string $input The input value |
||
392 | * @param string $expected The expected value |
||
393 | * |
||
394 | * @return boolean |
||
395 | */ |
||
396 | public function notLessThanOrEqual($input, $expected) |
||
400 | |||
401 | /** |
||
402 | * The input value is greater than or equal to the expected value |
||
403 | * |
||
404 | * @param string $input The input value |
||
405 | * @param string $expected The expected value |
||
406 | * |
||
407 | * @return boolean |
||
408 | */ |
||
409 | public function greaterThanOrEqual($input, $expected) |
||
417 | |||
418 | /** |
||
419 | * The input value isn't greater than or equal to the expected value |
||
420 | * |
||
421 | * @param string $input The input value |
||
422 | * @param string $expected The expected value |
||
423 | * |
||
424 | * @return boolean |
||
425 | */ |
||
426 | public function notGreaterThanOrEqual($input, $expected) |
||
430 | |||
431 | /** |
||
432 | * The input value starts with the expected value |
||
433 | * |
||
434 | * @param string $input The input value |
||
435 | * @param string $expected The expected value |
||
436 | * |
||
437 | * @return boolean |
||
438 | */ |
||
439 | View Code Duplication | public function startsWith($input, $expected) |
|
449 | |||
450 | /** |
||
451 | * The input value doesn't start with the expected value |
||
452 | * |
||
453 | * @param string $input The input value |
||
454 | * @param string $expected The expected value |
||
455 | * |
||
456 | * @return boolean |
||
457 | */ |
||
458 | public function notStartsWith($input, $expected) |
||
462 | |||
463 | /** |
||
464 | * The input value ends with the expected value |
||
465 | * |
||
466 | * @param string $input The input value |
||
467 | * @param string $expected The expected value |
||
468 | * |
||
469 | * @return boolean |
||
470 | */ |
||
471 | View Code Duplication | public function endsWith($input, $expected) |
|
481 | |||
482 | /** |
||
483 | * The input value doesn't end with the expected value |
||
484 | * |
||
485 | * @param string $input The input value |
||
486 | * @param string $expected The expected value |
||
487 | * |
||
488 | * @return boolean |
||
489 | */ |
||
490 | public function notEndsWith($input, $expected) |
||
494 | } |
||
495 |
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.