Complex classes like CheckerBase 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 CheckerBase, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
24 | abstract class CheckerBase |
||
25 | { |
||
26 | /** |
||
27 | * @var EcAdapterInterface |
||
28 | */ |
||
29 | protected $adapter; |
||
30 | |||
31 | /** |
||
32 | * @var TransactionInterface |
||
33 | */ |
||
34 | protected $transaction; |
||
35 | |||
36 | /** |
||
37 | * @var int |
||
38 | */ |
||
39 | protected $nInput; |
||
40 | |||
41 | /** |
||
42 | * @var int|string |
||
43 | */ |
||
44 | protected $amount; |
||
45 | |||
46 | /** |
||
47 | * @var array |
||
48 | */ |
||
49 | protected $sigCache = []; |
||
50 | |||
51 | /** |
||
52 | * @var TransactionSignatureSerializer |
||
53 | */ |
||
54 | private $sigSerializer; |
||
55 | |||
56 | /** |
||
57 | * @var PublicKeySerializerInterface |
||
58 | */ |
||
59 | private $pubKeySerializer; |
||
60 | |||
61 | /** |
||
62 | * @var int |
||
63 | */ |
||
64 | protected $sigHashOptionalBits = SigHash::ANYONECANPAY; |
||
65 | |||
66 | /** |
||
67 | * Checker constructor. |
||
68 | * @param EcAdapterInterface $ecAdapter |
||
69 | * @param TransactionInterface $transaction |
||
70 | * @param int $nInput |
||
71 | * @param int $amount |
||
72 | * @param TransactionSignatureSerializer|null $sigSerializer |
||
73 | * @param PublicKeySerializerInterface|null $pubKeySerializer |
||
74 | */ |
||
75 | 4803 | public function __construct(EcAdapterInterface $ecAdapter, TransactionInterface $transaction, int $nInput, int $amount, TransactionSignatureSerializer $sigSerializer = null, PublicKeySerializerInterface $pubKeySerializer = null) |
|
84 | |||
85 | /** |
||
86 | * @param ScriptInterface $script |
||
87 | * @param int $hashType |
||
88 | * @param int $sigVersion |
||
89 | * @return BufferInterface |
||
90 | */ |
||
91 | abstract function getSigHash(ScriptInterface $script, int $hashType, int $sigVersion): BufferInterface; |
||
92 | |||
93 | /** |
||
94 | * @param BufferInterface $signature |
||
95 | * @return bool |
||
96 | */ |
||
97 | 195 | public function isValidSignatureEncoding(BufferInterface $signature): bool |
|
108 | |||
109 | /** |
||
110 | * @param BufferInterface $signature |
||
111 | * @return bool |
||
112 | * @throws ScriptRuntimeException |
||
113 | * @throws \Exception |
||
114 | */ |
||
115 | 7 | public function isLowDerSignature(BufferInterface $signature): bool |
|
128 | |||
129 | /** |
||
130 | * @param int $hashType |
||
131 | * @return bool |
||
132 | */ |
||
133 | 132 | public function isDefinedHashtype(int $hashType): bool |
|
139 | |||
140 | /** |
||
141 | * Determine whether the sighash byte appended to the signature encodes |
||
142 | * a valid sighash type. |
||
143 | * |
||
144 | * @param BufferInterface $signature |
||
145 | * @return bool |
||
146 | */ |
||
147 | 44 | public function isDefinedHashtypeSignature(BufferInterface $signature): bool |
|
156 | |||
157 | /** |
||
158 | * @param BufferInterface $signature |
||
159 | * @param int $flags |
||
160 | * @return $this |
||
161 | * @throws \BitWasp\Bitcoin\Exceptions\ScriptRuntimeException |
||
162 | */ |
||
163 | 578 | public function checkSignatureEncoding(BufferInterface $signature, int $flags) |
|
179 | |||
180 | /** |
||
181 | * @param BufferInterface $publicKey |
||
182 | * @param int $flags |
||
183 | * @return $this |
||
184 | * @throws \Exception |
||
185 | */ |
||
186 | 473 | public function checkPublicKeyEncoding(BufferInterface $publicKey, int $flags) |
|
194 | |||
195 | /** |
||
196 | * @param ScriptInterface $script |
||
197 | * @param BufferInterface $sigBuf |
||
198 | * @param BufferInterface $keyBuf |
||
199 | * @param int $sigVersion |
||
200 | * @param int $flags |
||
201 | * @return bool |
||
202 | * @throws ScriptRuntimeException |
||
203 | */ |
||
204 | 571 | public function checkSig(ScriptInterface $script, BufferInterface $sigBuf, BufferInterface $keyBuf, int $sigVersion, int $flags) |
|
227 | |||
228 | /** |
||
229 | * @param \BitWasp\Bitcoin\Script\Interpreter\Number $scriptLockTime |
||
230 | * @return bool |
||
231 | */ |
||
232 | 8 | public function checkLockTime(\BitWasp\Bitcoin\Script\Interpreter\Number $scriptLockTime): bool |
|
254 | |||
255 | /** |
||
256 | * @param \BitWasp\Bitcoin\Script\Interpreter\Number $sequence |
||
257 | * @return bool |
||
258 | */ |
||
259 | 15 | public function checkSequence(\BitWasp\Bitcoin\Script\Interpreter\Number $sequence): bool |
|
286 | } |
||
287 |
Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.
If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with
private
, and only raise it toprotected
if a sub-class needs to have access, orpublic
if an external class needs access.