Complex classes like Peer 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 Peer, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
29 | class Peer extends EventEmitter |
||
30 | { |
||
31 | /** |
||
32 | * @var string |
||
33 | */ |
||
34 | private $buffer = ''; |
||
35 | |||
36 | /** |
||
37 | * @var LoopInterface |
||
38 | */ |
||
39 | private $loop; |
||
40 | |||
41 | /** |
||
42 | * @var \BitWasp\Bitcoin\Networking\Messages\Factory |
||
43 | */ |
||
44 | private $msgs; |
||
45 | |||
46 | /** |
||
47 | * @var Stream |
||
48 | */ |
||
49 | private $stream; |
||
50 | |||
51 | /** |
||
52 | * @var Version |
||
53 | */ |
||
54 | private $localVersion; |
||
55 | |||
56 | /** |
||
57 | * @var Version |
||
58 | */ |
||
59 | private $remoteVersion; |
||
60 | |||
61 | /** |
||
62 | * @var NetworkAddressInterface |
||
63 | */ |
||
64 | private $peerAddress; |
||
65 | |||
66 | /** |
||
67 | * @var ConnectionParams |
||
68 | */ |
||
69 | private $connectionParams; |
||
70 | |||
71 | /** |
||
72 | * @var bool |
||
73 | */ |
||
74 | private $exchangedVersion = false; |
||
75 | |||
76 | /** |
||
77 | * @param \BitWasp\Bitcoin\Networking\Messages\Factory $msgs |
||
78 | * @param LoopInterface $loop |
||
79 | */ |
||
80 | 12 | public function __construct(\BitWasp\Bitcoin\Networking\Messages\Factory $msgs, LoopInterface $loop) |
|
85 | |||
86 | /** |
||
87 | * @return Version |
||
88 | */ |
||
89 | 3 | public function getLocalVersion() |
|
93 | |||
94 | /** |
||
95 | * @return Version |
||
96 | */ |
||
97 | 3 | public function getRemoteVersion() |
|
101 | |||
102 | /** |
||
103 | * Reliably returns the remote peers NetAddr when known through |
||
104 | * the connection process. Often better than the data contained |
||
105 | * in a Version message. |
||
106 | * |
||
107 | * @return NetworkAddressInterface |
||
108 | */ |
||
109 | 3 | public function getRemoteAddress() |
|
113 | |||
114 | /** |
||
115 | * @return ConnectionParams |
||
116 | */ |
||
117 | 3 | public function getConnectionParams() |
|
121 | |||
122 | /** |
||
123 | * @param NetworkSerializable $msg |
||
124 | */ |
||
125 | 12 | public function send(NetworkSerializable $msg) |
|
131 | |||
132 | /** |
||
133 | * Handler for incoming data. Buffers possibly fragmented packets since they arrive sequentially. |
||
134 | * Before finishing the version exchange, this will only emit Version and VerAck messages. |
||
135 | */ |
||
136 | 12 | private function onData() |
|
151 | |||
152 | /** |
||
153 | * @param Stream $stream |
||
154 | * @return $this |
||
155 | */ |
||
156 | 12 | public function setupStream(Stream $stream) |
|
178 | |||
179 | /** |
||
180 | * @param Stream $connection |
||
181 | * @param ConnectionParams $params |
||
182 | * @return \React\Promise\Promise|\React\Promise\PromiseInterface |
||
183 | */ |
||
184 | 9 | public function inboundHandshake(Stream $connection, ConnectionParams $params) |
|
209 | |||
210 | /** |
||
211 | * @param NetworkAddressInterface $remotePeer |
||
212 | * @param ConnectionParams $params |
||
213 | * @return \React\Promise\Promise|\React\Promise\PromiseInterface |
||
214 | */ |
||
215 | 12 | public function outboundHandshake(NetworkAddressInterface $remotePeer, ConnectionParams $params) |
|
216 | { |
||
217 | 12 | $deferred = new Deferred(); |
|
218 | |||
219 | 12 | $awaitVersion = true; |
|
220 | $this->stream->on('close', function () use (&$awaitVersion, $deferred) { |
||
221 | 7 | if ($awaitVersion) { |
|
222 | 7 | $awaitVersion = false; |
|
223 | 7 | $deferred->reject('peer disconnected'); |
|
224 | 5 | } |
|
225 | 12 | }); |
|
226 | |||
227 | $this->on(Message::VERSION, function (Peer $peer, Version $version) use ($params) { |
||
228 | 12 | $this->remoteVersion = $version; |
|
229 | 12 | $this->verack(); |
|
230 | 12 | }); |
|
231 | |||
232 | 12 | $this->on(Message::VERACK, function () use ($deferred) { |
|
233 | 9 | if (false === $this->exchangedVersion) { |
|
234 | 9 | $this->exchangedVersion = true; |
|
235 | 9 | $this->emit('ready', [$this]); |
|
236 | 9 | $deferred->resolve($this); |
|
237 | 6 | } |
|
238 | 12 | }); |
|
239 | |||
240 | 12 | $this->peerAddress = $remotePeer; |
|
241 | 12 | $this->localVersion = $version = $params->produceVersion($this->msgs, $remotePeer); |
|
242 | 12 | $this->connectionParams = $params; |
|
243 | |||
244 | 12 | $this->send($version); |
|
245 | |||
246 | 12 | return $deferred->promise(); |
|
247 | } |
||
248 | |||
249 | /** |
||
250 | * |
||
251 | */ |
||
252 | public function intentionalClose() |
||
253 | { |
||
254 | $this->emit('intentionaldisconnect', [$this]); |
||
255 | $this->close(); |
||
256 | } |
||
257 | |||
258 | /** |
||
259 | * |
||
260 | */ |
||
261 | 9 | public function close() |
|
262 | { |
||
263 | 9 | $this->emit('close', [$this]); |
|
264 | 9 | $this->stream->end(); |
|
265 | 9 | $this->removeAllListeners(); |
|
266 | 9 | } |
|
267 | |||
268 | /** |
||
269 | * @param int $protocolVersion |
||
270 | * @param int $services |
||
271 | * @param int $timestamp |
||
272 | * @param NetworkAddressInterface $remoteAddr |
||
273 | * @param NetworkAddressInterface $localAddr |
||
274 | * @param string $userAgent |
||
275 | * @param int $blockHeight |
||
276 | * @param bool $relayToUs |
||
277 | */ |
||
278 | public function version( |
||
279 | $protocolVersion, |
||
280 | $services, |
||
281 | $timestamp, |
||
282 | NetworkAddressInterface $remoteAddr, |
||
283 | NetworkAddressInterface $localAddr, |
||
284 | $userAgent, |
||
285 | $blockHeight, |
||
286 | $relayToUs |
||
287 | ) { |
||
288 | $this->send($this->msgs->version( |
||
289 | $protocolVersion, |
||
290 | $services, |
||
291 | $timestamp, |
||
292 | $remoteAddr, |
||
293 | $localAddr, |
||
294 | new Buffer($userAgent), |
||
295 | $blockHeight, |
||
296 | $relayToUs |
||
297 | )); |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * |
||
302 | */ |
||
303 | 12 | public function verack() |
|
304 | { |
||
305 | 12 | $this->send($this->msgs->verack()); |
|
306 | 12 | } |
|
307 | |||
308 | /** |
||
309 | * |
||
310 | */ |
||
311 | public function sendheaders() |
||
315 | |||
316 | /** |
||
317 | * @param Inventory[] $vInv |
||
318 | */ |
||
319 | public function inv(array $vInv) |
||
323 | |||
324 | /** |
||
325 | * @param Inventory[] $vInv |
||
326 | */ |
||
327 | public function getdata(array $vInv) |
||
331 | |||
332 | /** |
||
333 | * @param array $vInv |
||
334 | */ |
||
335 | public function notfound(array $vInv) |
||
339 | |||
340 | /** |
||
341 | * @param NetworkAddressTimestamp[] $vNetAddr |
||
342 | */ |
||
343 | public function addr(array $vNetAddr) |
||
347 | |||
348 | /** |
||
349 | * |
||
350 | */ |
||
351 | public function getaddr() |
||
355 | |||
356 | /** |
||
357 | * |
||
358 | */ |
||
359 | public function ping() |
||
363 | |||
364 | /** |
||
365 | * @param Ping $ping |
||
366 | */ |
||
367 | public function pong(Ping $ping) |
||
371 | |||
372 | /** |
||
373 | * @param TransactionInterface $tx |
||
374 | */ |
||
375 | public function tx(TransactionInterface $tx) |
||
379 | |||
380 | /** |
||
381 | * @param BlockLocator $locator |
||
382 | */ |
||
383 | public function getblocks(BlockLocator $locator) |
||
384 | { |
||
385 | $this->send($this->msgs->getblocks( |
||
386 | $this->localVersion->getVersion(), |
||
387 | $locator |
||
388 | )); |
||
389 | } |
||
390 | |||
391 | /** |
||
392 | * @param BlockLocator $locator |
||
393 | */ |
||
394 | public function getheaders(BlockLocator $locator) |
||
395 | { |
||
396 | $this->send($this->msgs->getheaders( |
||
397 | $this->localVersion->getVersion(), |
||
398 | $locator |
||
399 | )); |
||
400 | } |
||
401 | |||
402 | /** |
||
403 | * @param BlockInterface $block |
||
404 | */ |
||
405 | public function block(BlockInterface $block) |
||
409 | |||
410 | /** |
||
411 | * @param array $vHeaders |
||
412 | */ |
||
413 | public function headers(array $vHeaders) |
||
414 | { |
||
415 | $this->send($this->msgs->headers($vHeaders)); |
||
416 | } |
||
417 | |||
418 | /** |
||
419 | * @param AlertDetail $detail |
||
420 | * @param SignatureInterface $signature |
||
421 | */ |
||
422 | public function alert(AlertDetail $detail, SignatureInterface $signature) |
||
426 | |||
427 | /** |
||
428 | * @param int $feeRate |
||
429 | */ |
||
430 | public function feefilter($feeRate) |
||
434 | |||
435 | /** |
||
436 | * @param BufferInterface $data |
||
437 | */ |
||
438 | public function filteradd(BufferInterface $data) |
||
442 | |||
443 | /** |
||
444 | * @param BloomFilter $filter |
||
445 | */ |
||
446 | public function filterload(BloomFilter $filter) |
||
450 | |||
451 | /** |
||
452 | * |
||
453 | */ |
||
454 | public function filterclear() |
||
458 | |||
459 | /** |
||
460 | * @param FilteredBlock $filtered |
||
461 | */ |
||
462 | public function merkleblock(FilteredBlock $filtered) |
||
466 | |||
467 | /** |
||
468 | * |
||
469 | */ |
||
470 | public function mempool() |
||
471 | { |
||
472 | $this->send($this->msgs->mempool()); |
||
473 | } |
||
474 | |||
475 | /** |
||
476 | * Issue a Reject message, with a required $msg, $code, and $reason |
||
477 | * |
||
478 | * @param BufferInterface $msg |
||
479 | * @param int $code |
||
480 | * @param BufferInterface $reason |
||
481 | * @param BufferInterface $data |
||
482 | */ |
||
483 | public function reject(BufferInterface $msg, $code, BufferInterface $reason, BufferInterface $data = null) |
||
487 | } |
||
488 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.