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 |
||
| 27 | final class ProductContext implements Context |
||
| 28 | { |
||
| 29 | /** |
||
| 30 | * @var ShowPageInterface |
||
| 31 | */ |
||
| 32 | private $showPage; |
||
| 33 | |||
| 34 | /** |
||
| 35 | * @var TaxonShowPageInterface |
||
| 36 | */ |
||
| 37 | private $taxonShowPage; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * @var IndexPageInterface |
||
| 41 | */ |
||
| 42 | private $productReviewsIndexPage; |
||
| 43 | |||
| 44 | /** |
||
| 45 | * @param ShowPageInterface $showPage |
||
| 46 | * @param TaxonShowPageInterface $taxonShowPage |
||
| 47 | * @param IndexPageInterface $productReviewsIndexPage |
||
| 48 | */ |
||
| 49 | public function __construct( |
||
| 58 | |||
| 59 | /** |
||
| 60 | * @Then I should be able to access product :product |
||
| 61 | */ |
||
| 62 | public function iShouldBeAbleToAccessProduct(ProductInterface $product) |
||
| 71 | |||
| 72 | /** |
||
| 73 | * @Then I should not be able to access product :product |
||
| 74 | */ |
||
| 75 | public function iShouldNotBeAbleToAccessProduct(ProductInterface $product) |
||
| 84 | |||
| 85 | /** |
||
| 86 | * @When /^I check (this product)'s details/ |
||
| 87 | * @When I view product :product |
||
| 88 | */ |
||
| 89 | public function iOpenProductPage(ProductInterface $product) |
||
| 93 | |||
| 94 | /** |
||
| 95 | * @Given I should see the product name :name |
||
| 96 | */ |
||
| 97 | public function iShouldSeeProductName($name) |
||
| 105 | |||
| 106 | /** |
||
| 107 | * @When I open page :url |
||
| 108 | */ |
||
| 109 | public function iOpenPage($url) |
||
| 113 | |||
| 114 | /** |
||
| 115 | * @Then I should be on :product product detailed page |
||
| 116 | * @Then I should still be on product :product page |
||
| 117 | */ |
||
| 118 | public function iShouldBeOnProductDetailedPage(ProductInterface $product) |
||
| 125 | |||
| 126 | /** |
||
| 127 | * @Then I should see the product attribute :attributeName with value :AttributeValue |
||
| 128 | */ |
||
| 129 | public function iShouldSeeTheProductAttributeWithValue($attributeName, $AttributeValue) |
||
| 136 | |||
| 137 | /** |
||
| 138 | * @When /^I browse products from (taxon "([^"]+)")$/ |
||
| 139 | */ |
||
| 140 | public function iCheckListOfProductsForTaxon(TaxonInterface $taxon) |
||
| 144 | |||
| 145 | /** |
||
| 146 | * @When I search for products with name :name |
||
| 147 | */ |
||
| 148 | public function iSearchForProductsWithName($name) |
||
| 152 | |||
| 153 | /** |
||
| 154 | * @When I clear filter |
||
| 155 | */ |
||
| 156 | public function iClearFilter() |
||
| 160 | |||
| 161 | /** |
||
| 162 | * @Then I should see the product :productName |
||
| 163 | */ |
||
| 164 | public function iShouldSeeProduct($productName) |
||
| 171 | |||
| 172 | /** |
||
| 173 | * @Then I should not see the product :productName |
||
| 174 | */ |
||
| 175 | public function iShouldNotSeeProduct($productName) |
||
| 182 | |||
| 183 | /** |
||
| 184 | * @Then I should see empty list of products |
||
| 185 | */ |
||
| 186 | public function iShouldSeeEmptyListOfProducts() |
||
| 193 | |||
| 194 | /** |
||
| 195 | * @Then I should see that it is out of stock |
||
| 196 | */ |
||
| 197 | public function iShouldSeeItIsOutOfStock() |
||
| 204 | |||
| 205 | /** |
||
| 206 | * @Then I should be unable to add it to the cart |
||
| 207 | */ |
||
| 208 | public function iShouldBeUnableToAddItToTheCart() |
||
| 215 | |||
| 216 | /** |
||
| 217 | * @Then the product price should be :price |
||
| 218 | * @Then I should see the product price :price |
||
| 219 | */ |
||
| 220 | public function iShouldSeeTheProductPrice($price) |
||
| 228 | |||
| 229 | /** |
||
| 230 | * @When I set its :optionName to :optionValue |
||
| 231 | */ |
||
| 232 | public function iSetItsOptionTo($optionName, $optionValue) |
||
| 236 | |||
| 237 | /** |
||
| 238 | * @When I select :variantName variant |
||
| 239 | */ |
||
| 240 | public function iSelectVariant($variantName) |
||
| 244 | |||
| 245 | /** |
||
| 246 | * @Then I should see the product :productName with price :productPrice |
||
| 247 | */ |
||
| 248 | public function iShouldSeeTheProductWithPrice($productName, $productPrice) |
||
| 255 | |||
| 256 | /** |
||
| 257 | * @Then /^I should be notified that (this product) does not have sufficient stock$/ |
||
| 258 | */ |
||
| 259 | public function iShouldBeNotifiedThatThisProductDoesNotHaveSufficientStock(ProductInterface $product) |
||
| 268 | |||
| 269 | /** |
||
| 270 | * @Then /^I should not be notified that (this product) does not have sufficient stock$/ |
||
| 271 | */ |
||
| 272 | public function iShouldNotBeNotifiedThatThisProductDoesNotHaveSufficientStock(ProductInterface $product) |
||
| 279 | |||
| 280 | /** |
||
| 281 | * @Then I should see a main image |
||
| 282 | */ |
||
| 283 | public function iShouldSeeAMainImage() |
||
| 290 | |||
| 291 | /** |
||
| 292 | * @When /^I view (oldest|newest) products from (taxon "([^"]+)")$/ |
||
| 293 | */ |
||
| 294 | public function iViewSortedProductsFromTaxon($sortDirection, TaxonInterface $taxon) |
||
| 300 | |||
| 301 | /** |
||
| 302 | * @Then I should see :numberOfProducts products in the list |
||
| 303 | */ |
||
| 304 | public function iShouldSeeProductsInTheList($numberOfProducts) |
||
| 314 | |||
| 315 | /** |
||
| 316 | * @Then I should see a product with name :name |
||
| 317 | */ |
||
| 318 | public function iShouldSeeProductWithName($name) |
||
| 325 | |||
| 326 | /** |
||
| 327 | * @Then the first product on the list should have name :name |
||
| 328 | */ |
||
| 329 | public function theFirstProductOnTheListShouldHaveName($name) |
||
| 339 | |||
| 340 | /** |
||
| 341 | * @Then I should see :count product reviews |
||
| 342 | */ |
||
| 343 | public function iShouldSeeProductReviews($count) |
||
| 351 | |||
| 352 | /** |
||
| 353 | * @Then I should see reviews titled :firstReview, :secondReview and :thirdReview |
||
| 354 | */ |
||
| 355 | public function iShouldSeeReviewsTitled(...$reviews) |
||
| 364 | |||
| 365 | /** |
||
| 366 | * @Then I should not see review titled :title |
||
| 367 | */ |
||
| 368 | public function iShouldNotSeeReviewTitled($title) |
||
| 375 | |||
| 376 | /** |
||
| 377 | * @When /^I check (this product)'s reviews$/ |
||
| 378 | */ |
||
| 379 | public function iCheckThisProductSReviews(ProductInterface $product) |
||
| 383 | |||
| 384 | /** |
||
| 385 | * @Then /^I should see (\d+) product reviews in the list$/ |
||
| 386 | */ |
||
| 387 | public function iShouldSeeNumberOfProductReviewsInTheList($count) |
||
| 388 | { |
||
| 389 | Assert::same( |
||
| 390 | (int) $count, |
||
| 391 | $this->productReviewsIndexPage->countReviews(), |
||
| 392 | 'Product has %2$s reviews in the list, but should have %s.' |
||
| 393 | ); |
||
| 394 | } |
||
| 395 | |||
| 396 | /** |
||
| 397 | * @Then I should not see review titled :title in the list |
||
| 398 | */ |
||
| 399 | public function iShouldNotSeeReviewTitledInTheList($title) |
||
| 406 | |||
| 407 | /** |
||
| 408 | * @Then /^I should be notified that there are no reviews$/ |
||
| 409 | */ |
||
| 410 | public function iShouldBeNotifiedThatThereAreNoReviews() |
||
| 417 | |||
| 418 | /** |
||
| 419 | * @Then I should see :rating as its average rating |
||
| 420 | */ |
||
| 421 | public function iShouldSeeAsItsAverageRating($rating) |
||
| 431 | |||
| 432 | /** |
||
| 433 | * @Then /^I should(?:| also) see the product association "([^"]+)" with (products "[^"]+" and "[^"]+")$/ |
||
| 434 | */ |
||
| 435 | public function iShouldSeeTheProductAssociationWithProducts($productAssociationName, array $products) |
||
| 446 | |||
| 447 | /** |
||
| 448 | * @param string $productName |
||
| 449 | * @param string $productAssociationName |
||
| 450 | * |
||
| 451 | * @throws \InvalidArgumentException |
||
| 452 | */ |
||
| 453 | private function assertIsProductIsInAssociation($productName, $productAssociationName) |
||
| 464 | |||
| 465 | /** |
||
| 466 | * @Then /^average rating of (product "[^"]+") should be (\d+)$/ |
||
| 467 | */ |
||
| 468 | public function thisProductAverageRatingShouldBe(ProductInterface $product, $averageRating) |
||
| 473 | } |
||
| 474 |
This check examines a number of code elements and verifies that they conform to the given naming conventions.
You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.