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 DataTableAPI 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 DataTableAPI, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
9 | class DataTableAPI extends RestAPI |
||
10 | { |
||
11 | protected $dataSetName; |
||
12 | protected $dataTableName; |
||
13 | protected $primaryKeyName; |
||
14 | |||
15 | /** |
||
16 | * Create the DataTableAPI for the given DataTable info |
||
17 | * |
||
18 | * @param string $datSetName The name of the DataSet used in the Settings |
||
|
|||
19 | * @param string $dataTableName The name of the table in the DataSet |
||
20 | * @param string|false $primaryKeyName The table primary key. Must be specified for update/delete capable tables |
||
21 | */ |
||
22 | public function __construct($dataSetName, $dataTableName, $primaryKeyName = false) |
||
28 | |||
29 | public function setup($app) |
||
40 | |||
41 | protected function getDataTable() |
||
45 | |||
46 | protected function canRead($request) |
||
52 | |||
53 | protected function canCreate($request) |
||
58 | |||
59 | protected function canUpdate($request, $entity) |
||
64 | |||
65 | protected function canDelete($request, $entity) |
||
70 | |||
71 | protected function getFilterForPrimaryKey($value) |
||
75 | |||
76 | protected function manipulateParameters($request, &$odata) |
||
80 | |||
81 | protected function validateCreate(&$obj, $request) |
||
85 | |||
86 | protected function validateUpdate(&$newObj, $request, $oldObj) |
||
90 | |||
91 | protected function postUpdateAction($newObj, $request, $oldObj) |
||
95 | |||
96 | protected function postDeleteAction($entry) |
||
100 | |||
101 | public function readEntries($request, $response, $args) |
||
131 | |||
132 | public function createEntry($request, $response, $args) |
||
151 | |||
152 | public function readEntry($request, $response, $args) |
||
173 | |||
174 | public function updateEntry($request, $response, $args) |
||
175 | { |
||
176 | if($this->canRead($request) === false) |
||
177 | { |
||
178 | return $response->withStatus(401); |
||
179 | } |
||
180 | $filter = $this->getFilterForPrimaryKey($args['name']); |
||
181 | $dataTable = $this->getDataTable(); |
||
182 | $entry = $dataTable->read($filter); |
||
183 | if(empty($entry)) |
||
184 | { |
||
185 | return $response->withStatus(404); |
||
186 | } |
||
187 | if(count($entry) === 1 && isset($entry[0])) |
||
188 | { |
||
189 | $entry = $entry[0]; |
||
190 | } |
||
191 | if($this->canUpdate($request, $entry) === false) |
||
192 | { |
||
193 | return $response->withStatus(401); |
||
194 | } |
||
195 | $obj = $request->getParsedBody(); |
||
196 | View Code Duplication | if($obj === null) |
|
197 | { |
||
198 | $request->getBody()->rewind(); |
||
199 | $obj = $request->getBody()->getContents(); |
||
200 | $tmp = json_decode($obj, true); |
||
201 | if($tmp !== null) |
||
202 | { |
||
203 | $obj = $tmp; |
||
204 | } |
||
205 | } |
||
206 | if($this->validateUpdate($obj, $request, $entry) === false) |
||
207 | { |
||
208 | return $response->withStatus(400); |
||
209 | } |
||
210 | $ret = $dataTable->update($filter, $obj); |
||
211 | if($ret) |
||
212 | { |
||
213 | $ret = $this->postUpdateAction($obj, $request, $entry); |
||
214 | } |
||
215 | return $response->withJson($ret); |
||
216 | } |
||
217 | |||
218 | public function deleteEntry($request, $response, $args) |
||
246 | } |
||
247 |
This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.
Consider the following example. The parameter
$ireland
is not defined by the methodfinale(...)
.The most likely cause is that the parameter was changed, but the annotation was not.