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 TableNode 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 TableNode, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class TableNode implements ArgumentInterface, IteratorAggregate |
||
24 | { |
||
25 | /** |
||
26 | * @var array |
||
27 | */ |
||
28 | private $table; |
||
29 | /** |
||
30 | * @var integer |
||
31 | */ |
||
32 | private $maxLineLength = array(); |
||
33 | |||
34 | /** |
||
35 | * Initializes table. |
||
36 | * |
||
37 | * @param array $table Table in form of [$rowLineNumber => [$val1, $val2, $val3]] |
||
38 | * |
||
39 | * @throws NodeException If the given table is invalid |
||
40 | */ |
||
41 | 251 | public function __construct(array $table) |
|
87 | |||
88 | /** |
||
89 | * Creates a table from a given list. |
||
90 | * |
||
91 | * @param array $list One-dimensional array |
||
92 | * |
||
93 | * @return TableNode |
||
94 | * |
||
95 | * @throws NodeException If the given list is not a one-dimensional array |
||
96 | */ |
||
97 | 2 | public static function fromList(array $list) |
|
98 | { |
||
99 | 2 | if (count($list) !== count($list, COUNT_RECURSIVE)) { |
|
100 | 1 | throw new NodeException('List is not a one-dimensional array.'); |
|
101 | } |
||
102 | |||
103 | array_walk($list, function (&$item) { |
||
104 | 1 | $item = array($item); |
|
105 | 1 | }); |
|
106 | 1 | return new self($list); |
|
107 | } |
||
108 | |||
109 | /** |
||
110 | * Returns node type. |
||
111 | * |
||
112 | * @return string |
||
113 | */ |
||
114 | public function getNodeType() |
||
118 | |||
119 | /** |
||
120 | * Returns table hash, formed by columns (ColumnsHash). |
||
121 | * |
||
122 | * @return array |
||
123 | */ |
||
124 | 4 | public function getHash() |
|
128 | |||
129 | /** |
||
130 | * Returns table hash, formed by columns. |
||
131 | * |
||
132 | * @return array |
||
133 | */ |
||
134 | 10 | public function getColumnsHash() |
|
146 | |||
147 | /** |
||
148 | * Returns table hash, formed by rows. |
||
149 | * |
||
150 | * @return array |
||
151 | */ |
||
152 | 2 | public function getRowsHash() |
|
162 | |||
163 | /** |
||
164 | * Returns numerated table lines. |
||
165 | * Line numbers are keys, lines are values. |
||
166 | * |
||
167 | * @return array |
||
168 | */ |
||
169 | 14 | public function getTable() |
|
173 | |||
174 | /** |
||
175 | * Returns table rows. |
||
176 | * |
||
177 | * @return array |
||
178 | */ |
||
179 | 251 | public function getRows() |
|
183 | |||
184 | /** |
||
185 | * Returns table definition lines. |
||
186 | * |
||
187 | * @return array |
||
188 | */ |
||
189 | 11 | public function getLines() |
|
193 | |||
194 | /** |
||
195 | * Returns specific row in a table. |
||
196 | * |
||
197 | * @param integer $index Row number |
||
198 | * |
||
199 | * @return array |
||
200 | * |
||
201 | * @throws NodeException If row with specified index does not exist |
||
202 | */ |
||
203 | 17 | View Code Duplication | public function getRow($index) |
213 | |||
214 | /** |
||
215 | * Returns specific column in a table. |
||
216 | * |
||
217 | * @param integer $index Column number |
||
218 | * |
||
219 | * @return array |
||
220 | * |
||
221 | * @throws NodeException If column with specified index does not exist |
||
222 | */ |
||
223 | 1 | public function getColumn($index) |
|
238 | |||
239 | /** |
||
240 | * Returns line number at which specific row was defined. |
||
241 | * |
||
242 | * @param integer $index |
||
243 | * |
||
244 | * @return integer |
||
245 | * |
||
246 | * @throws NodeException If row with specified index does not exist |
||
247 | */ |
||
248 | 10 | View Code Duplication | public function getRowLine($index) |
258 | |||
259 | /** |
||
260 | * Converts row into delimited string. |
||
261 | * |
||
262 | * @param integer $rowNum Row number |
||
263 | * |
||
264 | * @return string |
||
265 | */ |
||
266 | 6 | public function getRowAsString($rowNum) |
|
275 | |||
276 | /** |
||
277 | * Converts row into delimited string. |
||
278 | * |
||
279 | * @param integer $rowNum Row number |
||
280 | * @param callable $wrapper Wrapper function |
||
281 | * |
||
282 | * @return string |
||
283 | */ |
||
284 | public function getRowAsStringWithWrappedValues($rowNum, $wrapper) |
||
295 | |||
296 | /** |
||
297 | * Converts entire table into string |
||
298 | * |
||
299 | * @return string |
||
300 | */ |
||
301 | 2 | public function getTableAsString() |
|
310 | |||
311 | /** |
||
312 | * Returns line number at which table was started. |
||
313 | * |
||
314 | * @return integer |
||
315 | */ |
||
316 | 5 | public function getLine() |
|
317 | { |
||
318 | 5 | return $this->getRowLine(0); |
|
319 | } |
||
320 | |||
321 | /** |
||
322 | * Converts table into string |
||
323 | * |
||
324 | * @return string |
||
325 | */ |
||
326 | public function __toString() |
||
330 | |||
331 | /** |
||
332 | * Retrieves a hash iterator. |
||
333 | * |
||
334 | * @return Iterator |
||
335 | */ |
||
336 | 1 | public function getIterator() |
|
340 | |||
341 | /** |
||
342 | * Obtains and adds rows from another table to the current table. |
||
343 | * The second table should have the same structure as the current one. |
||
344 | * @param TableNode $node |
||
345 | * |
||
346 | * @deprecated remove together with OutlineNode::getExampleTable |
||
347 | */ |
||
348 | 8 | public function mergeRowsFromTable(TableNode $node) |
|
364 | |||
365 | /** |
||
366 | * Pads string right. |
||
367 | * |
||
368 | * @param string $text Text to pad |
||
369 | * @param integer $length Length |
||
370 | * |
||
371 | * @return string |
||
372 | */ |
||
373 | 6 | protected function padRight($text, $length) |
|
381 | } |
||
382 |
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.