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 Archangel 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 Archangel, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
12 | class Archangel |
||
13 | { |
||
14 | |||
15 | /** @var string $subject */ |
||
16 | protected $subject; |
||
17 | |||
18 | /** @var array $to */ |
||
19 | protected $to = array(); |
||
20 | |||
21 | /** @var array $cc */ |
||
22 | protected $cc = array(); |
||
23 | |||
24 | /** @var array $bcc */ |
||
25 | protected $bcc = array(); |
||
26 | |||
27 | /** @var array $headers */ |
||
28 | protected $headers = array(); |
||
29 | |||
30 | /** @var string $plainMessage */ |
||
31 | protected $plainMessage; |
||
32 | |||
33 | /** @var string $htmlMessage */ |
||
34 | protected $htmlMessage; |
||
35 | |||
36 | /** @var array $attachments */ |
||
37 | protected $attachments = array(); |
||
38 | |||
39 | /** @var string $boundary */ |
||
40 | protected $boundary; |
||
41 | |||
42 | /** @var string $alternativeBoundary */ |
||
43 | protected $alternativeBoundary; |
||
44 | |||
45 | /** @var string LINE_BREAK */ |
||
46 | const LINE_BREAK = "\r\n"; |
||
47 | |||
48 | /** |
||
49 | * @param string $mailer |
||
50 | */ |
||
51 | public function __construct($mailer = null) |
||
58 | |||
59 | /** |
||
60 | * Setter method for adding recipients |
||
61 | * |
||
62 | * @param string $address email address for the recipient |
||
63 | * @param string $title name of the recipient (optional) |
||
64 | |||
65 | * @return object instantiated $this |
||
66 | */ |
||
67 | View Code Duplication | public function addTo($address, $title = '') |
|
76 | |||
77 | /** |
||
78 | * Setter method for adding cc recipients |
||
79 | * |
||
80 | * @param string $address email address for the cc recipient |
||
81 | * @param string $title name of the cc recipient (optional) |
||
82 | * |
||
83 | * @return object instantiated $this |
||
84 | */ |
||
85 | View Code Duplication | public function addCC($address, $title = '') |
|
94 | |||
95 | /** |
||
96 | * Setter method for adding bcc recipients |
||
97 | * |
||
98 | * @param string $address email address for the bcc recipient |
||
99 | * @param string $title name of the bcc recipient (optional) |
||
100 | * |
||
101 | * @return object instantiated $this |
||
102 | */ |
||
103 | View Code Duplication | public function addBCC($address, $title = '') |
|
112 | |||
113 | /** |
||
114 | * Setter method for setting the single 'from' field |
||
115 | * |
||
116 | * @param string $address email address for the sender |
||
117 | * @param string $title name of the sender (optional) |
||
118 | * |
||
119 | * @return object instantiated $this |
||
120 | */ |
||
121 | View Code Duplication | public function setFrom($address, $title = '') |
|
130 | |||
131 | /** |
||
132 | * Setter method for setting the single 'reply-to' field |
||
133 | * |
||
134 | * @param string $address email address for the reply-to |
||
135 | * @param string $title name of the reply-to (optional) |
||
136 | * |
||
137 | * @return object instantiated $this |
||
138 | */ |
||
139 | View Code Duplication | public function setReplyTo($address, $title = '') |
|
148 | |||
149 | /** |
||
150 | * Setter method for setting a subject |
||
151 | * |
||
152 | * @param string $subject subject for the email |
||
153 | * |
||
154 | * @return object instantiated $this |
||
155 | */ |
||
156 | public function setSubject($subject) |
||
162 | |||
163 | /** |
||
164 | * Setter method for the plain text message |
||
165 | * |
||
166 | * @param string $message the plain-text message |
||
167 | * |
||
168 | * @return object instantiated $this |
||
169 | */ |
||
170 | public function setPlainMessage($message) |
||
176 | |||
177 | /** |
||
178 | * Setter method for the html message |
||
179 | * |
||
180 | * @param string $message the html message |
||
181 | * |
||
182 | * @return object instantiated $this |
||
183 | */ |
||
184 | public function setHTMLMessage($message) |
||
190 | |||
191 | /** |
||
192 | * Setter method for adding attachments |
||
193 | * |
||
194 | * @param string $path the full path of the attachment |
||
195 | * @param string $type mime type of the file |
||
196 | * @param string $title the title of the attachment (optional) |
||
197 | * |
||
198 | * @return object instantiated $this |
||
199 | */ |
||
200 | public function addAttachment($path, $type, $title = '') |
||
210 | |||
211 | /** |
||
212 | * The executing step, the actual sending of the email |
||
213 | * First checks to make sure the minimum fields are set (returns false if they are not) |
||
214 | * Second it attempts to send the mail with php's mail() (returns false if it fails) |
||
215 | * |
||
216 | * return boolean whether or not the email was valid & sent |
||
217 | */ |
||
218 | public function send() |
||
231 | |||
232 | /** |
||
233 | * Call to check the minimum required fields |
||
234 | * |
||
235 | * @return boolean whether or not the email meets the minimum required fields |
||
236 | */ |
||
237 | protected function checkRequiredFields() |
||
256 | |||
257 | /** |
||
258 | * Build the recipients from 'to' |
||
259 | * |
||
260 | * @return string comma-separated lit of recipients |
||
261 | */ |
||
262 | protected function buildTo() |
||
266 | |||
267 | /** |
||
268 | * Long, nasty creater of the actual message, with all the multipart logic you'd never want to see |
||
269 | * |
||
270 | * @return string email message |
||
271 | */ |
||
272 | protected function buildMessage() |
||
329 | |||
330 | |||
331 | /** |
||
332 | * Builder for the additional headers needed for multipart emails |
||
333 | * |
||
334 | * @return string headers needed for multipart |
||
335 | */ |
||
336 | protected function buildHeaders() |
||
360 | |||
361 | /** |
||
362 | * File reader for attachments |
||
363 | * |
||
364 | * @return string binary representation of file, base64'd |
||
365 | */ |
||
366 | protected function buildAttachmentContent($attachment) |
||
380 | |||
381 | /** |
||
382 | * Holder for the boundry logic |
||
383 | * Not called/created unless it's needed |
||
384 | * |
||
385 | * @return string boundary |
||
386 | */ |
||
387 | protected function getBoundary() |
||
394 | |||
395 | /** |
||
396 | * Holder to create the alternative boundry logic |
||
397 | * Not called/created unless it's needed |
||
398 | * |
||
399 | * @return string alternative boundary |
||
400 | */ |
||
401 | protected function getAlternativeBoundary() |
||
408 | } |
||
409 |
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.