Complex classes like GuzzleClient 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 GuzzleClient, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
50 | 1 | class GuzzleClient implements IClient |
|
51 | { |
||
52 | /** |
||
53 | * Implement nette smart magic |
||
54 | */ |
||
55 | 1 | use Nette\SmartObject; |
|
56 | |||
57 | 1 | use TSendsRequests; |
|
58 | |||
59 | /** |
||
60 | * Additional request headers |
||
61 | * |
||
62 | * @var string[] |
||
63 | */ |
||
64 | private $headers = []; |
||
65 | |||
66 | /** |
||
67 | * @var Client |
||
68 | */ |
||
69 | private $http; |
||
70 | |||
71 | /** |
||
72 | * @param string|NULL $baseUri |
||
73 | * @param Schemas\SchemaProvider $schemaProvider |
||
74 | * @param Client|NULL $client |
||
75 | */ |
||
76 | public function __construct( |
||
93 | |||
94 | /** |
||
95 | * {@inheritdoc} |
||
96 | */ |
||
97 | public function index(string $endpoint, EncodingParametersInterface $parameters = NULL, array $options = []) : Http\IResponse |
||
106 | |||
107 | /** |
||
108 | * {@inheritdoc} |
||
109 | */ |
||
110 | public function read(string $endpoint, EncodingParametersInterface $parameters = NULL, array $options = []) : Http\IResponse |
||
119 | |||
120 | /** |
||
121 | * {@inheritdoc} |
||
122 | */ |
||
123 | public function create(string $endpoint, $record, EncodingParametersInterface $parameters = NULL, array $options = []) : Http\IResponse |
||
131 | |||
132 | /** |
||
133 | * {@inheritdoc} |
||
134 | */ |
||
135 | public function update(string $endpoint, $record, array $fields = NULL, EncodingParametersInterface $parameters = NULL, array $options = []) : Http\IResponse |
||
143 | |||
144 | /** |
||
145 | * {@inheritdoc} |
||
146 | */ |
||
147 | public function delete(string $endpoint, array $options = []) : Http\IResponse |
||
155 | |||
156 | /** |
||
157 | * {@inheritdoc} |
||
158 | */ |
||
159 | public function addApiKey(string $key) : void |
||
163 | |||
164 | /** |
||
165 | * {@inheritdoc} |
||
166 | */ |
||
167 | public function addAuthorization(string $token) : void |
||
171 | |||
172 | /** |
||
173 | * {@inheritdoc} |
||
174 | */ |
||
175 | public function removeAuthorization() : void |
||
181 | |||
182 | /** |
||
183 | * {@inheritdoc} |
||
184 | */ |
||
185 | public function addHeader(string $header, string $value) : void |
||
189 | |||
190 | /** |
||
191 | * @param string $endpoint |
||
192 | * @param string $method |
||
193 | * @param array $serializedRecord the encoded record |
||
194 | * @param EncodingParametersInterface|NULL $parameters |
||
195 | * @param array $options |
||
196 | * |
||
197 | * @return Http\IResponse |
||
198 | * |
||
199 | * @throws JsonApiException |
||
200 | * @throws GuzzleHttp\Exception\GuzzleException |
||
201 | * @throws Utils\JsonException |
||
202 | */ |
||
203 | protected function sendRecord(string $endpoint, string $method, array $serializedRecord, EncodingParametersInterface $parameters = NULL, array $options = []) : Http\IResponse |
||
214 | |||
215 | /** |
||
216 | * @param array $new |
||
217 | * @param array $existing |
||
218 | * |
||
219 | * @return array |
||
220 | */ |
||
221 | protected function mergeOptions(array $new, array $existing) : array |
||
225 | |||
226 | /** |
||
227 | * @param string $method |
||
228 | * @param string $uri |
||
229 | * @param array $options |
||
230 | * |
||
231 | * @return Http\IResponse |
||
232 | * |
||
233 | * @throws JsonApiException |
||
234 | * @throws GuzzleHttp\Exception\GuzzleException |
||
235 | * @throws Utils\JsonException |
||
236 | */ |
||
237 | protected function request(string $method, string $uri, array $options = []) : Http\IResponse |
||
250 | |||
251 | /** |
||
252 | * Safely parse an error response. |
||
253 | * |
||
254 | * This method wraps decoding the body content of the provided exception, so that |
||
255 | * another exception is not thrown while trying to parse an existing exception. |
||
256 | * |
||
257 | * @param PsrRequest $request |
||
258 | * @param BadResponseException $ex |
||
259 | * |
||
260 | * @return JsonApiException |
||
261 | */ |
||
262 | private function parseErrorResponse(PsrRequest $request, BadResponseException $ex) : JsonApiException |
||
280 | |||
281 | /** |
||
282 | * @param PsrRequest $request |
||
283 | * @param PsrResponse|NULL $response |
||
284 | * |
||
285 | * @return Objects\IDocument|NULL |
||
286 | * |
||
287 | * @throws Utils\JsonException |
||
288 | */ |
||
289 | private function createDocumentObject(PsrRequest $request, PsrResponse $response = NULL) : ?Objects\IDocument |
||
297 | |||
298 | /** |
||
299 | * @param PsrRequest $request |
||
300 | * @param PsrResponse|NULL $response |
||
301 | * |
||
302 | * @return Objects\IMutableError|NULL |
||
303 | * |
||
304 | * @throws Utils\JsonException |
||
305 | */ |
||
306 | private function createErrorObject(PsrRequest $request, PsrResponse $response = NULL) : ?Objects\IMutableError |
||
314 | |||
315 | /** |
||
316 | * @param PsrRequest $request |
||
317 | * @param PsrResponse|NULL $response |
||
318 | * |
||
319 | * @return bool |
||
320 | */ |
||
321 | private function httpContainsBody(PsrRequest $request, ?PsrResponse $response = NULL) : bool |
||
327 | |||
328 | /** |
||
329 | * Does the HTTP request contain body content? |
||
330 | * |
||
331 | * The presence of a message-body in a request is signaled by the inclusion of a Content-Length or |
||
332 | * Transfer-Encoding header field in the request's message-headers. |
||
333 | * https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3 |
||
334 | * |
||
335 | * However, some browsers send a Content-Length header with an empty string for e.g. GET requests |
||
336 | * without any message-body. Therefore rather than checking for the existence of a Content-Length |
||
337 | * header, we will allow an empty value to indicate that the request does not contain body. |
||
338 | * |
||
339 | * @param PsrRequest $request |
||
340 | * |
||
341 | * @return bool |
||
342 | */ |
||
343 | private function doesRequestHaveBody(PsrRequest $request) : bool |
||
355 | |||
356 | /** |
||
357 | * Does the HTTP response contain body content? |
||
358 | * |
||
359 | * For response messages, whether or not a message-body is included with a message is dependent |
||
360 | * on both the request method and the response status code (section 6.1.1). All responses to the |
||
361 | * HEAD request method MUST NOT include a message-body, even though the presence of entity-header |
||
362 | * fields might lead one to believe they do. All 1xx (informational), 204 (no content), and 304 |
||
363 | * (not modified) responses MUST NOT include a message-body. All other responses do include a |
||
364 | * message-body, although it MAY be of zero length. |
||
365 | * https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3 |
||
366 | * |
||
367 | * @param PsrRequest $request |
||
368 | * @param PsrResponse $response |
||
369 | * |
||
370 | * @return bool |
||
371 | */ |
||
372 | private function doesResponseHaveBody(PsrRequest $request, PsrResponse $response) : bool |
||
394 | |||
395 | /** |
||
396 | * @param string $baseUri |
||
397 | * |
||
398 | * @return Client |
||
399 | */ |
||
400 | private function createClient(string $baseUri) : Client |
||
408 | } |
||
409 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.