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 SectionService 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 SectionService, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
36 | class SectionService implements SectionServiceInterface |
||
37 | { |
||
38 | /** |
||
39 | * @var \eZ\Publish\API\Repository\Repository |
||
40 | */ |
||
41 | protected $repository; |
||
42 | |||
43 | /** |
||
44 | * @var \eZ\Publish\API\Repository\PermissionResolver |
||
45 | */ |
||
46 | protected $permissionResolver; |
||
47 | |||
48 | /** |
||
49 | * @var \eZ\Publish\API\Repository\PermissionCriterionResolver |
||
50 | */ |
||
51 | protected $permissionCriterionResolver; |
||
52 | |||
53 | /** |
||
54 | * @var \eZ\Publish\SPI\Persistence\Content\Section\Handler |
||
55 | */ |
||
56 | protected $sectionHandler; |
||
57 | |||
58 | /** |
||
59 | * @var \eZ\Publish\SPI\Persistence\Content\Location\Handler |
||
60 | */ |
||
61 | protected $locationHandler; |
||
62 | |||
63 | /** |
||
64 | * @var array |
||
65 | */ |
||
66 | protected $settings; |
||
67 | |||
68 | /** |
||
69 | * Setups service with reference to repository object that created it & corresponding handler. |
||
70 | * |
||
71 | * @param \eZ\Publish\API\Repository\Repository $repository |
||
72 | * @param \eZ\Publish\SPI\Persistence\Content\Section\Handler $sectionHandler |
||
73 | * @param \eZ\Publish\SPI\Persistence\Content\Location\Handler $locationHandler |
||
74 | * @param \eZ\Publish\API\Repository\PermissionCriterionResolver $permissionCriterionResolver |
||
75 | * @param array $settings |
||
76 | */ |
||
77 | public function __construct(RepositoryInterface $repository, SectionHandler $sectionHandler, LocationHandler $locationHandler, PermissionCriterionResolver $permissionCriterionResolver, array $settings = array()) |
||
89 | |||
90 | /** |
||
91 | * Creates a new Section in the content repository. |
||
92 | * |
||
93 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to create a section |
||
94 | * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the new identifier in $sectionCreateStruct already exists |
||
95 | * |
||
96 | * @param \eZ\Publish\API\Repository\Values\Content\SectionCreateStruct $sectionCreateStruct |
||
97 | * |
||
98 | * @return \eZ\Publish\API\Repository\Values\Content\Section The newly created section |
||
99 | */ |
||
100 | public function createSection(SectionCreateStruct $sectionCreateStruct) |
||
137 | |||
138 | /** |
||
139 | * Updates the given section in the content repository. |
||
140 | * |
||
141 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to create a section |
||
142 | * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the new identifier already exists (if set in the update struct) |
||
143 | * |
||
144 | * @param \eZ\Publish\API\Repository\Values\Content\Section $section |
||
145 | * @param \eZ\Publish\API\Repository\Values\Content\SectionUpdateStruct $sectionUpdateStruct |
||
146 | * |
||
147 | * @return \eZ\Publish\API\Repository\Values\Content\Section |
||
148 | */ |
||
149 | public function updateSection(Section $section, SectionUpdateStruct $sectionUpdateStruct) |
||
193 | |||
194 | /** |
||
195 | * Loads a Section from its id ($sectionId). |
||
196 | * |
||
197 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if section could not be found |
||
198 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to read a section |
||
199 | * |
||
200 | * @param mixed $sectionId |
||
201 | * |
||
202 | * @return \eZ\Publish\API\Repository\Values\Content\Section |
||
203 | */ |
||
204 | public function loadSection($sectionId) |
||
216 | |||
217 | /** |
||
218 | * Loads all sections. |
||
219 | * |
||
220 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to read a section |
||
221 | * |
||
222 | * @return \eZ\Publish\API\Repository\Values\Content\Section[] |
||
223 | */ |
||
224 | public function loadSections() |
||
238 | |||
239 | /** |
||
240 | * Loads a Section from its identifier ($sectionIdentifier). |
||
241 | * |
||
242 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException if section could not be found |
||
243 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user user is not allowed to read a section |
||
244 | * |
||
245 | * @param string $sectionIdentifier |
||
246 | * |
||
247 | * @return \eZ\Publish\API\Repository\Values\Content\Section |
||
248 | */ |
||
249 | public function loadSectionByIdentifier($sectionIdentifier) |
||
265 | |||
266 | /** |
||
267 | * Counts the contents which $section is assigned to. |
||
268 | * |
||
269 | * @param \eZ\Publish\API\Repository\Values\Content\Section $section |
||
270 | * |
||
271 | * @return int |
||
272 | * |
||
273 | * @deprecated since 6.0 |
||
274 | */ |
||
275 | public function countAssignedContents(Section $section) |
||
279 | |||
280 | /** |
||
281 | * Returns true if the given section is assigned to contents, or used in role policies, or in role assignments. |
||
282 | * |
||
283 | * This does not check user permissions. |
||
284 | * |
||
285 | * @since 6.0 |
||
286 | * |
||
287 | * @param \eZ\Publish\API\Repository\Values\Content\Section $section |
||
288 | * |
||
289 | * @return bool |
||
290 | */ |
||
291 | public function isSectionUsed(Section $section) |
||
297 | |||
298 | /** |
||
299 | * Assigns the content to the given section |
||
300 | * this method overrides the current assigned section. |
||
301 | * |
||
302 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If user does not have access to view provided object |
||
303 | * |
||
304 | * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo |
||
305 | * @param \eZ\Publish\API\Repository\Values\Content\Section $section |
||
306 | */ |
||
307 | public function assignSection(ContentInfo $contentInfo, Section $section) |
||
335 | |||
336 | /** |
||
337 | * Assigns the subtree to the given section |
||
338 | * this method overrides the current assigned section. |
||
339 | * |
||
340 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException |
||
341 | * |
||
342 | * @param \eZ\Publish\API\Repository\Values\Content\Location $location |
||
343 | * @param \eZ\Publish\API\Repository\Values\Content\Section $section |
||
344 | */ |
||
345 | public function assignSectionToSubtree(Location $location, Section $section): void |
||
398 | |||
399 | /** |
||
400 | * Deletes $section from content repository. |
||
401 | * |
||
402 | * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the specified section is not found |
||
403 | * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is not allowed to delete a section |
||
404 | * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException If section can not be deleted |
||
405 | * because it is still assigned to some contents, |
||
406 | * or because it is still being used in policy limitations. |
||
407 | * |
||
408 | * @param \eZ\Publish\API\Repository\Values\Content\Section $section |
||
409 | */ |
||
410 | public function deleteSection(Section $section) |
||
435 | |||
436 | /** |
||
437 | * Instantiates a new SectionCreateStruct. |
||
438 | * |
||
439 | * @return \eZ\Publish\API\Repository\Values\Content\SectionCreateStruct |
||
440 | */ |
||
441 | public function newSectionCreateStruct() |
||
445 | |||
446 | /** |
||
447 | * Instantiates a new SectionUpdateStruct. |
||
448 | * |
||
449 | * @return \eZ\Publish\API\Repository\Values\Content\SectionUpdateStruct |
||
450 | */ |
||
451 | public function newSectionUpdateStruct() |
||
455 | |||
456 | /** |
||
457 | * Builds API Section object from provided SPI Section object. |
||
458 | * |
||
459 | * @param \eZ\Publish\SPI\Persistence\Content\Section $spiSection |
||
460 | * |
||
461 | * @return \eZ\Publish\API\Repository\Values\Content\Section |
||
462 | */ |
||
463 | protected function buildDomainSectionObject(SPISection $spiSection) |
||
473 | } |
||
474 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.