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 Url 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 Url, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
10 | class Url |
||
11 | { |
||
12 | protected $scheme; |
||
13 | protected $host; |
||
14 | protected $port; |
||
15 | protected $username; |
||
16 | protected $password; |
||
17 | protected $path = ''; |
||
18 | protected $fragment; |
||
19 | |||
20 | /** @var QueryString Query part of the URL */ |
||
21 | protected $query; |
||
22 | |||
23 | /** |
||
24 | * Factory method to create a new URL from a URL string |
||
25 | * |
||
26 | * @param string $url Full URL used to create a Url object |
||
27 | * |
||
28 | * @return Url |
||
29 | * @throws InvalidArgumentException |
||
30 | */ |
||
31 | public static function factory($url) |
||
51 | |||
52 | /** |
||
53 | * Build a URL from parse_url parts. The generated URL will be a relative URL if a scheme or host are not provided. |
||
54 | * |
||
55 | * @param array $parts Array of parse_url parts |
||
56 | * |
||
57 | * @return string |
||
58 | */ |
||
59 | public static function buildUrl(array $parts) |
||
109 | |||
110 | /** |
||
111 | * Create a new URL from URL parts |
||
112 | * |
||
113 | * @param string $scheme Scheme of the URL |
||
114 | * @param string $host Host of the URL |
||
115 | * @param string $username Username of the URL |
||
116 | * @param string $password Password of the URL |
||
117 | * @param int $port Port of the URL |
||
118 | * @param string $path Path of the URL |
||
119 | * @param QueryString|array|string $query Query string of the URL |
||
120 | * @param string $fragment Fragment of the URL |
||
121 | */ |
||
122 | public function __construct($scheme, $host, $username = null, $password = null, $port = null, $path = null, QueryString $query = null, $fragment = null) |
||
137 | |||
138 | /** |
||
139 | * Clone the URL |
||
140 | */ |
||
141 | public function __clone() |
||
145 | |||
146 | /** |
||
147 | * Returns the URL as a URL string |
||
148 | * |
||
149 | * @return string |
||
150 | */ |
||
151 | public function __toString() |
||
155 | |||
156 | /** |
||
157 | * Get the parts of the URL as an array |
||
158 | * |
||
159 | * @return array |
||
160 | */ |
||
161 | public function getParts() |
||
176 | |||
177 | /** |
||
178 | * Set the host of the request. |
||
179 | * |
||
180 | * @param string $host Host to set (e.g. www.yahoo.com, yahoo.com) |
||
181 | * |
||
182 | * @return Url |
||
183 | */ |
||
184 | public function setHost($host) |
||
196 | |||
197 | /** |
||
198 | * Get the host part of the URL |
||
199 | * |
||
200 | * @return string |
||
201 | */ |
||
202 | public function getHost() |
||
206 | |||
207 | /** |
||
208 | * Set the scheme part of the URL (http, https, ftp, etc) |
||
209 | * |
||
210 | * @param string $scheme Scheme to set |
||
211 | * |
||
212 | * @return Url |
||
213 | */ |
||
214 | public function setScheme($scheme) |
||
226 | |||
227 | /** |
||
228 | * Get the scheme part of the URL |
||
229 | * |
||
230 | * @return string |
||
231 | */ |
||
232 | public function getScheme() |
||
236 | |||
237 | /** |
||
238 | * Set the port part of the URL |
||
239 | * |
||
240 | * @param int $port Port to set |
||
241 | * |
||
242 | * @return Url |
||
243 | */ |
||
244 | public function setPort($port) |
||
250 | |||
251 | /** |
||
252 | * Get the port part of the URl. Will return the default port for a given scheme if no port has been set. |
||
253 | * |
||
254 | * @return int|null |
||
255 | */ |
||
256 | public function getPort() |
||
268 | |||
269 | /** |
||
270 | * Set the path part of the URL |
||
271 | * |
||
272 | * @param array|string $path Path string or array of path segments |
||
273 | * |
||
274 | * @return Url |
||
275 | */ |
||
276 | public function setPath($path) |
||
287 | |||
288 | /** |
||
289 | * Normalize the URL so that double slashes and relative paths are removed |
||
290 | * |
||
291 | * @return Url |
||
292 | */ |
||
293 | public function normalizePath() |
||
319 | |||
320 | /** |
||
321 | * Add a relative path to the currently set path. |
||
322 | * |
||
323 | * @param string $relativePath Relative path to add |
||
324 | * |
||
325 | * @return Url |
||
326 | */ |
||
327 | public function addPath($relativePath) |
||
339 | |||
340 | /** |
||
341 | * Get the path part of the URL |
||
342 | * |
||
343 | * @return string |
||
344 | */ |
||
345 | public function getPath() |
||
349 | |||
350 | /** |
||
351 | * Get the path segments of the URL as an array |
||
352 | * |
||
353 | * @return array |
||
354 | */ |
||
355 | public function getPathSegments() |
||
359 | |||
360 | /** |
||
361 | * Set the password part of the URL |
||
362 | * |
||
363 | * @param string $password Password to set |
||
364 | * |
||
365 | * @return Url |
||
366 | */ |
||
367 | public function setPassword($password) |
||
373 | |||
374 | /** |
||
375 | * Get the password part of the URL |
||
376 | * |
||
377 | * @return null|string |
||
378 | */ |
||
379 | public function getPassword() |
||
383 | |||
384 | /** |
||
385 | * Set the username part of the URL |
||
386 | * |
||
387 | * @param string $username Username to set |
||
388 | * |
||
389 | * @return Url |
||
390 | */ |
||
391 | public function setUsername($username) |
||
397 | |||
398 | /** |
||
399 | * Get the username part of the URl |
||
400 | * |
||
401 | * @return null|string |
||
402 | */ |
||
403 | public function getUsername() |
||
407 | |||
408 | /** |
||
409 | * Get the query part of the URL as a QueryString object |
||
410 | * |
||
411 | * @return QueryString |
||
412 | */ |
||
413 | public function getQuery() |
||
417 | |||
418 | /** |
||
419 | * Set the query part of the URL |
||
420 | * |
||
421 | * @param QueryString|string|array $query Query to set |
||
422 | * |
||
423 | * @return Url |
||
424 | */ |
||
425 | public function setQuery($query) |
||
439 | |||
440 | /** |
||
441 | * Get the fragment part of the URL |
||
442 | * |
||
443 | * @return null|string |
||
444 | */ |
||
445 | public function getFragment() |
||
449 | |||
450 | /** |
||
451 | * Set the fragment part of the URL |
||
452 | * |
||
453 | * @param string $fragment Fragment to set |
||
454 | * |
||
455 | * @return Url |
||
456 | */ |
||
457 | public function setFragment($fragment) |
||
463 | |||
464 | /** |
||
465 | * Check if this is an absolute URL |
||
466 | * |
||
467 | * @return bool |
||
468 | */ |
||
469 | public function isAbsolute() |
||
473 | |||
474 | /** |
||
475 | * Combine the URL with another URL. Follows the rules specific in RFC 3986 section 5.4. |
||
476 | * |
||
477 | * @param string $url Relative URL to combine with |
||
478 | * @param bool $strictRfc3986 Set to true to use strict RFC 3986 compliance when merging paths. When first |
||
479 | * released, Guzzle used an incorrect algorithm for combining relative URL paths. In |
||
480 | * order to not break users, we introduced this flag to allow the merging of URLs based |
||
481 | * on strict RFC 3986 section 5.4.1. This means that "http://a.com/foo/baz" merged with |
||
482 | * "bar" would become "http://a.com/foo/bar". When this value is set to false, it would |
||
483 | * become "http://a.com/foo/baz/bar". |
||
484 | * @return Url |
||
485 | * @throws InvalidArgumentException |
||
486 | * @link http://tools.ietf.org/html/rfc3986#section-5.4 |
||
487 | */ |
||
488 | public function combine($url, $strictRfc3986 = false) |
||
545 | |||
546 | private function addQuery(QueryString $new, $strictRfc386) |
||
554 | } |
||
555 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
integer
values, zero is a special case, in particular the following results might be unexpected: