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 XmlContext 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 XmlContext, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 11 | class XmlContext extends BehatContext implements ResponseStorageAware |
||
| 12 | { |
||
| 13 | private $asserter; |
||
| 14 | |||
| 15 | private $xmlStorage; |
||
| 16 | |||
| 17 | public function __construct(asserter $asserter) |
||
| 21 | |||
| 22 | public function setResponseStorage(ResponseStorage $responseStorage) |
||
| 26 | |||
| 27 | /** |
||
| 28 | * @When /^I load XML:$/ |
||
| 29 | */ |
||
| 30 | public function iLoadXml(PyStringNode $jsonContent) |
||
| 34 | |||
| 35 | /** |
||
| 36 | * Checks that the response is correct XML |
||
| 37 | * |
||
| 38 | * @Then /^the response should be in XML$/ |
||
| 39 | */ |
||
| 40 | public function theResponseShouldBeInXml() |
||
| 44 | |||
| 45 | /** |
||
| 46 | * Checks that the response is not correct XML |
||
| 47 | * |
||
| 48 | * @Then /^the response should not be in XML$/ |
||
| 49 | */ |
||
| 50 | public function theResponseShouldNotBeInXml() |
||
| 61 | |||
| 62 | /** |
||
| 63 | * Checks that the specified XML element exists |
||
| 64 | * |
||
| 65 | * @param string $element |
||
| 66 | * @throws \Exception |
||
| 67 | * @return \DomNodeList |
||
| 68 | * |
||
| 69 | * @Then /^the XML element "(?P<element>[^"]*)" should exists?$/ |
||
| 70 | */ |
||
| 71 | View Code Duplication | public function theXmlElementShouldExist($element) |
|
| 79 | |||
| 80 | /** |
||
| 81 | * Checks that the specified XML element does not exist |
||
| 82 | * |
||
| 83 | * @Then /^the XML element "(?P<element>[^"]*)" should not exists?$/ |
||
| 84 | */ |
||
| 85 | View Code Duplication | public function theXmlElementShouldNotExist($element) |
|
| 92 | |||
| 93 | /** |
||
| 94 | * @Then /^the XML response should be equal to:$/ |
||
| 95 | */ |
||
| 96 | public function theResponseXmlShouldBeEqualTo(PyStringNode $expected) |
||
| 109 | |||
| 110 | /** |
||
| 111 | * Checks that the specified XML element is equal to the given value |
||
| 112 | * |
||
| 113 | * @Then /^the XML element "(?P<element>(?:[^"]|\\")*)" should be equal to "(?P<text>[^"]*)"$/ |
||
| 114 | */ |
||
| 115 | View Code Duplication | public function theXmlElementShouldBeEqualTo($element, $text) |
|
| 123 | |||
| 124 | /** |
||
| 125 | * Checks that the specified XML element is not equal to the given value |
||
| 126 | * |
||
| 127 | * @Then /^the XML element "(?P<element>(?:[^"]|\\")*)" should not be equal to "(?P<text>[^"]*)"$/ |
||
| 128 | */ |
||
| 129 | View Code Duplication | public function theXmlElementShouldNotBeEqualTo($element, $text) |
|
| 137 | |||
| 138 | /** |
||
| 139 | * Checks that the XML attribute on the specified element exists |
||
| 140 | * |
||
| 141 | * @Then /^the XML attribute "(?P<attribute>[^"]*)" on element "(?P<element>(?:[^"]|\\")*)" should exists?$/ |
||
| 142 | */ |
||
| 143 | View Code Duplication | public function theXmlAttributeShouldExist($attribute, $element) |
|
| 152 | |||
| 153 | /** |
||
| 154 | * Checks that the XML attribute on the specified element does not exist |
||
| 155 | * |
||
| 156 | * @Then /^the XML attribute "(?P<attribute>[^"]*)" on element "(?P<element>(?:[^"]|\\")*)" should not exists?$/ |
||
| 157 | */ |
||
| 158 | View Code Duplication | public function theXmlAttributeShouldNotExist($attribute, $element) |
|
| 170 | |||
| 171 | /** |
||
| 172 | * Checks that the XML attribute on the specified element is equal to the given value |
||
| 173 | * |
||
| 174 | * @Then /^the XML attribute "(?P<attribute>[^"]*)" on element "(?P<element>(?:[^"]|\\")*)" should be equal to "(?P<text>[^"]*)"$/ |
||
| 175 | */ |
||
| 176 | View Code Duplication | public function theXmlAttributeShouldBeEqualTo($attribute, $element, $text) |
|
| 183 | |||
| 184 | /** |
||
| 185 | * Checks that the XML attribute on the specified element is not equal to the given value |
||
| 186 | * |
||
| 187 | * @Then /^the XML attribute "(?P<attribute>[^"]*)" on element "(?P<element>(?:[^"]|\\")*)" should not be equal to "(?P<text>[^"]*)"$/ |
||
| 188 | */ |
||
| 189 | View Code Duplication | public function theXmlAttributeShouldNotBeEqualTo($attribute, $element, $text) |
|
| 196 | |||
| 197 | /** |
||
| 198 | * Checks that the given XML element has N child element(s) |
||
| 199 | * |
||
| 200 | * @Then /^the XML element "(?P<element>[^"]*)" should have (?P<nth>\d+) elements?$/ |
||
| 201 | */ |
||
| 202 | |||
| 203 | public function theXmlElementShouldHaveNChildElements($element, $nth) |
||
| 217 | |||
| 218 | /** |
||
| 219 | * Checks that the given XML element contains the given value |
||
| 220 | * |
||
| 221 | * @Then /^the XML element "(?P<element>[^"]*)" should contain "(?P<text>[^"]*)"$/ |
||
| 222 | */ |
||
| 223 | public function theXmlElementShouldContain($element, $text) |
||
| 231 | |||
| 232 | /** |
||
| 233 | * Checks that the given XML element does not contain the given value |
||
| 234 | * |
||
| 235 | * @Then /^the XML element "(?P<element>[^"]*)" should not contain "(?P<text>[^"]*)"$/ |
||
| 236 | */ |
||
| 237 | public function theXmlElementShouldNotContain($element, $text) |
||
| 245 | |||
| 246 | /** |
||
| 247 | * Checks that the XML uses the specified namespace |
||
| 248 | * |
||
| 249 | * @Then /^[Tt]he XML should use the namespace "(?P<namespace>[^"]*)"$/ |
||
| 250 | */ |
||
| 251 | View Code Duplication | public function theXmlShouldUseTheNamespace($namespace) |
|
| 258 | |||
| 259 | /** |
||
| 260 | * Checks that the XML does not use the specified namespace |
||
| 261 | * |
||
| 262 | * @Then /^[Tt]he XML should not use the namespace "(?P<namespace>[^"]*)"$/ |
||
| 263 | */ |
||
| 264 | View Code Duplication | public function theXmlShouldNotUseTheNamespace($namespace) |
|
| 271 | |||
| 272 | /** |
||
| 273 | * Optimistically (ignoring errors) attempt to pretty-print the last XML response |
||
| 274 | * |
||
| 275 | * @Then /^print last XML response$/ |
||
| 276 | */ |
||
| 277 | public function printLastXmlResponse() |
||
| 282 | |||
| 283 | /** |
||
| 284 | * @param string $element |
||
| 285 | * @return \DomNodeList |
||
| 286 | */ |
||
| 287 | public function xpath($element) |
||
| 293 | |||
| 294 | /** |
||
| 295 | * @return array |
||
| 296 | */ |
||
| 297 | private function getNamespaces() |
||
| 301 | |||
| 302 | /** |
||
| 303 | * @BeforeScenario |
||
| 304 | */ |
||
| 305 | public function beforeScenario() |
||
| 310 | } |
||
| 311 |