Complex classes like Card 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 Card, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | abstract class Card |
||
14 | { |
||
15 | /** |
||
16 | * Regular expression for card number recognition. |
||
17 | * |
||
18 | * @var string |
||
19 | */ |
||
20 | public static $pattern; |
||
21 | |||
22 | /** |
||
23 | * Credit card type: "debit", "credit". |
||
24 | * |
||
25 | * @var string |
||
26 | */ |
||
27 | protected $type; |
||
28 | |||
29 | /** |
||
30 | * Credit card name. |
||
31 | * |
||
32 | * @var string |
||
33 | */ |
||
34 | protected $name; |
||
35 | |||
36 | /** |
||
37 | * Card number length's. |
||
38 | * |
||
39 | * @var array |
||
40 | */ |
||
41 | protected $number_length; |
||
42 | |||
43 | /** |
||
44 | * CVC code length's. |
||
45 | * |
||
46 | * @var array |
||
47 | */ |
||
48 | protected $cvc_length; |
||
49 | |||
50 | /** |
||
51 | * Test cvc code checksum against Luhn algorithm. |
||
52 | * |
||
53 | * @var bool |
||
54 | */ |
||
55 | protected $checksum_test; |
||
56 | |||
57 | /** |
||
58 | * @var string |
||
59 | */ |
||
60 | private $card_number; |
||
61 | |||
62 | /** |
||
63 | * Card constructor. |
||
64 | * |
||
65 | * @param string $card_number |
||
66 | * |
||
67 | * @throws \LVR\CreditCard\Exceptions\CreditCardException |
||
68 | */ |
||
69 | 95 | public function __construct(string $card_number = '') |
|
77 | |||
78 | /** |
||
79 | * @param string $card_number |
||
80 | * |
||
81 | * @return $this |
||
82 | * @throws \LVR\CreditCard\Exceptions\CreditCardPatternException |
||
83 | */ |
||
84 | 67 | public function setCardNumber(string $card_number) |
|
98 | |||
99 | /** |
||
100 | * @return bool |
||
101 | * @throws \LVR\CreditCard\Exceptions\CreditCardChecksumException |
||
102 | * @throws \LVR\CreditCard\Exceptions\CreditCardException |
||
103 | * @throws \LVR\CreditCard\Exceptions\CreditCardLengthException |
||
104 | */ |
||
105 | 55 | public function isValidCardNumber() |
|
125 | |||
126 | /** |
||
127 | * @return string |
||
128 | */ |
||
129 | 11 | public function type() |
|
133 | |||
134 | /** |
||
135 | * @param $cvc |
||
136 | * |
||
137 | * @return bool |
||
138 | */ |
||
139 | 1 | public function isValidCvc($cvc) |
|
144 | |||
145 | /** |
||
146 | * Check CVS length against possible lengths. |
||
147 | * |
||
148 | * @param string|int $cvc |
||
149 | * |
||
150 | * @param array $available_lengths |
||
151 | * |
||
152 | * @return bool |
||
153 | */ |
||
154 | 2 | public static function isValidCvcLength($cvc, array $available_lengths = [3, 4]) |
|
160 | |||
161 | /** |
||
162 | * @param string $year |
||
163 | * @param string $month |
||
164 | * |
||
165 | * @return bool |
||
166 | */ |
||
167 | 4 | public static function isValidExpirationDate(string $year, string $month) |
|
190 | |||
191 | /** |
||
192 | * @throws \LVR\CreditCard\Exceptions\CreditCardException |
||
193 | */ |
||
194 | 95 | protected function checkImplementation() |
|
228 | |||
229 | /** |
||
230 | * @return bool |
||
231 | */ |
||
232 | 67 | protected function validPattern() |
|
236 | |||
237 | /** |
||
238 | * @return bool |
||
239 | */ |
||
240 | 44 | protected function validLength() |
|
244 | |||
245 | /** |
||
246 | * @return bool |
||
247 | */ |
||
248 | 33 | protected function validChecksum() |
|
252 | |||
253 | /** |
||
254 | * @return bool |
||
255 | */ |
||
256 | 31 | protected function checksumTest() |
|
275 | } |
||
276 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.