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:
1 | <?php |
||
32 | class BandController extends RestController |
||
33 | { |
||
34 | |||
35 | /** |
||
36 | * List all registered bands |
||
37 | * @Route("s/{limit}/{offset}", name="bands_list") |
||
38 | * @Method("GET") |
||
39 | * @ApiDoc( |
||
40 | * section="Band", |
||
41 | * statusCodes={ |
||
42 | * 200="OK", |
||
43 | * } |
||
44 | * ) |
||
45 | * @param int $limit Limit results. Default is 50 |
||
46 | * @param int $offset Starting serial number of result collection. Default is 0 |
||
47 | */ |
||
48 | 2 | public function listAction($limit = null, $offset = null): Response |
|
52 | |||
53 | /** |
||
54 | * View band by name |
||
55 | * @Route("/{id}", name="band_view") |
||
56 | * @Method("GET") |
||
57 | * @ApiDoc( |
||
58 | * section="Band", |
||
59 | * statusCodes={ |
||
60 | * 200="Band was found", |
||
61 | * 404="Band with given name was not found", |
||
62 | * } |
||
63 | * ) |
||
64 | * @param string $id band name |
||
65 | */ |
||
66 | 3 | public function viewAction(string $id): Response |
|
70 | |||
71 | /** |
||
72 | * Create new band |
||
73 | * @Route("", name="band_create") |
||
74 | * @Method("POST") |
||
75 | * @Security("has_role('ROLE_USER')") |
||
76 | * @ApiDoc( |
||
77 | * section="Band", |
||
78 | * requirements={ |
||
79 | * { |
||
80 | * "name"="name", |
||
81 | * "dataType"="string", |
||
82 | * "requirement"="true", |
||
83 | * "description"="band name" |
||
84 | * }, |
||
85 | * { |
||
86 | * "name"="description", |
||
87 | * "dataType"="string", |
||
88 | * "requirement"="true", |
||
89 | * "description"="band description" |
||
90 | * }, |
||
91 | * { |
||
92 | * "name"="members", |
||
93 | * "dataType"="array", |
||
94 | * "requirement"="false", |
||
95 | * "description"="logins and short descriptions of band musicians" |
||
96 | * }, |
||
97 | * }, |
||
98 | * statusCodes={ |
||
99 | * 201="New band was created. Link to new resource provided in header 'Location'", |
||
100 | * 400="Validation error", |
||
101 | * } |
||
102 | * ) |
||
103 | */ |
||
104 | 2 | View Code Duplication | public function createAction(Request $request): Response |
118 | |||
119 | /** |
||
120 | * Edit band |
||
121 | * @Route("/{bandName}", name="band_edit") |
||
122 | * @Method("PUT") |
||
123 | * @Security("has_role('ROLE_USER')") |
||
124 | * @ApiDoc( |
||
125 | * section="Band", |
||
126 | * requirements={ |
||
127 | * { |
||
128 | * "name"="name", |
||
129 | * "dataType"="string", |
||
130 | * "requirement"="true", |
||
131 | * "description"="band name" |
||
132 | * }, |
||
133 | * { |
||
134 | * "name"="description", |
||
135 | * "dataType"="string", |
||
136 | * "requirement"="true", |
||
137 | * "description"="band description" |
||
138 | * }, |
||
139 | * { |
||
140 | * "name"="users", |
||
141 | * "dataType"="array", |
||
142 | * "requirement"="true", |
||
143 | * "description"="logins of band musicians" |
||
144 | * }, |
||
145 | * }, |
||
146 | * statusCodes={ |
||
147 | * 204="Band was edited with new data", |
||
148 | * 400="Validation error", |
||
149 | * } |
||
150 | * ) |
||
151 | * @param string $bandName band name |
||
152 | */ |
||
153 | 2 | public function editAction(Request $request, string $bandName): Response |
|
166 | |||
167 | /** |
||
168 | * List all band members |
||
169 | * @Route("/{bandName}/members", name="band_members") |
||
170 | * @Method("GET") |
||
171 | * @ApiDoc( |
||
172 | * section="Band", |
||
173 | * statusCodes={ |
||
174 | * 200="OK", |
||
175 | * 404="Band was not found", |
||
176 | * } |
||
177 | * ) |
||
178 | */ |
||
179 | 4 | View Code Duplication | public function listMembersAction(string $bandName): Response |
192 | |||
193 | /** |
||
194 | * Add member to band |
||
195 | * @Route("/{bandName}/members", name="band_member_create") |
||
196 | * @Method("POST") |
||
197 | * @Security("has_role('ROLE_USER')") |
||
198 | * @ApiDoc( |
||
199 | * section="Band", |
||
200 | * requirements={ |
||
201 | * { |
||
202 | * "name"="login", |
||
203 | * "dataType"="string", |
||
204 | * "requirement"="true", |
||
205 | * "description"="user login" |
||
206 | * }, |
||
207 | * { |
||
208 | * "name"="short_description", |
||
209 | * "dataType"="string", |
||
210 | * "requirement"="true", |
||
211 | * "description"="short description of musicians role in band" |
||
212 | * }, |
||
213 | * { |
||
214 | * "name"="description", |
||
215 | * "dataType"="string", |
||
216 | * "requirement"="false", |
||
217 | * "description"="long description of musician" |
||
218 | * }, |
||
219 | * }, |
||
220 | * statusCodes={ |
||
221 | * 200="Member was added to the band", |
||
222 | * 400="Validation error", |
||
223 | * } |
||
224 | * ) |
||
225 | * @param string $bandName band name |
||
226 | */ |
||
227 | 1 | public function createMemberAction(Request $request, string $bandName): Response |
|
267 | |||
268 | /** |
||
269 | * Delete member from band |
||
270 | * @Route("/{bandName}/member/{userLogin}", name="band_member_delete") |
||
271 | * @Method("DELETE") |
||
272 | * @Security("has_role('ROLE_USER')") |
||
273 | * @ApiDoc( |
||
274 | * section="Band", |
||
275 | * statusCodes={ |
||
276 | * 204="Member was deleted from the band", |
||
277 | * 404="Band or user was not found", |
||
278 | * } |
||
279 | * ) |
||
280 | * @param string $bandName band name |
||
281 | * @param string $userLogin member login |
||
282 | */ |
||
283 | 1 | public function deleteMemberAction(string $bandName, string $userLogin) |
|
313 | |||
314 | /** |
||
315 | * Update band member |
||
316 | * @Route("/{bandName}/member", name="band_member_update") |
||
317 | * @Method("PUT") |
||
318 | * @Security("has_role('ROLE_USER')") |
||
319 | * @ApiDoc( |
||
320 | * section="Band", |
||
321 | * requirements={ |
||
322 | * { |
||
323 | * "name"="login", |
||
324 | * "dataType"="string", |
||
325 | * "requirement"="true", |
||
326 | * "description"="login of musician" |
||
327 | * }, |
||
328 | * { |
||
329 | * "name"="short_description", |
||
330 | * "dataType"="string", |
||
331 | * "requirement"="true", |
||
332 | * "description"="short description of role in band" |
||
333 | * }, |
||
334 | * { |
||
335 | * "name"="description", |
||
336 | * "dataType"="string", |
||
337 | * "requirement"="false", |
||
338 | * "description"="long description of musician" |
||
339 | * }, |
||
340 | * }, |
||
341 | * statusCodes={ |
||
342 | * 204="Band member was successfully updated", |
||
343 | * 404="Band or user was not found", |
||
344 | * } |
||
345 | * ) |
||
346 | * @param string $bandName band name |
||
347 | * @param string $userLogin member login |
||
348 | */ |
||
349 | 1 | public function updateMemberAction(Request $request, string $bandName) |
|
383 | |||
384 | /** |
||
385 | * @return ApiError|CreatedApiResponse|EmptyApiResponse |
||
386 | */ |
||
387 | 3 | private function createResponseFromUpdateForm(FormInterface $form): AbstractApiResponse |
|
395 | } |
||
396 |
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.