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 Spec 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 Spec, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
99 | class Spec |
||
100 | { |
||
101 | /** |
||
102 | * @param string $name |
||
103 | * @param array $arguments |
||
104 | * |
||
105 | * @return PlatformFunction |
||
106 | */ |
||
107 | public static function __callStatic($name, array $arguments = []) |
||
119 | |||
120 | /* |
||
121 | * Logic |
||
122 | */ |
||
123 | |||
124 | /** |
||
125 | * @return AndX |
||
126 | */ |
||
127 | View Code Duplication | public static function andX() |
|
141 | |||
142 | /** |
||
143 | * @return OrX |
||
144 | */ |
||
145 | View Code Duplication | public static function orX() |
|
159 | |||
160 | /** |
||
161 | * @param Filter $spec |
||
162 | * |
||
163 | * @return Not |
||
164 | */ |
||
165 | public static function not(Filter $spec) |
||
169 | |||
170 | /* |
||
171 | * Query modifier |
||
172 | */ |
||
173 | |||
174 | /** |
||
175 | * @param string $field |
||
176 | * @param string $newAlias |
||
177 | * @param string|null $dqlAlias |
||
178 | * |
||
179 | * @return Join |
||
180 | */ |
||
181 | public static function join($field, $newAlias, $dqlAlias = null) |
||
185 | |||
186 | /** |
||
187 | * @param string $field |
||
188 | * @param string $newAlias |
||
189 | * @param string|null $dqlAlias |
||
190 | * |
||
191 | * @return LeftJoin |
||
192 | */ |
||
193 | public static function leftJoin($field, $newAlias, $dqlAlias = null) |
||
197 | |||
198 | /** |
||
199 | * @param string $field |
||
200 | * @param string $newAlias |
||
201 | * @param string|null $dqlAlias |
||
202 | * |
||
203 | * @return InnerJoin |
||
204 | */ |
||
205 | public static function innerJoin($field, $newAlias, $dqlAlias = null) |
||
209 | |||
210 | /** |
||
211 | * @param Field|string $field |
||
212 | * @param string|null $dqlAlias |
||
213 | * |
||
214 | * @return IndexBy |
||
215 | */ |
||
216 | public static function indexBy($field, $dqlAlias = null) |
||
220 | |||
221 | /** |
||
222 | * @param int $count |
||
223 | * |
||
224 | * @return Limit |
||
225 | */ |
||
226 | public static function limit($count) |
||
230 | |||
231 | /** |
||
232 | * @param int $count |
||
233 | * |
||
234 | * @return Offset |
||
235 | */ |
||
236 | public static function offset($count) |
||
240 | |||
241 | /** |
||
242 | * @param int $sliceSize |
||
243 | * @param int $sliceNumber |
||
244 | * |
||
245 | * @return Slice |
||
246 | */ |
||
247 | public static function slice($sliceSize, $sliceNumber = 0) |
||
251 | |||
252 | /** |
||
253 | * @param Field|Alias|string $field |
||
254 | * @param string $order |
||
255 | * @param string|null $dqlAlias |
||
256 | * |
||
257 | * @return OrderBy |
||
258 | */ |
||
259 | public static function orderBy($field, $order = 'ASC', $dqlAlias = null) |
||
263 | |||
264 | /** |
||
265 | * @param Field|Alias|string $field |
||
266 | * @param string|null $dqlAlias |
||
267 | * |
||
268 | * @return GroupBy |
||
269 | */ |
||
270 | public static function groupBy($field, $dqlAlias = null) |
||
274 | |||
275 | /** |
||
276 | * @return Distinct |
||
277 | */ |
||
278 | public static function distinct() |
||
282 | |||
283 | /* |
||
284 | * Selection |
||
285 | */ |
||
286 | |||
287 | /** |
||
288 | * @param mixed $field |
||
289 | * |
||
290 | * @return Select |
||
291 | */ |
||
292 | public static function select($field) |
||
297 | |||
298 | /** |
||
299 | * @param mixed $field |
||
300 | * |
||
301 | * @return AddSelect |
||
302 | */ |
||
303 | public static function addSelect($field) |
||
308 | |||
309 | /** |
||
310 | * @param string $dqlAlias |
||
311 | * |
||
312 | * @return SelectEntity |
||
313 | */ |
||
314 | public static function selectEntity($dqlAlias) |
||
318 | |||
319 | /** |
||
320 | * @param Filter|Operand|string $expression |
||
321 | * @param string $alias |
||
322 | * |
||
323 | * @return SelectAs |
||
324 | */ |
||
325 | public static function selectAs($expression, $alias) |
||
329 | |||
330 | /** |
||
331 | * @param Filter|Operand|string $expression |
||
332 | * @param string $alias |
||
333 | * |
||
334 | * @return SelectHiddenAs |
||
335 | */ |
||
336 | public static function selectHiddenAs($expression, $alias) |
||
340 | |||
341 | /* |
||
342 | * Result modifier |
||
343 | */ |
||
344 | |||
345 | /** |
||
346 | * @return AsArray |
||
347 | */ |
||
348 | public static function asArray() |
||
352 | |||
353 | /** |
||
354 | * @return AsSingleScalar |
||
355 | */ |
||
356 | public static function asSingleScalar() |
||
360 | |||
361 | /** |
||
362 | * @return AsScalar |
||
363 | */ |
||
364 | public static function asScalar() |
||
368 | |||
369 | /** |
||
370 | * @param int $cacheLifetime How many seconds the cached entry is valid |
||
371 | * |
||
372 | * @return Cache |
||
373 | */ |
||
374 | public static function cache($cacheLifetime) |
||
378 | |||
379 | /** |
||
380 | * @param int $roundSeconds How may seconds to round time |
||
381 | * |
||
382 | * @return RoundDateTime |
||
383 | */ |
||
384 | public static function roundDateTimeParams($roundSeconds) |
||
388 | |||
389 | /* |
||
390 | * Filters |
||
391 | */ |
||
392 | |||
393 | /** |
||
394 | * @param Operand|string $field |
||
395 | * @param string|null $dqlAlias |
||
396 | * |
||
397 | * @return IsNull |
||
398 | */ |
||
399 | public static function isNull($field, $dqlAlias = null) |
||
403 | |||
404 | /** |
||
405 | * @param Operand|string $field |
||
406 | * @param string|null $dqlAlias |
||
407 | * |
||
408 | * @return IsNotNull |
||
409 | */ |
||
410 | public static function isNotNull($field, $dqlAlias = null) |
||
414 | |||
415 | /** |
||
416 | * Make sure the $field has a value equals to $value. |
||
417 | * |
||
418 | * @param Operand|string $field |
||
419 | * @param Operand|mixed $value |
||
420 | * @param string|null $dqlAlias |
||
421 | * |
||
422 | * @return In |
||
423 | */ |
||
424 | public static function in($field, $value, $dqlAlias = null) |
||
428 | |||
429 | /** |
||
430 | * @param Operand|string $field |
||
431 | * @param Operand|mixed $value |
||
432 | * @param string|null $dqlAlias |
||
433 | * |
||
434 | * @return Not |
||
435 | */ |
||
436 | public static function notIn($field, $value, $dqlAlias = null) |
||
440 | |||
441 | /** |
||
442 | * @param Operand|string $field |
||
443 | * @param Operand|mixed $value |
||
444 | * @param string|null $dqlAlias |
||
445 | * |
||
446 | * @return Comparison |
||
447 | */ |
||
448 | public static function eq($field, $value, $dqlAlias = null) |
||
452 | |||
453 | /** |
||
454 | * @param Operand|string $field |
||
455 | * @param Operand|mixed $value |
||
456 | * @param string|null $dqlAlias |
||
457 | * |
||
458 | * @return Comparison |
||
459 | */ |
||
460 | public static function neq($field, $value, $dqlAlias = null) |
||
464 | |||
465 | /** |
||
466 | * @param Operand|string $field |
||
467 | * @param Operand|mixed $value |
||
468 | * @param string|null $dqlAlias |
||
469 | * |
||
470 | * @return Comparison |
||
471 | */ |
||
472 | public static function lt($field, $value, $dqlAlias = null) |
||
476 | |||
477 | /** |
||
478 | * @param Operand|string $field |
||
479 | * @param Operand|mixed $value |
||
480 | * @param string|null $dqlAlias |
||
481 | * |
||
482 | * @return Comparison |
||
483 | */ |
||
484 | public static function lte($field, $value, $dqlAlias = null) |
||
488 | |||
489 | /** |
||
490 | * @param Operand|string $field |
||
491 | * @param Operand|mixed $value |
||
492 | * @param string|null $dqlAlias |
||
493 | * |
||
494 | * @return Comparison |
||
495 | */ |
||
496 | public static function gt($field, $value, $dqlAlias = null) |
||
500 | |||
501 | /** |
||
502 | * @param Operand|string $field |
||
503 | * @param Operand|mixed $value |
||
504 | * @param string|null $dqlAlias |
||
505 | * |
||
506 | * @return Comparison |
||
507 | */ |
||
508 | public static function gte($field, $value, $dqlAlias = null) |
||
512 | |||
513 | /** |
||
514 | * @param Operand|string $field |
||
515 | * @param LikePattern|string $value |
||
516 | * @param string $format |
||
517 | * @param string|null $dqlAlias |
||
518 | * |
||
519 | * @return Like |
||
520 | */ |
||
521 | public static function like($field, $value, $format = Like::CONTAINS, $dqlAlias = null) |
||
525 | |||
526 | /** |
||
527 | * @param string $value |
||
528 | * @param string|null $dqlAlias |
||
529 | * |
||
530 | * @return InstanceOfX |
||
531 | */ |
||
532 | public static function instanceOfX($value, $dqlAlias = null) |
||
536 | |||
537 | /** |
||
538 | * @param Operand|string $value |
||
539 | * @param Operand|string $field |
||
540 | * @param string|null $dqlAlias |
||
541 | * |
||
542 | * @return MemberOfX |
||
543 | */ |
||
544 | public static function memberOfX($value, $field, $dqlAlias = null) |
||
548 | |||
549 | /* |
||
550 | * Specifications |
||
551 | */ |
||
552 | |||
553 | /** |
||
554 | * @param Filter|QueryModifier $spec |
||
555 | * |
||
556 | * @return CountOf |
||
557 | */ |
||
558 | public static function countOf($spec) |
||
562 | |||
563 | /** |
||
564 | * @param Filter|QueryModifier|string $spec |
||
565 | * |
||
566 | * @return Having |
||
567 | */ |
||
568 | public static function having($spec) |
||
578 | |||
579 | /* |
||
580 | * Operands |
||
581 | */ |
||
582 | |||
583 | /** |
||
584 | * @param string $fieldName |
||
585 | * @param string|null $dqlAlias |
||
586 | * |
||
587 | * @return Field |
||
588 | */ |
||
589 | public static function field($fieldName, $dqlAlias = null) |
||
593 | |||
594 | /** |
||
595 | * @param mixed $value |
||
596 | * @param int|string|null $valueType |
||
597 | * |
||
598 | * @return Value |
||
599 | */ |
||
600 | public static function value($value, $valueType = null) |
||
604 | |||
605 | /** |
||
606 | * @param array $values |
||
607 | * @param int|string|null $valueType |
||
608 | * |
||
609 | * @return Values |
||
610 | */ |
||
611 | public static function values($values, $valueType = null) |
||
615 | |||
616 | /** |
||
617 | * @param string $value |
||
618 | * @param string $format |
||
619 | * |
||
620 | * @return LikePattern |
||
621 | */ |
||
622 | public static function likePattern($value, $format = LikePattern::CONTAINS) |
||
626 | |||
627 | /** |
||
628 | * @param Operand|string $field |
||
629 | * |
||
630 | * @return CountDistinct |
||
631 | */ |
||
632 | public static function countDistinct($field) |
||
636 | |||
637 | /* |
||
638 | * Arithmetic operands |
||
639 | */ |
||
640 | |||
641 | /** |
||
642 | * @param Operand|string $field |
||
643 | * @param Operand|mixed $value |
||
644 | * |
||
645 | * @return Addition |
||
646 | */ |
||
647 | public static function add($field, $value) |
||
651 | |||
652 | /** |
||
653 | * @param Operand|string $field |
||
654 | * @param Operand|mixed $value |
||
655 | * |
||
656 | * @return Subtraction |
||
657 | */ |
||
658 | public static function sub($field, $value) |
||
662 | |||
663 | /** |
||
664 | * @param Operand|string $field |
||
665 | * @param Operand|mixed $value |
||
666 | * |
||
667 | * @return Multiplication |
||
668 | */ |
||
669 | public static function mul($field, $value) |
||
673 | |||
674 | /** |
||
675 | * @param Operand|string $field |
||
676 | * @param Operand|mixed $value |
||
677 | * |
||
678 | * @return Division |
||
679 | */ |
||
680 | public static function div($field, $value) |
||
684 | |||
685 | /** |
||
686 | * @deprecated This method is deprecated since version 1.1 and will be removed in 2.0, use Spec::MOD() instead. |
||
687 | * |
||
688 | * @param Operand|string $field |
||
689 | * @param Operand|mixed $value |
||
690 | * |
||
691 | * @return Modulo |
||
692 | */ |
||
693 | public static function mod($field, $value) |
||
697 | |||
698 | /* |
||
699 | * Bitwise operands |
||
700 | */ |
||
701 | |||
702 | /** |
||
703 | * @deprecated This method is deprecated since version 1.1 and will be removed in 2.0, use "Spec::BIT_AND($a, $b)" instead. |
||
704 | * |
||
705 | * @param Operand|string $field |
||
706 | * @param Operand|mixed $value |
||
707 | * |
||
708 | * @return BitAnd |
||
709 | */ |
||
710 | public static function bAnd($field, $value) |
||
714 | |||
715 | /** |
||
716 | * @deprecated This method is deprecated since version 1.1 and will be removed in 2.0, use "Spec::BIT_OR($a, $b)" instead. |
||
717 | * |
||
718 | * @param Operand|string $field |
||
719 | * @param Operand|mixed $value |
||
720 | * |
||
721 | * @return BitOr |
||
722 | */ |
||
723 | public static function bOr($field, $value) |
||
727 | |||
728 | /** |
||
729 | * @deprecated This method is deprecated since version 1.1 and will be removed in 2.0. |
||
730 | * |
||
731 | * @param Operand|string $field |
||
732 | * @param Operand|mixed $value |
||
733 | * |
||
734 | * @return BitXor |
||
735 | */ |
||
736 | public static function bXor($field, $value) |
||
740 | |||
741 | /** |
||
742 | * @deprecated This method is deprecated since version 1.1 and will be removed in 2.0. |
||
743 | * |
||
744 | * @param Operand|string $field |
||
745 | * @param Operand|mixed $value |
||
746 | * |
||
747 | * @return BitLeftShift |
||
748 | */ |
||
749 | public static function bLs($field, $value) |
||
753 | |||
754 | /** |
||
755 | * @deprecated This method is deprecated since version 1.1 and will be removed in 2.0. |
||
756 | * |
||
757 | * @param Operand|string $field |
||
758 | * @param Operand|mixed $value |
||
759 | * |
||
760 | * @return BitRightShift |
||
761 | */ |
||
762 | public static function bRs($field, $value) |
||
766 | |||
767 | /** |
||
768 | * @deprecated This method is deprecated since version 1.1 and will be removed in 2.0. |
||
769 | * |
||
770 | * @param Operand|string $field |
||
771 | * |
||
772 | * @return BitNot |
||
773 | */ |
||
774 | public static function bNot($field) |
||
778 | |||
779 | /** |
||
780 | * Call DQL function. |
||
781 | * |
||
782 | * Usage: |
||
783 | * Spec::fun('CURRENT_DATE') |
||
784 | * Spec::fun('DATE_DIFF', $date1, $date2) |
||
785 | * Spec::fun('DATE_DIFF', [$date1, $date2]) |
||
786 | * |
||
787 | * @param string $functionName |
||
788 | * @param mixed $arguments |
||
789 | * |
||
790 | * @return PlatformFunction |
||
791 | */ |
||
792 | public static function fun($functionName, $arguments = []) |
||
804 | |||
805 | /** |
||
806 | * @param string $alias |
||
807 | * |
||
808 | * @return Alias |
||
809 | */ |
||
810 | public static function alias($alias) |
||
814 | } |
||
815 |
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.