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 SemRush 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 SemRush, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class SemRush extends SEOstats |
||
20 | { |
||
21 | 30 | public static function getDBs() |
|
22 | { |
||
23 | return array( |
||
24 | 30 | "au", # Google.com.au (Australia) |
|
25 | 30 | "br", # Google.com.br (Brazil) |
|
26 | 30 | "ca", # Google.ca (Canada) |
|
27 | 30 | "de", # Google.de (Germany) |
|
28 | 30 | "es", # Google.es (Spain) |
|
29 | 30 | "fr", # Google.fr (France) |
|
30 | 30 | "it", # Google.it (Italy) |
|
31 | 30 | "ru", # Google.ru (Russia) |
|
32 | 30 | "uk", # Google.co.uk (United Kingdom) |
|
33 | 30 | 'us', # Google.com (United States) |
|
34 | "us.bing" # Bing.com |
||
35 | 30 | ); |
|
36 | } |
||
37 | |||
38 | 1 | public static function getParams() |
|
39 | { |
||
40 | return array( |
||
41 | "DomainReports" => array( |
||
42 | 1 | "Ac" => "Estimated expenses the site has for advertising in Ads (per month).", |
|
43 | 1 | "Ad" => "Number of Keywords this site has in the TOP20 Ads results.", |
|
44 | 1 | "At" => "Estimated number of visitors coming from Ads (per month).", |
|
45 | 1 | "Dn" => "The requested site name.", |
|
46 | 1 | "Dt" => "The date when the report data was computed (formatted as YYYYmmdd).", |
|
47 | 1 | "Np" => "The number of keywords for which the site is displayed in search results next to the analyzed site.", |
|
48 | 1 | "Oa" => "Estimated number of potential ad/traffic buyers.", |
|
49 | 1 | "Oc" => "Estimated cost of purchasing the same number of visitors through Ads.", |
|
50 | 1 | "Oo" => "Estimated number of competitors in organic search.", |
|
51 | 1 | "Or" => "Number of Keywords this site has in the TOP20 organic results.", |
|
52 | 1 | "Ot" => "Estimated number of visitors coming from the first 20 search results (per month).", |
|
53 | "Rk" => "The SEMRush Rank (rating of sites by the number of visitors coming from the first 20 search results)." |
||
54 | 1 | ), |
|
55 | "OrganicKeywordReports" => array( |
||
56 | 1 | "Co" => "Competition of advertisers for that term (the higher the number - the greater the competition).", |
|
57 | 1 | "Cp" => "Average price of a click on an Ad for this search query (in U.S. dollars).", |
|
58 | 1 | "Nr" => "The number of search results - how many results does the search engine return for this query.", |
|
59 | 1 | "Nq" => "Average number of queries for the keyword per month (for the corresponding local version of search engine).", |
|
60 | 1 | "Ph" => "The search query the site has within the first 20 search results.", |
|
61 | 1 | "Po" => "The site's position for the search query (at the moment of data collection).", |
|
62 | 1 | "Pp" => "The site's position for the search query (at the time of prior data collection).", |
|
63 | 1 | "Tc" => "The estimated value of the organic traffic generated by the query as compared to the cost of purchasing the same volume of traffic through Ads.", |
|
64 | 1 | "Tr" => "The ratio comparing the number of visitors coming to the site from this search request to all visitors to the site from search results.", |
|
65 | "Ur" => "URL of a page on the site displayed in search results for this query (landing page)." |
||
66 | 1 | ) |
|
67 | 1 | ); |
|
68 | } |
||
69 | |||
70 | /** |
||
71 | * Returns the SEMRush main report data. |
||
72 | * (Only main report is public available.) |
||
73 | * |
||
74 | * @access public |
||
75 | * @param url string Domain name only, eg. "ebay.com" (/wo quotes). |
||
76 | * @param db string Optional: The database to use. Valid values are: |
||
77 | * au, br, ca, de, es, fr, it, ru, uk, us, us.bing (us is default) |
||
78 | * @return array Returns an array containing the main report data. |
||
79 | * @link http://www.semrush.com/api.html |
||
80 | */ |
||
81 | 6 | public static function getDomainRank($url = false, $db = false) |
|
87 | |||
88 | 6 | public static function getDomainRankHistory($url = false, $db = false) |
|
94 | |||
95 | 4 | public static function getOrganicKeywords($url = false, $db = false) |
|
99 | |||
100 | 4 | public static function getCompetitors($url = false, $db = false) |
|
104 | |||
105 | 10 | public static function getDomainGraph($reportType = 1, $url = false, $db = false, $w = 400, $h = 300, $lc = 'e43011', $dc = 'e43011', $lang = 'en', $html = true) |
|
122 | |||
123 | 13 | protected static function getApiData($url) |
|
128 | |||
129 | 29 | protected static function getSemRushDatabase($db) |
|
135 | |||
136 | 36 | protected static function guardDomainIsValid($domain) |
|
142 | |||
143 | 29 | protected static function guardDatabaseIsValid($database) |
|
149 | |||
150 | 8 | protected static function guardValidArgsForGetDomainGraph($reportType, $width, $height, $lang) |
|
168 | |||
169 | 12 | protected static function getBackendData($url, $db, $reportType) |
|
184 | |||
185 | 15 | View Code Duplication | protected static function getBackendUrl($url, $db, $reportType) |
193 | |||
194 | 11 | View Code Duplication | protected static function getWidgetUrl($url, $db, $reportType) |
202 | |||
203 | 8 | protected static function getWidgetData($url, $db, $reportType, $valueKey) |
|
211 | |||
212 | 29 | protected static function checkDatabase($db) |
|
216 | |||
217 | /** |
||
218 | * |
||
219 | * @throws E |
||
220 | */ |
||
221 | 20 | View Code Duplication | protected static function exc($err) |
222 | { |
||
223 | 20 | $e = ($err == 'db') ? "Invalid database. Choose one of: " . |
|
224 | 20 | substr( implode(", ", self::getDBs()), 0, -2) : $err; |
|
225 | 20 | throw new E($e); |
|
226 | exit(0); |
||
227 | } |
||
228 | |||
229 | 36 | protected static function getDomainFromUrl($url) |
|
230 | { |
||
231 | 36 | $url = parent::getUrl($url); |
|
232 | 36 | $domain = Helper\Url::parseHost($url); |
|
233 | 36 | static::guardDomainIsValid($domain); |
|
234 | |||
235 | 29 | return $domain; |
|
236 | } |
||
237 | |||
238 | 29 | protected static function getValidDatabase($db) |
|
246 | } |
||
247 |
This check looks for a call to a parent method whose name is different than the method from which it is called.
Consider the following code:
The
getFirstName()
method in theSon
calls the wrong method in the parent class.