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 Swift 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 Swift, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
31 | class Swift |
||
32 | { |
||
33 | /** |
||
34 | * The version number. |
||
35 | */ |
||
36 | const VERSION = "3.3.2"; |
||
37 | /** |
||
38 | * Constant to flag Swift not to try and connect upon instantiation |
||
39 | */ |
||
40 | const NO_START = 2; |
||
41 | /** |
||
42 | * Constant to tell Swift not to perform the standard SMTP handshake upon connect |
||
43 | */ |
||
44 | const NO_HANDSHAKE = 4; |
||
45 | /** |
||
46 | * Constant to ask Swift to start logging |
||
47 | */ |
||
48 | const ENABLE_LOGGING = 8; |
||
49 | /** |
||
50 | * Constant to prevent postConnect() being run in the connection |
||
51 | */ |
||
52 | const NO_POST_CONNECT = 16; |
||
53 | /** |
||
54 | * The connection object currently active |
||
55 | * @var Swift_Connection |
||
56 | */ |
||
57 | public $connection = null; |
||
58 | /** |
||
59 | * The domain name of this server (should technically be a FQDN) |
||
60 | * @var string |
||
61 | */ |
||
62 | protected $domain = null; |
||
63 | /** |
||
64 | * Flags to change the behaviour of Swift |
||
65 | * @var int |
||
66 | */ |
||
67 | protected $options; |
||
68 | /** |
||
69 | * Loaded plugins, separated into containers according to roles |
||
70 | * @var array |
||
71 | */ |
||
72 | protected $listeners = array(); |
||
73 | |||
74 | /** |
||
75 | * Constructor |
||
76 | * @param Swift_Connection The connection object to deal with I/O |
||
77 | * @param string The domain name of this server (the client) as a FQDN |
||
78 | * @param int Optional flags |
||
79 | * @throws Swift_ConnectionException If a connection cannot be established or the connection is behaving incorrectly |
||
80 | */ |
||
81 | public function __construct(Swift_Connection $conn, $domain=false, $options=null) |
||
104 | /** |
||
105 | * Populate the listeners array with the defined listeners ready for plugins |
||
106 | */ |
||
107 | protected function initializeEventListenerContainer() |
||
116 | /** |
||
117 | * Add a new plugin to Swift |
||
118 | * Plugins must implement one or more event listeners |
||
119 | * @param Swift_Events_Listener The plugin to load |
||
120 | */ |
||
121 | public function attachPlugin(Swift_Events_Listener $plugin, $id) |
||
130 | /** |
||
131 | * Get an attached plugin if it exists |
||
132 | * @param string The id of the plugin |
||
133 | * @return Swift_Event_Listener |
||
134 | */ |
||
135 | public function getPlugin($id) |
||
143 | /** |
||
144 | * Remove a plugin attached under the ID of $id |
||
145 | * @param string The ID of the plugin |
||
146 | */ |
||
147 | public function removePlugin($id) |
||
158 | /** |
||
159 | * Send a new type of event to all objects which are listening for it |
||
160 | * @param Swift_Events The event to send |
||
161 | * @param string The type of event |
||
162 | * @param string $type |
||
163 | */ |
||
164 | public function notifyListeners($e, $type) |
||
177 | /** |
||
178 | * Check if an option flag has been set |
||
179 | * @param string Option name |
||
180 | * @param integer $option |
||
181 | * @return boolean |
||
182 | */ |
||
183 | public function hasOption($option) |
||
187 | /** |
||
188 | * Adjust the options flags |
||
189 | * E.g. $obj->setOptions(Swift::NO_START | Swift::NO_HANDSHAKE) |
||
190 | * @param int The bits to set |
||
191 | */ |
||
192 | public function setOptions($options) |
||
196 | /** |
||
197 | * Get the current options set (as bits) |
||
198 | * @return int |
||
199 | */ |
||
200 | public function getOptions() |
||
204 | /** |
||
205 | * Set the FQDN of this server as it will identify itself |
||
206 | * @param string The FQDN of the server |
||
207 | * @param string|boolean $name |
||
208 | */ |
||
209 | public function setDomain($name) |
||
213 | /** |
||
214 | * Attempt to establish a connection with the service |
||
215 | * @throws Swift_ConnectionException If the connection cannot be established or behaves oddly |
||
216 | */ |
||
217 | public function connect() |
||
228 | /** |
||
229 | * Disconnect from the MTA |
||
230 | * @throws Swift_ConnectionException If the connection will not stop |
||
231 | */ |
||
232 | public function disconnect() |
||
239 | /** |
||
240 | * Throws an exception if the response code wanted does not match the one returned |
||
241 | * @param Swift_Event_ResponseEvent The full response from the service |
||
242 | * @param int The 3 digit response code wanted |
||
243 | * @param integer $codes |
||
244 | * @throws Swift_BadResponseException If the code does not match |
||
245 | */ |
||
246 | protected function assertCorrectResponse(Swift_Events_ResponseEvent $response, $codes) |
||
257 | /** |
||
258 | * Have a polite greeting with the server and work out what it's capable of |
||
259 | * @param Swift_Events_ResponseEvent The initial service line respoonse |
||
260 | * @throws Swift_ConnectionException If conversation is not going very well |
||
261 | */ |
||
262 | protected function handshake(Swift_Events_ResponseEvent $greeting) |
||
270 | /** |
||
271 | * Set the extensions which the service reports in the connection object |
||
272 | * @param Swift_Events_ResponseEvent The list of extensions as reported by the service |
||
273 | */ |
||
274 | protected function setConnectionExtensions(Swift_Events_ResponseEvent $list) |
||
285 | /** |
||
286 | * Execute a command against the service and get the response |
||
287 | * @param string The command to execute (leave off any CRLF!!!) |
||
288 | * @param int The code to check for in the response, if any. -1 indicates that no response is wanted. |
||
289 | * @param integer $code |
||
290 | * @return Swift_Events_ResponseEvent The server's response (could be multiple lines) |
||
291 | * @throws Swift_ConnectionException If a code was expected but does not match the one returned |
||
292 | */ |
||
293 | public function command($command, $code=null) |
||
318 | /** |
||
319 | * Reset a conversation which has gone badly |
||
320 | * @throws Swift_ConnectionException If the service refuses to reset |
||
321 | */ |
||
322 | public function reset() |
||
326 | /** |
||
327 | * Send a message to any number of recipients |
||
328 | * @param Swift_Message The message to send. This does not need to (and shouldn't really) have any of the recipient headers set. |
||
329 | * @param mixed The recipients to send to. Can be a string, Swift_Address or Swift_RecipientList. Note that all addresses apart from Bcc recipients will appear in the message headers |
||
330 | * @param mixed The address to send the message from. Can either be a string or an instance of Swift_Address. |
||
331 | * @return int The number of successful recipients |
||
332 | * @throws Swift_ConnectionException If sending fails for any reason. |
||
333 | */ |
||
334 | public function send(Swift_Message $message, $recipients, $from) |
||
481 | /** |
||
482 | * Send a message to a batch of recipients. |
||
483 | * Unlike send() this method ignores Cc and Bcc recipients and does not reveal every recipients' address in the headers |
||
484 | * @param Swift_Message The message to send (leave out the recipient headers unless you are deliberately overriding them) |
||
485 | * @param Swift_RecipientList The addresses to send to |
||
486 | * @param Swift_Address The address the mail is from (sender) |
||
487 | * @param Swift_Address $from |
||
488 | * @return int The number of successful recipients |
||
489 | */ |
||
490 | public function batchSend(Swift_Message $message, Swift_RecipientList $to, $from) |
||
495 | } |
||
496 |
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: