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 PrintSetup 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 PrintSetup, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
11 | class PrintSetup |
||
12 | { |
||
13 | const ORIENTATION_PORTRAIT = 1; |
||
14 | const ORIENTATION_LANDSCAPE = 0; |
||
15 | |||
16 | const PAPER_CUSTOM = 0; |
||
17 | const PAPER_US_LETTER = 1; |
||
18 | const PAPER_A3 = 8; |
||
19 | const PAPER_A4 = 9; |
||
20 | const PAPER_A5 = 11; |
||
21 | |||
22 | /** |
||
23 | * The paper size |
||
24 | * |
||
25 | * @var integer |
||
26 | */ |
||
27 | protected $paperSize = self::PAPER_CUSTOM; |
||
28 | |||
29 | /** |
||
30 | * Bit specifying paper orientation (for printing). 0 => landscape, 1 => portrait |
||
31 | * |
||
32 | * @var integer |
||
33 | */ |
||
34 | protected $orientation = self::ORIENTATION_PORTRAIT; |
||
35 | |||
36 | /** |
||
37 | * @var Range |
||
38 | */ |
||
39 | protected $printRepeat; |
||
40 | |||
41 | /** |
||
42 | * @var null|Range |
||
43 | */ |
||
44 | protected $printArea = null; |
||
45 | |||
46 | /** |
||
47 | * @var float |
||
48 | */ |
||
49 | protected $printScale = 100; |
||
50 | |||
51 | /** |
||
52 | * Whether to fit to page when printing or not. |
||
53 | * |
||
54 | * @var bool |
||
55 | */ |
||
56 | protected $fitPage = false; |
||
57 | |||
58 | /** |
||
59 | * Number of pages to fit wide |
||
60 | * |
||
61 | * @var integer |
||
62 | */ |
||
63 | protected $fitWidth = 0; |
||
64 | |||
65 | /** |
||
66 | * Number of pages to fit high |
||
67 | * |
||
68 | * @var integer |
||
69 | */ |
||
70 | protected $fitHeight = 0; |
||
71 | |||
72 | /** |
||
73 | * The page header caption |
||
74 | * |
||
75 | * @var string |
||
76 | */ |
||
77 | protected $header = ''; |
||
78 | |||
79 | /** |
||
80 | * The page footer caption |
||
81 | * |
||
82 | * @var string |
||
83 | */ |
||
84 | protected $footer = ''; |
||
85 | |||
86 | /** |
||
87 | * The horizontal centering value for the page |
||
88 | * |
||
89 | * @var bool |
||
90 | */ |
||
91 | protected $hcenter = false; |
||
92 | |||
93 | /** |
||
94 | * The vertical centering value for the page |
||
95 | * |
||
96 | * @var bool |
||
97 | */ |
||
98 | protected $vcenter = false; |
||
99 | |||
100 | /** |
||
101 | * @var Margin |
||
102 | */ |
||
103 | protected $margin; |
||
104 | |||
105 | protected $printRowColHeaders = false; |
||
106 | protected $hbreaks = array(); |
||
107 | protected $vbreaks = array(); |
||
108 | protected $printGridLines = true; |
||
109 | |||
110 | /** |
||
111 | * |
||
112 | */ |
||
113 | public function __construct() |
||
120 | |||
121 | /** |
||
122 | * @return bool |
||
123 | */ |
||
124 | public function isPrintAreaSet() |
||
128 | |||
129 | /** |
||
130 | * @return null|Range |
||
131 | */ |
||
132 | public function getPrintArea() |
||
136 | |||
137 | /** |
||
138 | * Set the area of each worksheet that will be printed. |
||
139 | * |
||
140 | * @param integer $firstRow First row of the area to print |
||
141 | * @param integer $firstCol First column of the area to print |
||
142 | * @param integer $lastRow Last row of the area to print |
||
143 | * @param integer $lastCol Last column of the area to print |
||
144 | * |
||
145 | * @return PrintSetup |
||
146 | */ |
||
147 | public function setPrintArea($firstRow, $firstCol, $lastRow, $lastCol) |
||
153 | |||
154 | /** |
||
155 | * Set the rows to repeat at the top of each printed page. |
||
156 | * |
||
157 | * @param integer $firstRow First row to repeat |
||
158 | * @param integer $lastRow Last row to repeat. Optional. |
||
159 | * |
||
160 | * @return PrintSetup |
||
161 | */ |
||
162 | View Code Duplication | public function printRepeatRows($firstRow, $lastRow = null) |
|
182 | |||
183 | /** |
||
184 | * Set the columns to repeat at the left hand side of each printed page. |
||
185 | * |
||
186 | * @param integer $firstCol First column to repeat |
||
187 | * @param integer $lastCol Last column to repeat. Optional. |
||
188 | * |
||
189 | * @return PrintSetup |
||
190 | */ |
||
191 | View Code Duplication | public function printRepeatColumns($firstCol, $lastCol = null) |
|
211 | |||
212 | /** |
||
213 | * @return Range |
||
214 | */ |
||
215 | public function getPrintRepeat() |
||
219 | |||
220 | /** |
||
221 | * Set the scale factor for the printed page. |
||
222 | * It turns off the "fit to page" option |
||
223 | * |
||
224 | * @param integer $scale The optional scale factor. Defaults to 100 |
||
225 | * |
||
226 | * @throws \Exception |
||
227 | * @return PrintSetup |
||
228 | */ |
||
229 | public function setPrintScale($scale = 100) |
||
243 | |||
244 | /** |
||
245 | * @return float |
||
246 | */ |
||
247 | public function getPrintScale() |
||
251 | |||
252 | /** |
||
253 | * Set the paper type |
||
254 | * |
||
255 | * @param integer $size The type of paper size to use |
||
256 | * |
||
257 | * @return PrintSetup |
||
258 | */ |
||
259 | public function setPaper($size = self::PAPER_CUSTOM) |
||
265 | |||
266 | /** |
||
267 | * Set the page orientation as portrait. |
||
268 | * |
||
269 | * @return PrintSetup |
||
270 | */ |
||
271 | public function setPortrait() |
||
277 | |||
278 | /** |
||
279 | * Set the page orientation as landscape. |
||
280 | * |
||
281 | * @return PrintSetup |
||
282 | */ |
||
283 | public function setLandscape() |
||
289 | |||
290 | /** |
||
291 | * @return int |
||
292 | */ |
||
293 | public function getOrientation() |
||
297 | |||
298 | /** |
||
299 | * @return int |
||
300 | */ |
||
301 | public function getPaperSize() |
||
305 | |||
306 | /** |
||
307 | * @return int |
||
308 | */ |
||
309 | public function getFitWidth() |
||
313 | |||
314 | /** |
||
315 | * @return int |
||
316 | */ |
||
317 | public function getFitHeight() |
||
321 | |||
322 | /** |
||
323 | * @return boolean |
||
324 | */ |
||
325 | public function isFitPage() |
||
329 | |||
330 | /** |
||
331 | * Set the vertical and horizontal number of pages that will define the maximum area printed. |
||
332 | * It doesn't seem to work with OpenOffice. |
||
333 | * |
||
334 | * @param integer $width Maximun width of printed area in pages |
||
335 | * @param integer $height Maximun heigth of printed area in pages |
||
336 | * |
||
337 | * @return PrintSetup |
||
338 | */ |
||
339 | public function fitToPages($width, $height) |
||
347 | |||
348 | /** |
||
349 | * Set the page header caption and optional margin. |
||
350 | * |
||
351 | * @param string $string The header text |
||
352 | * @param float $margin optional head margin in inches. |
||
353 | * |
||
354 | * @return PrintSetup |
||
355 | */ |
||
356 | public function setHeader($string, $margin = 0.50) |
||
363 | |||
364 | /** |
||
365 | * Set the page footer caption and optional margin. |
||
366 | * |
||
367 | * @param string $string The footer text |
||
368 | * @param float $margin optional foot margin in inches. |
||
369 | * |
||
370 | * @return PrintSetup |
||
371 | */ |
||
372 | public function setFooter($string, $margin = 0.50) |
||
379 | |||
380 | /** |
||
381 | * @param $string |
||
382 | * |
||
383 | * @return string |
||
384 | */ |
||
385 | protected function truncateStringIfNeeded($string) |
||
393 | |||
394 | /** |
||
395 | * Center the page horinzontally. |
||
396 | * |
||
397 | * @param bool $enable the optional value for centering. Defaults to 1 (center). |
||
398 | * |
||
399 | * @return PrintSetup |
||
400 | */ |
||
401 | public function centerHorizontally($enable = true) |
||
407 | |||
408 | /** |
||
409 | * Center the page vertically. |
||
410 | * |
||
411 | * @param bool $enable the optional value for centering. Defaults to 1 (center). |
||
412 | * |
||
413 | * @return PrintSetup |
||
414 | */ |
||
415 | public function centerVertically($enable = true) |
||
421 | |||
422 | /** |
||
423 | * Set the option to print the row and column headers on the printed page. |
||
424 | * |
||
425 | * @param bool $print Whether to print the headers or not. Defaults to 1 (print). |
||
426 | * |
||
427 | * @return PrintSetup |
||
428 | */ |
||
429 | public function printRowColHeaders($print = true) |
||
435 | |||
436 | /** |
||
437 | * Store the horizontal page breaks on a worksheet (for printing). |
||
438 | * The breaks represent the row after which the break is inserted. |
||
439 | * |
||
440 | * @param array $breaks Array containing the horizontal page breaks |
||
441 | * |
||
442 | * @return PrintSetup |
||
443 | */ |
||
444 | public function setHPagebreaks($breaks) |
||
452 | |||
453 | /** |
||
454 | * Store the vertical page breaks on a worksheet (for printing). |
||
455 | * The breaks represent the column after which the break is inserted. |
||
456 | * |
||
457 | * @param array $breaks Array containing the vertical page breaks |
||
458 | * |
||
459 | * @return PrintSetup |
||
460 | */ |
||
461 | public function setVPagebreaks($breaks) |
||
469 | |||
470 | /** |
||
471 | * Set the option to hide gridlines on the printed page. |
||
472 | * |
||
473 | * @param bool $enable |
||
474 | * |
||
475 | * @return PrintSetup |
||
476 | */ |
||
477 | public function printGridlines($enable = true) |
||
483 | |||
484 | /** |
||
485 | * @return bool |
||
486 | */ |
||
487 | public function shouldPrintRowColHeaders() |
||
491 | |||
492 | /** |
||
493 | * @return array |
||
494 | */ |
||
495 | public function getHbreaks() |
||
499 | |||
500 | /** |
||
501 | * @return array |
||
502 | */ |
||
503 | public function getVbreaks() |
||
507 | |||
508 | /** |
||
509 | * @return string |
||
510 | */ |
||
511 | public function getHeader() |
||
515 | |||
516 | /** |
||
517 | * @return string |
||
518 | */ |
||
519 | public function getFooter() |
||
523 | |||
524 | /** |
||
525 | * @return bool |
||
526 | */ |
||
527 | public function isHcenteringOn() |
||
531 | |||
532 | /** |
||
533 | * @return bool |
||
534 | */ |
||
535 | public function isVcenteringOn() |
||
539 | |||
540 | /** |
||
541 | * @return bool |
||
542 | */ |
||
543 | public function shouldPrintGridLines() |
||
547 | |||
548 | /** |
||
549 | * @return Margin |
||
550 | */ |
||
551 | public function getMargin() |
||
555 | } |
||
556 |
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.