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: