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 QueryBuilderTrait 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 QueryBuilderTrait, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
8 | trait QueryBuilderTrait |
||
9 | { |
||
10 | /** |
||
11 | * @var |
||
12 | */ |
||
13 | protected $options = []; |
||
14 | |||
15 | /** |
||
16 | * @var |
||
17 | */ |
||
18 | protected $where = []; |
||
19 | |||
20 | /** |
||
21 | * @var |
||
22 | */ |
||
23 | protected $properties = []; |
||
24 | |||
25 | /** |
||
26 | * @var |
||
27 | */ |
||
28 | protected $isLazyCollection = false; |
||
29 | |||
30 | /** |
||
31 | * @var |
||
32 | */ |
||
33 | protected $isCollection = true; |
||
34 | |||
35 | /** |
||
36 | * @var |
||
37 | */ |
||
38 | protected $isOriginal = false; |
||
39 | |||
40 | /** |
||
41 | * Retrieve all Items. |
||
42 | * |
||
43 | * @param array $options |
||
44 | * |
||
45 | * @return array |
||
46 | */ |
||
47 | View Code Duplication | protected function all($options = []) |
|
|
|||
48 | { |
||
49 | if ($this->isLazyCollection) { |
||
50 | return LazyCollection::make(WooCommerce::all($this->endpoint, $options)); |
||
51 | } |
||
52 | |||
53 | if ($this->isCollection) { |
||
54 | return collect(WooCommerce::all($this->endpoint, $options)); |
||
55 | } |
||
56 | |||
57 | return WooCommerce::all($this->endpoint, $options); |
||
58 | } |
||
59 | |||
60 | /** |
||
61 | * Retrieve single Item. |
||
62 | * |
||
63 | * @param int $id |
||
64 | * @param array $options |
||
65 | * |
||
66 | * @return object |
||
67 | */ |
||
68 | protected function find($id, $options = []) |
||
69 | { |
||
70 | if ($this->isLazyCollection) { |
||
71 | return LazyCollection::make(WooCommerce::find("{$this->endpoint}/{$id}", $options)); |
||
72 | } |
||
73 | |||
74 | if ($this->isCollection) { |
||
75 | return collect(WooCommerce::find("{$this->endpoint}/{$id}", $options)); |
||
76 | } |
||
77 | |||
78 | return WooCommerce::find("{$this->endpoint}/{$id}", $options); |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * Create new Item. |
||
83 | * |
||
84 | * @param array $data |
||
85 | * |
||
86 | * @return object |
||
87 | */ |
||
88 | View Code Duplication | protected function create($data) |
|
89 | { |
||
90 | if ($this->isLazyCollection) { |
||
91 | return LazyCollection::make(WooCommerce::create($this->endpoint, $data)); |
||
92 | } |
||
93 | |||
94 | if ($this->isCollection) { |
||
95 | return collect(WooCommerce::create($this->endpoint, $data)); |
||
96 | } |
||
97 | |||
98 | return WooCommerce::create($this->endpoint, $data); |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * Update Existing Item. |
||
103 | * |
||
104 | * @param int $id |
||
105 | * @param array $data |
||
106 | * |
||
107 | * @return object |
||
108 | */ |
||
109 | View Code Duplication | protected function update($id, $data) |
|
110 | { |
||
111 | if ($this->isLazyCollection) { |
||
112 | return LazyCollection::make(WooCommerce::update("{$this->endpoint}/{$id}", $data)); |
||
113 | } |
||
114 | |||
115 | if ($this->isCollection) { |
||
116 | return collect(WooCommerce::update("{$this->endpoint}/{$id}", $data)); |
||
117 | } |
||
118 | |||
119 | return WooCommerce::update("{$this->endpoint}/{$id}", $data); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Destroy Item. |
||
124 | * |
||
125 | * @param int $id |
||
126 | * @param array $options |
||
127 | * |
||
128 | * @return object |
||
129 | */ |
||
130 | protected function delete($id, $options = []) |
||
131 | { |
||
132 | if ($this->isLazyCollection) { |
||
133 | return LazyCollection::make(WooCommerce::delete("{$this->endpoint}/{$id}", $options)); |
||
134 | } |
||
135 | |||
136 | if ($this->isCollection) { |
||
137 | return collect(WooCommerce::delete("{$this->endpoint}/{$id}", $options)); |
||
138 | } |
||
139 | |||
140 | return WooCommerce::delete("{$this->endpoint}/{$id}", $options); |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Batch Update. |
||
145 | * |
||
146 | * @param array $data |
||
147 | * |
||
148 | * @return object |
||
149 | */ |
||
150 | View Code Duplication | protected function batch($data) |
|
151 | { |
||
152 | if ($this->isLazyCollection) { |
||
153 | return LazyCollection::make(WooCommerce::create("{$this->endpoint}/batch", $data)); |
||
154 | } |
||
155 | |||
156 | if ($this->isCollection) { |
||
157 | return collect(WooCommerce::create("{$this->endpoint}/batch", $data)); |
||
158 | } |
||
159 | |||
160 | return WooCommerce::create("{$this->endpoint}/batch", $data); |
||
161 | } |
||
162 | |||
163 | /** |
||
164 | * Retrieve data. |
||
165 | * |
||
166 | * @return array |
||
167 | */ |
||
168 | View Code Duplication | protected function get() |
|
169 | { |
||
170 | if ($this->isLazyCollection) { |
||
171 | return LazyCollection::make(WooCommerce::all($this->endpoint, $this->options)); |
||
172 | } |
||
173 | |||
174 | if ($this->isCollection) { |
||
175 | return collect(WooCommerce::all($this->endpoint, $this->options)); |
||
176 | } |
||
177 | |||
178 | return WooCommerce::all($this->endpoint, $this->options); |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Retrieve data. |
||
183 | * |
||
184 | * @return object |
||
185 | */ |
||
186 | protected function first() |
||
187 | { |
||
188 | if ($this->isLazyCollection) { |
||
189 | return LazyCollection::make($this->get()[0] ?? new \stdClass()); |
||
190 | } |
||
191 | |||
192 | if ($this->isCollection) { |
||
193 | return collect($this->get()[0] ?? new \stdClass()); |
||
194 | } |
||
195 | |||
196 | return collect($this->get()[0] ?? new \stdClass()); |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Set original. |
||
201 | * |
||
202 | * @return object $this |
||
203 | */ |
||
204 | View Code Duplication | protected function withOriginal() |
|
212 | |||
213 | /** |
||
214 | * Set collection. |
||
215 | * |
||
216 | * @return object $this |
||
217 | */ |
||
218 | View Code Duplication | protected function withCollection() |
|
219 | { |
||
220 | $this->isOriginal = false; |
||
221 | $this->isCollection = true; |
||
222 | $this->isLazyCollection = false; |
||
223 | |||
224 | return $this; |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * Set lazy collection. |
||
229 | * |
||
230 | * @return object $this |
||
231 | */ |
||
232 | View Code Duplication | protected function withLazyCollection() |
|
240 | |||
241 | /** |
||
242 | * Set options for woocommerce request. |
||
243 | * |
||
244 | * @param array $parameters |
||
245 | * |
||
246 | * @return object $this |
||
247 | */ |
||
248 | protected function options($parameters) |
||
249 | { |
||
264 | |||
265 | /** |
||
266 | * Join options for woocommerce request. |
||
267 | * |
||
268 | * @param array $parameters |
||
269 | * |
||
270 | * @return object $this |
||
271 | */ |
||
272 | protected function where(...$parameters) |
||
291 | |||
292 | /** |
||
293 | * Set order direction. |
||
294 | * |
||
295 | * @param string $name |
||
296 | * @param string $direction |
||
297 | * |
||
298 | * @return object $this |
||
299 | */ |
||
300 | protected function orderBy($name, $direction = 'desc') |
||
307 | |||
308 | /** |
||
309 | * Paginate results. |
||
310 | * |
||
311 | * @param int $per_page |
||
312 | * @param int $current_page |
||
313 | * @param array $options |
||
314 | * |
||
315 | * @return array |
||
316 | */ |
||
317 | protected function paginate($per_page = 10, $current_page = 1, $options = []) |
||
365 | |||
366 | /** |
||
367 | * Count all results. |
||
368 | * |
||
369 | * @return int |
||
370 | */ |
||
371 | protected function count() |
||
382 | |||
383 | /** |
||
384 | * Store data. |
||
385 | * |
||
386 | * @return array |
||
387 | */ |
||
388 | View Code Duplication | public function save() |
|
402 | } |
||
403 |
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.