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 Builder 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 Builder, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
31 | class Builder extends \Doctrine\MongoDB\Query\Builder |
||
32 | { |
||
33 | /** |
||
34 | * The DocumentManager instance for this query |
||
35 | * |
||
36 | * @var DocumentManager |
||
37 | */ |
||
38 | private $dm; |
||
39 | |||
40 | /** |
||
41 | * The ClassMetadata instance. |
||
42 | * |
||
43 | * @var \Doctrine\ODM\MongoDB\Mapping\ClassMetadata |
||
44 | */ |
||
45 | private $class; |
||
46 | |||
47 | /** |
||
48 | * The current field we are operating on. |
||
49 | * |
||
50 | * @todo Change this to private once ODM requires doctrine/mongodb 1.1+ |
||
51 | * @var string |
||
52 | */ |
||
53 | protected $currentField; |
||
54 | |||
55 | /** |
||
56 | * Whether or not to hydrate the data to documents. |
||
57 | * |
||
58 | * @var boolean |
||
59 | */ |
||
60 | private $hydrate = true; |
||
61 | |||
62 | /** |
||
63 | * Whether or not to refresh the data for documents that are already in the identity map. |
||
64 | * |
||
65 | * @var boolean |
||
66 | */ |
||
67 | private $refresh = false; |
||
68 | |||
69 | /** |
||
70 | * Array of primer Closure instances. |
||
71 | * |
||
72 | * @var array |
||
73 | */ |
||
74 | private $primers = array(); |
||
75 | |||
76 | /** |
||
77 | * Whether or not to require indexes. |
||
78 | * |
||
79 | * @var bool |
||
80 | */ |
||
81 | private $requireIndexes; |
||
82 | |||
83 | /** |
||
84 | * Whether or not to register documents in UnitOfWork. |
||
85 | * |
||
86 | * @var bool |
||
87 | */ |
||
88 | private $readOnly; |
||
89 | |||
90 | /** |
||
91 | * Construct a Builder |
||
92 | * |
||
93 | * @param DocumentManager $dm |
||
94 | * @param string[]|string|null $documentName (optional) an array of document names, the document name, or none |
||
95 | */ |
||
96 | 232 | public function __construct(DocumentManager $dm, $documentName = null) |
|
104 | |||
105 | /** |
||
106 | * Set whether or not to require indexes. |
||
107 | * |
||
108 | * @param bool $requireIndexes |
||
109 | * @return $this |
||
110 | * |
||
111 | * @deprecated method was deprecated in 1.2 and will be removed in 2.0 |
||
112 | */ |
||
113 | 2 | public function requireIndexes($requireIndexes = true) |
|
118 | |||
119 | /** |
||
120 | * Set the current field to operate on. |
||
121 | * |
||
122 | * @param string $field |
||
123 | * @return $this |
||
124 | */ |
||
125 | 155 | public function field($field) |
|
132 | |||
133 | /** |
||
134 | * Use a primer to eagerly load all references in the current field. |
||
135 | * |
||
136 | * If $primer is true or a callable is provided, referenced documents for |
||
137 | * this field will loaded into UnitOfWork immediately after the query is |
||
138 | * executed. This will avoid multiple queries due to lazy initialization of |
||
139 | * Proxy objects. |
||
140 | * |
||
141 | * If $primer is false, no priming will take place. That is also the default |
||
142 | * behavior. |
||
143 | * |
||
144 | * If a custom callable is used, its signature should conform to the default |
||
145 | * Closure defined in {@link ReferencePrimer::__construct()}. |
||
146 | * |
||
147 | * @param boolean|callable $primer |
||
148 | * @return $this |
||
149 | * @throws \InvalidArgumentException If $primer is not boolean or callable |
||
150 | */ |
||
151 | 27 | public function prime($primer = true) |
|
170 | |||
171 | /** |
||
172 | * {@inheritdoc} |
||
173 | */ |
||
174 | 6 | public function eagerCursor($bool = true) |
|
182 | |||
183 | |||
184 | /** |
||
185 | * @param bool $bool |
||
186 | * @return $this |
||
187 | */ |
||
188 | 16 | public function hydrate($bool = true) |
|
193 | |||
194 | /** |
||
195 | * @param bool $bool |
||
196 | * @return $this |
||
197 | */ |
||
198 | 2 | public function readOnly($bool = true) |
|
199 | { |
||
200 | 2 | $this->readOnly = $bool; |
|
201 | 2 | return $this; |
|
202 | } |
||
203 | |||
204 | /** |
||
205 | * @param bool $bool |
||
206 | * @return $this |
||
207 | */ |
||
208 | 5 | public function refresh($bool = true) |
|
213 | |||
214 | /** |
||
215 | * Change the query type to find and optionally set and change the class being queried. |
||
216 | * |
||
217 | * @param string $documentName |
||
218 | * @return $this |
||
219 | */ |
||
220 | 12 | public function find($documentName = null) |
|
227 | |||
228 | /** |
||
229 | * @param string $documentName |
||
230 | * @return $this |
||
231 | */ |
||
232 | 13 | public function findAndUpdate($documentName = null) |
|
239 | |||
240 | /** |
||
241 | * @param bool $bool |
||
242 | * @return $this |
||
243 | */ |
||
244 | 4 | public function returnNew($bool = true) |
|
251 | |||
252 | /** |
||
253 | * @param string $documentName |
||
254 | * @return $this |
||
255 | */ |
||
256 | 1 | public function findAndRemove($documentName = null) |
|
263 | |||
264 | /** |
||
265 | * @param string $documentName |
||
266 | * @return $this |
||
267 | * |
||
268 | * @deprecated Deprecated in version 1.2 - use updateOne or updateMany instead |
||
269 | */ |
||
270 | 12 | public function update($documentName = null) |
|
277 | |||
278 | /** |
||
279 | * @param string $documentName |
||
280 | * @return $this |
||
281 | */ |
||
282 | public function updateOne($documentName = null) |
||
289 | |||
290 | /** |
||
291 | * @param string $documentName |
||
292 | * @return $this |
||
293 | */ |
||
294 | public function updateMany($documentName = null) |
||
301 | |||
302 | /** |
||
303 | * @param string $documentName |
||
304 | * @return $this |
||
305 | */ |
||
306 | 1 | public function insert($documentName = null) |
|
313 | |||
314 | /** |
||
315 | * @param string $documentName |
||
316 | * @return $this |
||
317 | */ |
||
318 | 1 | public function remove($documentName = null) |
|
325 | |||
326 | /** |
||
327 | * @param object $document |
||
328 | * @return $this |
||
329 | */ |
||
330 | 11 | public function references($document) |
|
335 | |||
336 | /** |
||
337 | * @param object $document |
||
338 | * @return $this |
||
339 | */ |
||
340 | 7 | public function includesReferenceTo($document) |
|
345 | |||
346 | /** |
||
347 | * @inheritdoc |
||
348 | * @deprecated Deprecated in version 1.2 - use Aggregation Builder's group stage instead. |
||
349 | */ |
||
350 | 1 | public function group($keys, array $initial, $reduce = null, array $options = []) |
|
358 | |||
359 | /** |
||
360 | * Gets the Query executable. |
||
361 | * |
||
362 | * @param array $options |
||
363 | * @return Query $query |
||
364 | */ |
||
365 | 201 | public function getQuery(array $options = array()) |
|
423 | |||
424 | /** |
||
425 | * Create a new Expr instance that can be used as an expression with the Builder |
||
426 | * |
||
427 | * @return Expr $expr |
||
428 | */ |
||
429 | 25 | public function expr() |
|
436 | |||
437 | /** |
||
438 | * @param string[]|string $documentName an array of document names or just one. |
||
439 | */ |
||
440 | 231 | private function setDocumentName($documentName) |
|
466 | |||
467 | /** |
||
468 | * Get Discriminator Values |
||
469 | * |
||
470 | * @param \Iterator|array $classNames |
||
471 | * @return array an array of discriminatorValues (mixed type) |
||
472 | * @throws \InvalidArgumentException if the number of found collections > 1 |
||
473 | */ |
||
474 | 2 | private function getDiscriminatorValues($classNames) |
|
489 | } |
||
490 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.