Complex classes like ProductContext 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 ProductContext, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 28 | final class ProductContext implements Context |
||
| 29 | { |
||
| 30 | /** |
||
| 31 | * @var ShowPageInterface |
||
| 32 | */ |
||
| 33 | private $showPage; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * @var TaxonShowPageInterface |
||
| 37 | */ |
||
| 38 | private $taxonShowPage; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @var IndexPageInterface |
||
| 42 | */ |
||
| 43 | private $productReviewsIndexPage; |
||
| 44 | |||
| 45 | /** |
||
| 46 | * @param ShowPageInterface $showPage |
||
| 47 | * @param TaxonShowPageInterface $taxonShowPage |
||
| 48 | * @param IndexPageInterface $productReviewsIndexPage |
||
| 49 | */ |
||
| 50 | public function __construct( |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @Then I should be able to access product :product |
||
| 62 | */ |
||
| 63 | public function iShouldBeAbleToAccessProduct(ProductInterface $product) |
||
| 72 | |||
| 73 | /** |
||
| 74 | * @Then I should not be able to access product :product |
||
| 75 | */ |
||
| 76 | public function iShouldNotBeAbleToAccessProduct(ProductInterface $product) |
||
| 85 | |||
| 86 | /** |
||
| 87 | * @When /^I check (this product)'s details/ |
||
| 88 | * @When I view product :product |
||
| 89 | */ |
||
| 90 | public function iOpenProductPage(ProductInterface $product) |
||
| 94 | |||
| 95 | /** |
||
| 96 | * @Given I should see the product name :name |
||
| 97 | */ |
||
| 98 | public function iShouldSeeProductName($name) |
||
| 106 | |||
| 107 | /** |
||
| 108 | * @When I open page :url |
||
| 109 | */ |
||
| 110 | public function iOpenPage($url) |
||
| 114 | |||
| 115 | /** |
||
| 116 | * @Then I should be on :product product detailed page |
||
| 117 | * @Then I should still be on product :product page |
||
| 118 | */ |
||
| 119 | public function iShouldBeOnProductDetailedPage(ProductInterface $product) |
||
| 126 | |||
| 127 | /** |
||
| 128 | * @Then I should see the product attribute :attributeName with value :expectedAttribute |
||
| 129 | */ |
||
| 130 | public function iShouldSeeTheProductAttributeWithValue($attributeName, $expectedAttribute) |
||
| 144 | |||
| 145 | /** |
||
| 146 | * @Then I should see :count attributes |
||
| 147 | */ |
||
| 148 | public function iShouldSeeAttributes($count) |
||
| 158 | |||
| 159 | /** |
||
| 160 | * @Then the first attribute should be :name |
||
| 161 | */ |
||
| 162 | public function theFirstAttributeShouldBe($name) |
||
| 173 | |||
| 174 | /** |
||
| 175 | * @Then the last attribute should be :name |
||
| 176 | */ |
||
| 177 | public function theLastAttributeShouldBe($name) |
||
| 188 | |||
| 189 | /** |
||
| 190 | * @When /^I browse products from (taxon "([^"]+)")$/ |
||
| 191 | */ |
||
| 192 | public function iCheckListOfProductsForTaxon(TaxonInterface $taxon) |
||
| 196 | |||
| 197 | /** |
||
| 198 | * @When I search for products with name :name |
||
| 199 | */ |
||
| 200 | public function iSearchForProductsWithName($name) |
||
| 204 | |||
| 205 | /** |
||
| 206 | * @When I clear filter |
||
| 207 | */ |
||
| 208 | public function iClearFilter() |
||
| 212 | |||
| 213 | /** |
||
| 214 | * @Then I should see the product :productName |
||
| 215 | */ |
||
| 216 | public function iShouldSeeProduct($productName) |
||
| 223 | |||
| 224 | /** |
||
| 225 | * @Then I should not see the product :productName |
||
| 226 | */ |
||
| 227 | public function iShouldNotSeeProduct($productName) |
||
| 234 | |||
| 235 | /** |
||
| 236 | * @Then I should see empty list of products |
||
| 237 | */ |
||
| 238 | public function iShouldSeeEmptyListOfProducts() |
||
| 245 | |||
| 246 | /** |
||
| 247 | * @Then I should see that it is out of stock |
||
| 248 | */ |
||
| 249 | public function iShouldSeeItIsOutOfStock() |
||
| 256 | |||
| 257 | /** |
||
| 258 | * @Then I should be unable to add it to the cart |
||
| 259 | */ |
||
| 260 | public function iShouldBeUnableToAddItToTheCart() |
||
| 267 | |||
| 268 | /** |
||
| 269 | * @Then the product price should be :price |
||
| 270 | * @Then I should see the product price :price |
||
| 271 | */ |
||
| 272 | public function iShouldSeeTheProductPrice($price) |
||
| 280 | |||
| 281 | /** |
||
| 282 | * @When I set its :optionName to :optionValue |
||
| 283 | */ |
||
| 284 | public function iSetItsOptionTo($optionName, $optionValue) |
||
| 288 | |||
| 289 | /** |
||
| 290 | * @When I select :variantName variant |
||
| 291 | */ |
||
| 292 | public function iSelectVariant($variantName) |
||
| 296 | |||
| 297 | /** |
||
| 298 | * @Then I should see the product :productName with price :productPrice |
||
| 299 | */ |
||
| 300 | public function iShouldSeeTheProductWithPrice($productName, $productPrice) |
||
| 307 | |||
| 308 | /** |
||
| 309 | * @Then /^I should be notified that (this product) does not have sufficient stock$/ |
||
| 310 | */ |
||
| 311 | public function iShouldBeNotifiedThatThisProductDoesNotHaveSufficientStock(ProductInterface $product) |
||
| 320 | |||
| 321 | /** |
||
| 322 | * @Then /^I should not be notified that (this product) does not have sufficient stock$/ |
||
| 323 | */ |
||
| 324 | public function iShouldNotBeNotifiedThatThisProductDoesNotHaveSufficientStock(ProductInterface $product) |
||
| 331 | |||
| 332 | /** |
||
| 333 | * @Then I should see a main image |
||
| 334 | */ |
||
| 335 | public function iShouldSeeAMainImage() |
||
| 342 | |||
| 343 | /** |
||
| 344 | * @When /^I view (oldest|newest) products from (taxon "([^"]+)")$/ |
||
| 345 | */ |
||
| 346 | public function iViewSortedProductsFromTaxon($sortDirection, TaxonInterface $taxon) |
||
| 352 | |||
| 353 | /** |
||
| 354 | * @Then I should see :numberOfProducts products in the list |
||
| 355 | */ |
||
| 356 | public function iShouldSeeProductsInTheList($numberOfProducts) |
||
| 366 | |||
| 367 | /** |
||
| 368 | * @Then I should see a product with name :name |
||
| 369 | */ |
||
| 370 | public function iShouldSeeProductWithName($name) |
||
| 377 | |||
| 378 | /** |
||
| 379 | * @Then the first product on the list should have name :name |
||
| 380 | */ |
||
| 381 | public function theFirstProductOnTheListShouldHaveName($name) |
||
| 391 | |||
| 392 | /** |
||
| 393 | * @Then I should see :count product reviews |
||
| 394 | */ |
||
| 395 | public function iShouldSeeProductReviews($count) |
||
| 403 | |||
| 404 | /** |
||
| 405 | * @Then I should see reviews titled :firstReview, :secondReview and :thirdReview |
||
| 406 | */ |
||
| 407 | public function iShouldSeeReviewsTitled(...$reviews) |
||
| 416 | |||
| 417 | /** |
||
| 418 | * @Then I should not see review titled :title |
||
| 419 | */ |
||
| 420 | public function iShouldNotSeeReviewTitled($title) |
||
| 427 | |||
| 428 | /** |
||
| 429 | * @When /^I check (this product)'s reviews$/ |
||
| 430 | */ |
||
| 431 | public function iCheckThisProductSReviews(ProductInterface $product) |
||
| 435 | |||
| 436 | /** |
||
| 437 | * @Then /^I should see (\d+) product reviews in the list$/ |
||
| 438 | */ |
||
| 439 | public function iShouldSeeNumberOfProductReviewsInTheList($count) |
||
| 447 | |||
| 448 | /** |
||
| 449 | * @Then I should not see review titled :title in the list |
||
| 450 | */ |
||
| 451 | public function iShouldNotSeeReviewTitledInTheList($title) |
||
| 458 | |||
| 459 | /** |
||
| 460 | * @Then /^I should be notified that there are no reviews$/ |
||
| 461 | */ |
||
| 462 | public function iShouldBeNotifiedThatThereAreNoReviews() |
||
| 469 | |||
| 470 | /** |
||
| 471 | * @Then I should see :rating as its average rating |
||
| 472 | */ |
||
| 473 | public function iShouldSeeAsItsAverageRating($rating) |
||
| 483 | |||
| 484 | /** |
||
| 485 | * @Then /^I should(?:| also) see the product association "([^"]+)" with (products "[^"]+" and "[^"]+")$/ |
||
| 486 | */ |
||
| 487 | public function iShouldSeeTheProductAssociationWithProducts($productAssociationName, array $products) |
||
| 498 | |||
| 499 | /** |
||
| 500 | * @Then /^average rating of (product "[^"]+") should be (\d+)$/ |
||
| 501 | */ |
||
| 502 | public function thisProductAverageRatingShouldBe(ProductInterface $product, $averageRating) |
||
| 507 | |||
| 508 | /** |
||
| 509 | * @Then they should have order like :firstProductName, :secondProductName and :thirdProductName |
||
| 510 | */ |
||
| 511 | public function theyShouldHaveOrderLikeAnd(...$productNames) |
||
| 518 | |||
| 519 | /** |
||
| 520 | * @param string $productName |
||
| 521 | * @param string $productAssociationName |
||
| 522 | * |
||
| 523 | * @throws \InvalidArgumentException |
||
| 524 | */ |
||
| 525 | private function assertIsProductIsInAssociation($productName, $productAssociationName) |
||
| 536 | |||
| 537 | /** |
||
| 538 | * @return NodeElement[] |
||
| 539 | * |
||
| 540 | * @throws \InvalidArgumentException |
||
| 541 | */ |
||
| 542 | private function getProductAttributes() |
||
| 549 | } |
||
| 550 |
PHP provides two ways to mark string literals. Either with single quotes
'literal'or with double quotes"literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (
\') and the backslash (\\). Every other character is displayed as is.Double quoted string literals may contain other variables or more complex escape sequences.
will print an indented:
Single is ValueIf your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.
For more information on PHP string literals and available escape sequences see the PHP core documentation.