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 TBSCertificate 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 TBSCertificate, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | class TBSCertificate |
||
28 | { |
||
29 | // Certificate version enumerations |
||
30 | const VERSION_1 = 0; |
||
31 | const VERSION_2 = 1; |
||
32 | const VERSION_3 = 2; |
||
33 | |||
34 | /** |
||
35 | * Certificate version. |
||
36 | * |
||
37 | * @var int |
||
38 | */ |
||
39 | protected $_version; |
||
40 | |||
41 | /** |
||
42 | * Serial number. |
||
43 | * |
||
44 | * @var int|string |
||
45 | */ |
||
46 | protected $_serialNumber; |
||
47 | |||
48 | /** |
||
49 | * Signature algorithm. |
||
50 | * |
||
51 | * @var SignatureAlgorithmIdentifier |
||
52 | */ |
||
53 | protected $_signature; |
||
54 | |||
55 | /** |
||
56 | * Certificate issuer. |
||
57 | * |
||
58 | * @var Name $_issuer |
||
59 | */ |
||
60 | protected $_issuer; |
||
61 | |||
62 | /** |
||
63 | * Certificate validity period. |
||
64 | * |
||
65 | * @var Validity $_validity |
||
66 | */ |
||
67 | protected $_validity; |
||
68 | |||
69 | /** |
||
70 | * Certificate subject. |
||
71 | * |
||
72 | * @var Name $_subject |
||
73 | */ |
||
74 | protected $_subject; |
||
75 | |||
76 | /** |
||
77 | * Subject public key. |
||
78 | * |
||
79 | * @var PublicKeyInfo $_subjectPublicKeyInfo |
||
80 | */ |
||
81 | protected $_subjectPublicKeyInfo; |
||
82 | |||
83 | /** |
||
84 | * Issuer unique identifier. |
||
85 | * |
||
86 | * @var UniqueIdentifier|null $_issuerUniqueID |
||
87 | */ |
||
88 | protected $_issuerUniqueID; |
||
89 | |||
90 | /** |
||
91 | * Subject unique identifier. |
||
92 | * |
||
93 | * @var UniqueIdentifier|null $_subjectUniqueID |
||
94 | */ |
||
95 | protected $_subjectUniqueID; |
||
96 | |||
97 | /** |
||
98 | * Extensions. |
||
99 | * |
||
100 | * @var Extensions $_extensions |
||
101 | */ |
||
102 | protected $_extensions; |
||
103 | |||
104 | /** |
||
105 | * Constructor |
||
106 | * |
||
107 | * @param Name $subject Certificate subject |
||
108 | * @param PublicKeyInfo $pki Subject public key |
||
109 | * @param Name $issuer Certificate issuer |
||
110 | * @param Validity $validity Validity period |
||
111 | */ |
||
112 | 18 | public function __construct(Name $subject, PublicKeyInfo $pki, Name $issuer, |
|
120 | |||
121 | /** |
||
122 | * Initialize from ASN.1. |
||
123 | * |
||
124 | * @param Sequence $seq |
||
125 | * @return self |
||
126 | */ |
||
127 | 12 | public static function fromASN1(Sequence $seq) { |
|
175 | |||
176 | /** |
||
177 | * Initialize from certification request. |
||
178 | * |
||
179 | * Note that signature is not verified and must be done by the caller. |
||
180 | * |
||
181 | * @param CertificationRequest $cr |
||
182 | * @return self |
||
183 | */ |
||
184 | 1 | public static function fromCSR(CertificationRequest $cr) { |
|
204 | |||
205 | /** |
||
206 | * Get self with fields set from the issuer's certificate. |
||
207 | * |
||
208 | * Issuer shall be set to issuing certificate's subject. |
||
209 | * Authority key identifier extensions shall be added with a key identifier |
||
210 | * set to issuing certificate's public key identifier. |
||
211 | * |
||
212 | * @param Certificate $cert Issuing party's certificate |
||
213 | * @return self |
||
214 | */ |
||
215 | 1 | public function withIssuerCertificate(Certificate $cert) { |
|
227 | |||
228 | /** |
||
229 | * Get self with given version. |
||
230 | * |
||
231 | * If version is not set, appropriate version is automatically |
||
232 | * determined during signing. |
||
233 | * |
||
234 | * @param int $version |
||
235 | * @return self |
||
236 | */ |
||
237 | 4 | public function withVersion($version) { |
|
242 | |||
243 | /** |
||
244 | * Get self with given serial number. |
||
245 | * |
||
246 | * @param int|string $serial Base 10 number |
||
247 | * @return self |
||
248 | */ |
||
249 | 5 | public function withSerialNumber($serial) { |
|
254 | |||
255 | /** |
||
256 | * Get self with random positive serial number. |
||
257 | * |
||
258 | * @param int $size Number of random bytes |
||
259 | * @return self |
||
260 | */ |
||
261 | 1 | View Code Duplication | public function withRandomSerialNumber($size = 16) { |
270 | |||
271 | /** |
||
272 | * Get self with given signature algorithm. |
||
273 | * |
||
274 | * @param SignatureAlgorithmIdentifier $algo |
||
275 | * @return self |
||
276 | */ |
||
277 | 4 | public function withSignature(SignatureAlgorithmIdentifier $algo) { |
|
282 | |||
283 | /** |
||
284 | * Get self with given issuer. |
||
285 | * |
||
286 | * @param Name $issuer |
||
287 | * @return self |
||
288 | */ |
||
289 | 1 | public function withIssuer(Name $issuer) { |
|
294 | |||
295 | /** |
||
296 | * Get self with given validity. |
||
297 | * |
||
298 | * @param Validity $validity |
||
299 | * @return self |
||
300 | */ |
||
301 | 2 | public function withValidity(Validity $validity) { |
|
306 | |||
307 | /** |
||
308 | * Get self with given subject. |
||
309 | * |
||
310 | * @param Name $subject |
||
311 | * @return self |
||
312 | */ |
||
313 | 1 | public function withSubject(Name $subject) { |
|
318 | |||
319 | /** |
||
320 | * Get self with given subject public key info. |
||
321 | * |
||
322 | * @param PublicKeyInfo $pub_key_info |
||
323 | * @return self |
||
324 | */ |
||
325 | 1 | public function withSubjectPublicKeyInfo(PublicKeyInfo $pub_key_info) { |
|
330 | |||
331 | /** |
||
332 | * Get self with issuer unique ID. |
||
333 | * |
||
334 | * @param UniqueIdentifier $id |
||
335 | * @return self |
||
336 | */ |
||
337 | 4 | public function withIssuerUniqueID(UniqueIdentifier $id) { |
|
342 | |||
343 | /** |
||
344 | * Get self with subject unique ID. |
||
345 | * |
||
346 | * @param UniqueIdentifier $id |
||
347 | * @return self |
||
348 | */ |
||
349 | 4 | public function withSubjectUniqueID(UniqueIdentifier $id) { |
|
354 | |||
355 | /** |
||
356 | * Get self with given extensions. |
||
357 | * |
||
358 | * @param Extensions $extensions |
||
359 | * @return self |
||
360 | */ |
||
361 | 4 | public function withExtensions(Extensions $extensions) { |
|
366 | |||
367 | /** |
||
368 | * Get self with extensions added. |
||
369 | * |
||
370 | * @param Extension ...$exts One or more Extension objects |
||
371 | * @return self |
||
372 | */ |
||
373 | 3 | public function withAdditionalExtensions(Extension ...$exts) { |
|
378 | |||
379 | /** |
||
380 | * Check whether version is set. |
||
381 | * |
||
382 | * @return bool |
||
383 | */ |
||
384 | 41 | public function hasVersion() { |
|
387 | |||
388 | /** |
||
389 | * Get certificate version. |
||
390 | * |
||
391 | * @return int |
||
392 | */ |
||
393 | 41 | public function version() { |
|
399 | |||
400 | /** |
||
401 | * Check whether serial number is set. |
||
402 | * |
||
403 | * @return bool |
||
404 | */ |
||
405 | 44 | public function hasSerialNumber() { |
|
408 | |||
409 | /** |
||
410 | * Get serial number. |
||
411 | * |
||
412 | * @return int|string Base 10 integer |
||
413 | */ |
||
414 | 44 | public function serialNumber() { |
|
420 | |||
421 | /** |
||
422 | * Check whether signature algorithm is set. |
||
423 | * |
||
424 | * @return bool |
||
425 | */ |
||
426 | 41 | public function hasSignature() { |
|
429 | |||
430 | /** |
||
431 | * Get signature algorithm. |
||
432 | * |
||
433 | * @return SignatureAlgorithmIdentifier |
||
434 | */ |
||
435 | 41 | public function signature() { |
|
441 | |||
442 | /** |
||
443 | * Get issuer. |
||
444 | * |
||
445 | * @return Name |
||
446 | */ |
||
447 | 37 | public function issuer() { |
|
450 | |||
451 | /** |
||
452 | * Get validity period. |
||
453 | * |
||
454 | * @return Validity |
||
455 | */ |
||
456 | 25 | public function validity() { |
|
459 | |||
460 | /** |
||
461 | * Get subject. |
||
462 | * |
||
463 | * @return Name |
||
464 | */ |
||
465 | 36 | public function subject() { |
|
468 | |||
469 | /** |
||
470 | * Get subject public key. |
||
471 | * |
||
472 | * @return PublicKeyInfo |
||
473 | */ |
||
474 | 31 | public function subjectPublicKeyInfo() { |
|
477 | |||
478 | /** |
||
479 | * Whether issuer unique identifier is present. |
||
480 | * |
||
481 | * @return bool |
||
482 | */ |
||
483 | 3 | public function hasIssuerUniqueID() { |
|
486 | |||
487 | /** |
||
488 | * Get issuerUniqueID. |
||
489 | * |
||
490 | * @return UniqueIdentifier |
||
491 | */ |
||
492 | 2 | public function issuerUniqueID() { |
|
498 | |||
499 | /** |
||
500 | * Whether subject unique identifier is present. |
||
501 | * |
||
502 | * @return bool |
||
503 | */ |
||
504 | 2 | public function hasSubjectUniqueID() { |
|
507 | |||
508 | /** |
||
509 | * Get subjectUniqueID. |
||
510 | * |
||
511 | * @return UniqueIdentifier |
||
512 | */ |
||
513 | 2 | public function subjectUniqueID() { |
|
519 | |||
520 | /** |
||
521 | * Get extensions. |
||
522 | * |
||
523 | * @return Extensions |
||
524 | */ |
||
525 | 35 | public function extensions() { |
|
528 | |||
529 | /** |
||
530 | * Generate ASN.1 structure. |
||
531 | * |
||
532 | * @return Sequence |
||
533 | */ |
||
534 | 38 | public function toASN1() { |
|
561 | |||
562 | /** |
||
563 | * Create signed certificate. |
||
564 | * |
||
565 | * @param Crypto $crypto Crypto engine |
||
566 | * @param SignatureAlgorithmIdentifier $algo Algorithm used for signing |
||
567 | * @param PrivateKeyInfo $privkey_info Private key used for signing |
||
568 | * @return Certificate |
||
569 | */ |
||
570 | 9 | public function sign(Crypto $crypto, SignatureAlgorithmIdentifier $algo, |
|
584 | |||
585 | /** |
||
586 | * Determine minimum version for the certificate. |
||
587 | * |
||
588 | * @return int |
||
589 | */ |
||
590 | 9 | protected function _determineVersion() { |
|
601 | } |
||
602 |
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.