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 EntityRepository 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 EntityRepository, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | class EntityRepository |
||
9 | { |
||
10 | /** |
||
11 | * REST Client. |
||
12 | * |
||
13 | * @var RestClient |
||
14 | */ |
||
15 | protected $restClient; |
||
16 | |||
17 | /** |
||
18 | * SDK Client. |
||
19 | * |
||
20 | * @var SdkClient |
||
21 | */ |
||
22 | protected $sdk; |
||
23 | |||
24 | /** |
||
25 | * @var string |
||
26 | */ |
||
27 | protected $entityName; |
||
28 | |||
29 | /** |
||
30 | * classMetadataCache |
||
31 | * |
||
32 | * @var ClassMetadata |
||
33 | * @access private |
||
34 | */ |
||
35 | private $classMetadataCache; |
||
36 | |||
37 | /** |
||
38 | * EntityRepository constructor |
||
39 | * |
||
40 | * @param SdkClient $sdkClient The client to connect to the datasource with |
||
41 | * @param RestClient $restClient The client to process the http requests |
||
42 | * @param string $entityName The entity to work with |
||
43 | */ |
||
44 | public function __construct(SdkClient $sdkClient, RestClient $restClient, $entityName) |
||
50 | |||
51 | /** |
||
52 | * find - finds one item of the entity based on the @REST\Id field in the entity |
||
53 | * |
||
54 | * @param string $id id of the element to fetch |
||
55 | * @param array $queryParams query parameters to add to the query |
||
56 | * @access public |
||
57 | * @return object |
||
58 | */ |
||
59 | public function find($id, $queryParams = []) |
||
80 | |||
81 | /** |
||
82 | * findAll |
||
83 | * |
||
84 | * @access public |
||
85 | * @return array |
||
86 | */ |
||
87 | public function findAll() |
||
117 | |||
118 | /** |
||
119 | * remove |
||
120 | * |
||
121 | * @param object $model |
||
122 | * @access public |
||
123 | * @return void |
||
124 | * |
||
125 | * @TODO STILL NEEDS TO BE CONVERTED TO ENTITY MODEL |
||
126 | */ |
||
127 | public function remove($model) |
||
134 | |||
135 | /** |
||
136 | * update |
||
137 | * |
||
138 | * @param object $model |
||
139 | * @access public |
||
140 | * @return void |
||
141 | */ |
||
142 | public function update($model, $serializationContext = []) |
||
154 | |||
155 | /** |
||
156 | * persist |
||
157 | * |
||
158 | * @param object $model |
||
159 | * @access public |
||
160 | * @return void |
||
161 | */ |
||
162 | public function persist($model, $serializationContext = []) |
||
174 | |||
175 | /** |
||
176 | * Adds support for magic finders. |
||
177 | * |
||
178 | * @param string $method |
||
179 | * @param mixed $arguments |
||
180 | * |
||
181 | * @return array|object The found entity/entities. |
||
182 | */ |
||
183 | public function __call($method, $arguments) |
||
252 | |||
253 | /** |
||
254 | * convertQueryParameters |
||
255 | * |
||
256 | * @param array $queryParameters |
||
257 | * @access private |
||
258 | * @return array |
||
259 | */ |
||
260 | private function convertQueryParameters($queryParameters) |
||
290 | |||
291 | /** |
||
292 | * fetchFromCache |
||
293 | * |
||
294 | * @access private |
||
295 | * @param string $key |
||
296 | * @return object|false |
||
297 | */ |
||
298 | private function fetchFromCache($key) |
||
313 | |||
314 | /** |
||
315 | * saveToCache |
||
316 | * |
||
317 | * @access private |
||
318 | * @return object |
||
319 | */ |
||
320 | private function saveToCache($key, $value) |
||
334 | |||
335 | /** |
||
336 | * normalizeCacheKey |
||
337 | * |
||
338 | * @access private |
||
339 | * @return string |
||
340 | */ |
||
341 | private function normalizeCacheKey($key) |
||
345 | |||
346 | /** |
||
347 | * removeFromCache |
||
348 | * |
||
349 | * @param string $key |
||
350 | * @access private |
||
351 | * @return boolean true if no cache or cache successfully cleared, false otherwise |
||
352 | */ |
||
353 | private function removeFromCache($key) |
||
367 | |||
368 | /** |
||
369 | * addQueryParameter |
||
370 | * |
||
371 | * @param string $path path to call |
||
372 | * @param array $params query parameters to add |
||
373 | * @access private |
||
374 | * @return string |
||
375 | */ |
||
376 | private function addQueryParameter($path, $params = []) |
||
384 | |||
385 | private function getClassMetadata() |
||
395 | |||
396 | private function getIdentifier($entity) |
||
411 | } |
||
412 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.