Complex classes like OverrideGraph 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 OverrideGraph, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
66 | class OverrideGraph |
||
67 | { |
||
68 | /** |
||
69 | * Stores the names of all packages (vertices) as keys. |
||
70 | * |
||
71 | * @var array |
||
72 | */ |
||
73 | private $packageNames = array(); |
||
74 | |||
75 | /** |
||
76 | * Stores the edges in the keys of a multi-dimensional array. |
||
77 | * |
||
78 | * The first dimension stores the targets, the second dimension the origins |
||
79 | * of the edges. |
||
80 | * |
||
81 | * @var array |
||
82 | */ |
||
83 | private $edges = array(); |
||
84 | |||
85 | /** |
||
86 | * Creates an override graph for the given packages. |
||
87 | * |
||
88 | * @param PackageCollection $packages The packages to load. |
||
89 | * |
||
90 | * @return static The created override graph. |
||
91 | */ |
||
92 | 65 | public static function forPackages(PackageCollection $packages) |
|
123 | |||
124 | /** |
||
125 | * Creates a new graph. |
||
126 | * |
||
127 | * @param string[] $packageNames The package names stored in the nodes of |
||
128 | * the graph. |
||
129 | */ |
||
130 | 104 | public function __construct(array $packageNames = array()) |
|
134 | |||
135 | /** |
||
136 | * Adds a package name to the graph. |
||
137 | * |
||
138 | * @param string $packageName The package name. |
||
139 | * |
||
140 | * @throws RuntimeException If the package name already exists. |
||
141 | */ |
||
142 | 103 | public function addPackageName($packageName) |
|
154 | |||
155 | /** |
||
156 | * Adds a list of package names to the graph. |
||
157 | * |
||
158 | * @param string[] $packageNames The package names. |
||
159 | * |
||
160 | * @throws RuntimeException If a package name already exists. |
||
161 | */ |
||
162 | 104 | public function addPackageNames(array $packageNames) |
|
168 | |||
169 | /** |
||
170 | * Returns whether a package name exists in the graph. |
||
171 | * |
||
172 | * @param string $packageName The package name. |
||
173 | * |
||
174 | * @return bool Whether the package name exists. |
||
175 | */ |
||
176 | 20 | public function hasPackageName($packageName) |
|
180 | |||
181 | /** |
||
182 | * Adds a directed edge from one to another package. |
||
183 | * |
||
184 | * @param string $from The start package name. |
||
185 | * @param string $to The end package name. |
||
186 | * |
||
187 | * @throws RuntimeException If any of the packages does not exist in the |
||
188 | * graph. Each package must have been added first. |
||
189 | * @throws CyclicDependencyException If adding the edge would create a cycle. |
||
190 | */ |
||
191 | 47 | public function addEdge($from, $to) |
|
221 | |||
222 | 2 | public function removeEdge($from, $to) |
|
226 | |||
227 | /** |
||
228 | * Returns whether an edge exists between two packages. |
||
229 | * |
||
230 | * @param string $from The start package name. |
||
231 | * @param string $to The end package name. |
||
232 | * |
||
233 | * @return bool Whether an edge exists from the origin to the target package. |
||
234 | */ |
||
235 | 40 | public function hasEdge($from, $to) |
|
239 | |||
240 | /** |
||
241 | * Returns whether a path exists from one to another package. |
||
242 | * |
||
243 | * @param string $from The start package name. |
||
244 | * @param string $to The end package name. |
||
245 | * |
||
246 | * @return bool Whether a path exists from the origin to the target package. |
||
247 | */ |
||
248 | 9 | public function hasPath($from, $to) |
|
269 | |||
270 | /** |
||
271 | * Returns the path from one to another package. |
||
272 | * |
||
273 | * @param string $from The start package name. |
||
274 | * @param string $to The end package name. |
||
275 | * |
||
276 | * @return string[]|null The path of package names or `null`, if no path |
||
|
|||
277 | * was found. |
||
278 | */ |
||
279 | 45 | public function getPath($from, $to) |
|
287 | |||
288 | /** |
||
289 | * Returns all package names in the graph. |
||
290 | * |
||
291 | * @return array All package names in the graph. |
||
292 | */ |
||
293 | public function getPackageNames() |
||
297 | |||
298 | /** |
||
299 | * Sorts package names according to the defined edges. |
||
300 | * |
||
301 | * The names are sorted such that if two packages p1 and p2 have an edge |
||
302 | * (p1, p2) in the graph, then p1 comes before p2 in the sorted set. |
||
303 | * |
||
304 | * If no package names are passed, all names are sorted. |
||
305 | * |
||
306 | * @param string[] $namesToSort The package names which should be sorted. |
||
307 | * |
||
308 | * @return string[] The sorted package names. |
||
309 | * |
||
310 | * @throws RuntimeException If any of the passed package names does not |
||
311 | * exist in the graph. |
||
312 | */ |
||
313 | 55 | public function getSortedPackageNames(array $namesToSort = array()) |
|
340 | |||
341 | /** |
||
342 | * Finds a path between packages using Depth-First Search. |
||
343 | * |
||
344 | * @param string $from The start package name. |
||
345 | * @param string $to The end package name. |
||
346 | * @param array $reversePath The path in reverse order. |
||
347 | * |
||
348 | * @return bool Whether a path was found. |
||
349 | */ |
||
350 | 45 | private function getPathDFS($from, $to, &$reversePath = array()) |
|
375 | |||
376 | /** |
||
377 | * Topologically sorts the given package name into the output array. |
||
378 | * |
||
379 | * The resulting array is sorted such that all predecessors of the package |
||
380 | * come before the package (and their predecessors before them, and so on). |
||
381 | * |
||
382 | * @param string $currentName The current package name to sort. |
||
383 | * @param array $namesToSort The package names yet to be sorted. |
||
384 | * @param array $output The output array. |
||
385 | */ |
||
386 | 54 | private function sortPackagesDFS($currentName, array &$namesToSort, array &$output) |
|
404 | } |
||
405 |
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.If the return type contains the type array, this check recommends the use of a more specific type like
String[]
orarray<String>
.