Complex classes like CsvFormat 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 CsvFormat, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class CsvFormat implements CsvFormatInterface |
||
20 | { |
||
21 | use GetOptionTrait; |
||
22 | |||
23 | const DEFAULT_DELIMITER = ','; |
||
24 | const DEFAULT_NULL = '\\N'; |
||
25 | const DEFAULT_HEADER_ROW = -1; |
||
26 | const DEFAULT_DATA_START = 1; |
||
27 | const DEFAULT_QUOTE = '"'; |
||
28 | const DEFAULT_ESCAPE = '\\'; |
||
29 | const DEFAULT_LIMIT = -1; |
||
30 | const DEFAULT_DOUBLE_QUOTE = false; |
||
31 | const DEFAULT_ENCODING = 'UTF-8'; |
||
32 | const DEFAULT_NEW_LINE = "\n"; |
||
33 | const DEFAULT_BOM = null; |
||
34 | |||
35 | const OPTION_DELIMITER = 'delimiter'; |
||
36 | const OPTION_NULL = 'null'; |
||
37 | const OPTION_HEADER_ROW = 'headerRow'; |
||
38 | const OPTION_DATA_START = 'dataStart'; |
||
39 | const OPTION_NEW_LINE = 'newLine'; |
||
40 | const OPTION_QUOTE = 'quote'; |
||
41 | const OPTION_ESCAPE = 'escape'; |
||
42 | const OPTION_LIMIT = 'limit'; |
||
43 | const OPTION_DOUBLE_QUOTE = 'doubleQuote'; |
||
44 | const OPTION_BOM = 'bom'; |
||
45 | const OPTION_ENCODING = 'encoding'; |
||
46 | |||
47 | /** @var string */ |
||
48 | protected $delimiter; |
||
49 | /** @var string */ |
||
50 | protected $quote; |
||
51 | /** @var string */ |
||
52 | protected $nullValue; |
||
53 | /** @var int */ |
||
54 | protected $headerRow; |
||
55 | /** @var string */ |
||
56 | protected $newLines; |
||
57 | /** @var string */ |
||
58 | protected $escape; |
||
59 | /** @var int */ |
||
60 | protected $limit; |
||
61 | /** @var bool */ |
||
62 | protected $doubleQuote; |
||
63 | /** @var int */ |
||
64 | protected $dataStart; |
||
65 | /** @var string */ |
||
66 | protected $boms; |
||
67 | /** @var string */ |
||
68 | protected $encoding; |
||
69 | |||
70 | /** |
||
71 | * @param array $options -delimiter <string> (Default: ,) Character to use between fields |
||
72 | * -quoteCharacter <string> (Default: ") |
||
73 | * -nullOutput <string> (Default: \N) |
||
74 | * -headerRow <int> (Default: -1) -1 for no header row. (1 is the first line of the file) |
||
75 | * -dataStart <int> (Default: 1) The line where the data starts (1 is the first list of the |
||
76 | * file) |
||
77 | * -lineTerminator <array> (Default: ["\n","\r","\r\n"]) |
||
78 | * -escape <string> (Default: \\) Character to use for escaping |
||
79 | * -limit <int> Total number of data rows to return |
||
80 | * -doubleQuote <bool> instances of quote in fields are indicated by a double quote |
||
81 | * -bom <array> (Default: BOM_ALL) Specify a ByteOrderMark for this file (see Bom::BOM_*) |
||
82 | * -encoding <string> (Default: UTF-8) Specify the encoding of the csv file |
||
83 | */ |
||
84 | 16 | public function __construct(array $options = []) |
|
99 | |||
100 | /** |
||
101 | * @return string |
||
102 | */ |
||
103 | 27 | public function getDelimiter() |
|
107 | |||
108 | /** |
||
109 | * @param string $delimiter |
||
110 | * |
||
111 | * @return static |
||
112 | */ |
||
113 | 2 | public function setDelimiter($delimiter) |
|
118 | |||
119 | /** |
||
120 | * @return string |
||
121 | */ |
||
122 | 26 | public function getQuote() |
|
126 | |||
127 | /** |
||
128 | * @return bool |
||
129 | */ |
||
130 | 20 | public function hasQuote() |
|
134 | |||
135 | /** |
||
136 | * @param string $quote |
||
137 | * |
||
138 | * @return static |
||
139 | */ |
||
140 | 1 | public function setQuote($quote) |
|
145 | |||
146 | /** |
||
147 | * @return string |
||
148 | */ |
||
149 | 16 | public function getNullValue() |
|
153 | |||
154 | /** |
||
155 | * @param string $nullValue |
||
156 | * |
||
157 | * @return static |
||
158 | */ |
||
159 | 1 | public function setNullValue($nullValue) |
|
164 | |||
165 | /** |
||
166 | * @return bool |
||
167 | */ |
||
168 | 13 | public function hasHeaderRow() |
|
172 | |||
173 | /** |
||
174 | * @param int $headerRow |
||
175 | * |
||
176 | * @return static |
||
177 | */ |
||
178 | 2 | public function setHeaderRow($headerRow) |
|
183 | |||
184 | /** |
||
185 | * @return int |
||
186 | */ |
||
187 | 7 | public function getHeaderRow() |
|
191 | |||
192 | /** |
||
193 | * @return int |
||
194 | */ |
||
195 | 13 | public function getDataStart() |
|
202 | |||
203 | /** |
||
204 | * @param int $row |
||
205 | * |
||
206 | * @return static |
||
207 | */ |
||
208 | 2 | public function setDataStart($row) |
|
213 | |||
214 | /** |
||
215 | * Type type of file format (defined in FileFormatType::) |
||
216 | * |
||
217 | * @return string |
||
218 | */ |
||
219 | 7 | public function getType() |
|
223 | |||
224 | /** |
||
225 | * @return string |
||
226 | */ |
||
227 | 29 | public function getEscape() |
|
231 | |||
232 | /** |
||
233 | * @param string $escape |
||
234 | * |
||
235 | * @return static |
||
236 | */ |
||
237 | 1 | public function setEscape($escape) |
|
242 | |||
243 | /** |
||
244 | * @return bool |
||
245 | */ |
||
246 | 3 | public function hasEscape() |
|
250 | |||
251 | /** |
||
252 | * Get the limit that should be returned (-1 for no limit) |
||
253 | * |
||
254 | * @return int |
||
255 | */ |
||
256 | 12 | public function getLimit() |
|
260 | |||
261 | /** |
||
262 | * Set the limit of the number of items to be returned (-1 for not limit) |
||
263 | * |
||
264 | * @param int $limit |
||
265 | * |
||
266 | * @return static |
||
267 | */ |
||
268 | 1 | public function setLimit($limit) |
|
273 | |||
274 | /** |
||
275 | * @return bool |
||
276 | */ |
||
277 | 24 | public function useDoubleQuotes() |
|
281 | |||
282 | /** |
||
283 | * @param bool $doubleQuote |
||
284 | * |
||
285 | * @return static |
||
286 | */ |
||
287 | 1 | public function setDoubleQuote($doubleQuote) |
|
292 | |||
293 | /** |
||
294 | * @param null|string[]|string $bom |
||
295 | * |
||
296 | * @return static |
||
297 | */ |
||
298 | 16 | public function setBom($bom) |
|
306 | |||
307 | /** |
||
308 | * @return string |
||
309 | */ |
||
310 | 24 | public function getEncoding() |
|
318 | |||
319 | /** |
||
320 | * @param string $encoding |
||
321 | * |
||
322 | * @return static |
||
323 | */ |
||
324 | 1 | public function setEncoding($encoding) |
|
329 | |||
330 | /** |
||
331 | * @return string[] |
||
332 | */ |
||
333 | 12 | public function getNewLines() |
|
337 | |||
338 | /** |
||
339 | * @param string|string[] $newLine |
||
340 | * |
||
341 | * @return static |
||
342 | */ |
||
343 | 16 | public function setNewLine($newLine) |
|
348 | |||
349 | /** |
||
350 | * @return string[] |
||
351 | */ |
||
352 | 12 | public function getBoms() |
|
362 | |||
363 | /** |
||
364 | * @return string[] |
||
365 | */ |
||
366 | 10 | private function getDefaultBoms() |
|
370 | |||
371 | /** |
||
372 | * Get a new line for writing |
||
373 | * |
||
374 | * @return string |
||
375 | */ |
||
376 | 7 | public function getNewLine() |
|
380 | |||
381 | /** |
||
382 | * Get a ByteOrderMark for writing if applicable |
||
383 | * |
||
384 | * @return string|null |
||
385 | */ |
||
386 | 20 | public function getBom() |
|
390 | } |
||
391 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.