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 Image_Transform_Driver_GD 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 Image_Transform_Driver_GD, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
65 | class Image_Transform_Driver_GD extends Image_Transform |
||
66 | { |
||
67 | /** |
||
68 | * Holds the image resource for manipulation |
||
69 | * |
||
70 | * @var resource $imageHandle |
||
71 | * @access protected |
||
72 | */ |
||
73 | var $imageHandle = null; |
||
74 | |||
75 | /** |
||
76 | * Holds the original image file |
||
77 | * |
||
78 | * @var resource $imageHandle |
||
79 | * @access protected |
||
80 | */ |
||
81 | var $oldImage = null; |
||
82 | |||
83 | /** |
||
84 | * Check settings |
||
85 | */ |
||
86 | function Image_Transform_Driver_GD() |
||
90 | |||
91 | /** |
||
92 | * Check settings |
||
93 | * |
||
94 | * @since PHP 5 |
||
95 | */ |
||
96 | function __construct() |
||
124 | |||
125 | /** |
||
126 | * Loads an image from file |
||
127 | * |
||
128 | * @param string $image filename |
||
129 | * @return bool|PEAR_Error TRUE or a PEAR_Error object on error |
||
130 | * @access public |
||
131 | */ |
||
132 | function load($image) |
||
156 | |||
157 | /** |
||
158 | * Returns the GD image handle |
||
159 | * |
||
160 | * @return resource |
||
161 | * |
||
162 | * @access public |
||
163 | */ |
||
164 | function getHandle() |
||
168 | |||
169 | /** |
||
170 | * Adds a border of constant width around an image |
||
171 | * |
||
172 | * @param int $border_width Width of border to add |
||
173 | * @author Peter Bowyer |
||
174 | * @return bool TRUE |
||
175 | * @access public |
||
176 | */ |
||
177 | function addBorder($border_width, $color = '') |
||
200 | |||
201 | /** |
||
202 | * addText |
||
203 | * |
||
204 | * @param array $params Array contains options |
||
205 | * array( |
||
206 | * 'text' The string to draw |
||
207 | * 'x' Horizontal position |
||
208 | * 'y' Vertical Position |
||
209 | * 'color' Font color |
||
210 | * 'font' Font to be used |
||
211 | * 'size' Size of the fonts in pixel |
||
212 | * 'resize_first' Tell if the image has to be resized |
||
213 | * before drawing the text |
||
214 | * ) |
||
215 | * |
||
216 | * @return bool|PEAR_Error TRUE or a PEAR_Error object on error |
||
217 | */ |
||
218 | function addText($params) |
||
237 | |||
238 | /** |
||
239 | * Rotates image by the given angle |
||
240 | * |
||
241 | * Uses a fast rotation algorythm for custom angles |
||
242 | * or lines copy for multiple of 90 degrees |
||
243 | * |
||
244 | * @param int $angle Rotation angle |
||
245 | * @param array $options array( |
||
246 | * 'canvasColor' => array(r ,g, b), named color or #rrggbb |
||
247 | * ) |
||
248 | * @author Pierre-Alain Joye |
||
249 | * @return bool|PEAR_Error TRUE or a PEAR_Error object on error |
||
250 | * @access public |
||
251 | */ |
||
252 | function rotate($angle, $options = null) |
||
269 | |||
270 | /** |
||
271 | * Horizontal mirroring |
||
272 | * |
||
273 | * @return mixed TRUE or PEAR_Error object on error |
||
274 | * @access public |
||
275 | * @see flip() |
||
276 | **/ |
||
277 | View Code Duplication | function mirror() |
|
288 | |||
289 | /** |
||
290 | * Vertical mirroring |
||
291 | * |
||
292 | * @return TRUE or PEAR Error object on error |
||
293 | * @access public |
||
294 | * @see mirror() |
||
295 | **/ |
||
296 | View Code Duplication | function flip() |
|
319 | |||
320 | /** |
||
321 | * Crops image by size and start coordinates |
||
322 | * |
||
323 | * @param int width Cropped image width |
||
324 | * @param int height Cropped image height |
||
325 | * @param int x X-coordinate to crop at |
||
326 | * @param int y Y-coordinate to crop at |
||
327 | * @return bool|PEAR_Error TRUE or a PEAR_Error object on error |
||
328 | * @access public |
||
329 | */ |
||
330 | function crop($width, $height, $x = 0, $y = 0) |
||
356 | |||
357 | /** |
||
358 | * Converts the image to greyscale |
||
359 | * |
||
360 | * @return bool|PEAR_Error TRUE or a PEAR_Error object on error |
||
361 | * @access public |
||
362 | */ |
||
363 | function greyscale() { |
||
367 | |||
368 | /** |
||
369 | * Resize Action |
||
370 | * |
||
371 | * For GD 2.01+ the new copyresampled function is used |
||
372 | * It uses a bicubic interpolation algorithm to get far |
||
373 | * better result. |
||
374 | * |
||
375 | * @param int $new_x New width |
||
376 | * @param int $new_y New height |
||
377 | * @param array $options Optional parameters |
||
378 | * <ul> |
||
379 | * <li>'scaleMethod': "pixel" or "smooth"</li> |
||
380 | * </ul> |
||
381 | * |
||
382 | * @return bool|PEAR_Error TRUE on success or PEAR_Error object on error |
||
383 | * @access protected |
||
384 | */ |
||
385 | function _resize($new_x, $new_y, $options = null) |
||
417 | |||
418 | /** |
||
419 | * Adjusts the image gamma |
||
420 | * |
||
421 | * @param float $outputgamma |
||
422 | * |
||
423 | * @return bool|PEAR_Error TRUE or a PEAR_Error object on error |
||
424 | * @access public |
||
425 | */ |
||
426 | function gamma($outputgamma = 1.0) |
||
433 | |||
434 | /** |
||
435 | * Helper method to save to a file or output the image |
||
436 | * |
||
437 | * @param string $filename the name of the file to write to (blank to output) |
||
438 | * @param string $types define the output format, default |
||
439 | * is the current used format |
||
440 | * @param int $quality output DPI, default is 75 |
||
441 | * |
||
442 | * @return bool|PEAR_Error TRUE on success or PEAR_Error object on error |
||
443 | * @access protected |
||
444 | */ |
||
445 | function _generate($filename, $type = '', $quality = null) |
||
494 | |||
495 | /** |
||
496 | * Displays image without saving and lose changes. |
||
497 | * |
||
498 | * This method adds the Content-type HTTP header |
||
499 | * |
||
500 | * @param string $type (JPEG, PNG...); |
||
501 | * @param int $quality 75 |
||
502 | * |
||
503 | * @return bool|PEAR_Error TRUE or PEAR_Error object on error |
||
504 | * @access public |
||
505 | */ |
||
506 | function display($type = '', $quality = null) |
||
510 | |||
511 | /** |
||
512 | * Saves the image to a file |
||
513 | * |
||
514 | * @param string $filename the name of the file to write to |
||
515 | * @param string $type the output format, default |
||
516 | * is the current used format |
||
517 | * @param int $quality default is 75 |
||
518 | * |
||
519 | * @return bool|PEAR_Error TRUE on success or PEAR_Error object on error |
||
520 | * @access public |
||
521 | */ |
||
522 | function save($filename, $type = '', $quality = null) |
||
530 | |||
531 | /** |
||
532 | * Destroys image handle |
||
533 | * |
||
534 | * @access public |
||
535 | */ |
||
536 | function free() |
||
548 | |||
549 | /** |
||
550 | * Returns a new image for temporary processing |
||
551 | * |
||
552 | * @param int $width width of the new image |
||
553 | * @param int $height height of the new image |
||
554 | * @param bool $trueColor force which type of image to create |
||
555 | * @return resource a GD image resource |
||
556 | * @access protected |
||
557 | */ |
||
558 | function _createImage($width = -1, $height = -1, $trueColor = null) |
||
615 | } |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.