Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Client 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 Client, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
22 | class Client |
||
23 | { |
||
24 | const STATUS_OK = 0; |
||
25 | const STATUS_WARNING = 1; |
||
26 | const STATUS_CRITICAL = 2; |
||
27 | const STATUS_UNKNOWN = 3; |
||
28 | |||
29 | const PRIORITY_LOW = 'low'; |
||
30 | const PRIORITY_NORMAL = 'normal'; |
||
31 | |||
32 | const ALERT_ERROR = 'error'; |
||
33 | const ALERT_WARNING = 'warning'; |
||
34 | const ALERT_INFO = 'info'; |
||
35 | const ALERT_SUCCESS = 'success'; |
||
36 | |||
37 | /** |
||
38 | * Instance instances array |
||
39 | * |
||
40 | * @var array |
||
41 | */ |
||
42 | protected static $instances = []; |
||
43 | |||
44 | /** |
||
45 | * Instance ID |
||
46 | * |
||
47 | * @var string |
||
48 | */ |
||
49 | protected $instanceId; |
||
50 | |||
51 | /** |
||
52 | * Server Host |
||
53 | * |
||
54 | * @var string |
||
55 | */ |
||
56 | protected $host = '127.0.0.1'; |
||
57 | |||
58 | /** |
||
59 | * Server Port |
||
60 | * |
||
61 | * @var integer |
||
62 | */ |
||
63 | protected $port = 8125; |
||
64 | |||
65 | /** |
||
66 | * Last message sent to the server |
||
67 | * |
||
68 | * @var string |
||
69 | */ |
||
70 | protected $message = ''; |
||
71 | |||
72 | /** |
||
73 | * Class namespace |
||
74 | * |
||
75 | * @var string |
||
76 | */ |
||
77 | protected $namespace = ''; |
||
78 | |||
79 | /** |
||
80 | * Timeout for creating the socket connection |
||
81 | * |
||
82 | * @var null|int |
||
83 | */ |
||
84 | protected $timeout; |
||
85 | |||
86 | /** |
||
87 | * Whether or not an exception should be thrown on failed connections |
||
88 | * |
||
89 | * @var bool |
||
90 | */ |
||
91 | protected $throwExceptions = true; |
||
92 | |||
93 | /** |
||
94 | * Socket connection |
||
95 | * |
||
96 | * @var resource|null |
||
97 | */ |
||
98 | protected $socket = null; |
||
99 | |||
100 | /** |
||
101 | * Metadata for the DataDog event message |
||
102 | * |
||
103 | * @var array - time - Assign a timestamp to the event. |
||
104 | * - hostname - Assign a hostname to the event |
||
105 | * - key - Assign an aggregation key to th event, to group it with some others |
||
106 | * - priority - Can be 'normal' or 'low' |
||
107 | * - source - Assign a source type to the event |
||
108 | * - alert - Can be 'error', 'warning', 'info' or 'success' |
||
109 | */ |
||
110 | protected $eventMetaData = [ |
||
111 | 'time' => 'd', |
||
112 | 'hostname' => 'h', |
||
113 | 'key' => 'k', |
||
114 | 'priority' => 'p', |
||
115 | 'source' => 's', |
||
116 | 'alert' => 't', |
||
117 | ]; |
||
118 | |||
119 | /** |
||
120 | * @var array - time - Assign a timestamp to the service check |
||
121 | * - hostname - Assign a hostname to the service check |
||
122 | */ |
||
123 | protected $serviceCheckMetaData = [ |
||
124 | 'time' => 'd', |
||
125 | 'hostname' => 'h', |
||
126 | ]; |
||
127 | |||
128 | /** |
||
129 | * @var array - message - Assign a message to the service check |
||
130 | */ |
||
131 | protected $serviceCheckMessage = [ |
||
132 | 'message' => 'm', |
||
133 | ]; |
||
134 | |||
135 | /** |
||
136 | * Is the server type DataDog implementation |
||
137 | * |
||
138 | 1 | * @var bool |
|
139 | */ |
||
140 | 1 | protected $dataDog = true; |
|
141 | 1 | ||
142 | 1 | /** |
|
143 | 1 | * Set of default tags to send to every request |
|
144 | * |
||
145 | * @var array |
||
146 | */ |
||
147 | protected $tags = []; |
||
148 | |||
149 | /** |
||
150 | * Singleton Reference |
||
151 | 45 | * |
|
152 | * @param string $name Instance name |
||
153 | 45 | * |
|
154 | * @return Client Client instance |
||
155 | 45 | */ |
|
156 | 45 | public static function instance($name = 'default') |
|
163 | |||
164 | /** |
||
165 | 2 | * Create a new instance |
|
166 | * |
||
167 | 2 | * @param string|null $instanceId |
|
168 | */ |
||
169 | public function __construct($instanceId = null) |
||
177 | |||
178 | /** |
||
179 | * Get string value of instance |
||
180 | * |
||
181 | * @return string String representation of this instance |
||
182 | */ |
||
183 | public function __toString() |
||
187 | |||
188 | 45 | /** |
|
189 | 15 | * Initialize Connection Details |
|
190 | 15 | * |
|
191 | 45 | * @param array $options Configuration options |
|
192 | * :host <string|ip> - host to talk to |
||
193 | 45 | * :port <int> - Port to communicate with |
|
194 | 45 | * :namespace <string> - Default namespace |
|
195 | 45 | * :timeout <int> - Timeout in seconds |
|
196 | 45 | * :throwExceptions <bool> - Throw an exception on connection error |
|
197 | 45 | * :dataDog <bool> - Use DataDog's version of statsd (Default: true) |
|
198 | 45 | * :tags <array> - List of tags to add to each message |
|
199 | 45 | * |
|
200 | * @return Client This instance |
||
201 | 45 | * @throws ConfigurationException If port is invalid |
|
202 | 2 | */ |
|
203 | public function configure(array $options = []) |
||
233 | 1 | ||
234 | /** |
||
235 | 1 | * Get Host |
|
236 | * |
||
237 | * @return string Host |
||
238 | */ |
||
239 | public function getHost() |
||
243 | 31 | ||
244 | /** |
||
245 | 31 | * Get Port |
|
246 | * |
||
247 | * @return int Port |
||
248 | */ |
||
249 | public function getPort() |
||
253 | |||
254 | /** |
||
255 | * Get Namespace |
||
256 | * |
||
257 | * @return string Namespace |
||
258 | 14 | */ |
|
259 | public function getNamespace() |
||
263 | 14 | ||
264 | 1 | /** |
|
265 | 1 | * Get Last Message |
|
266 | 1 | * |
|
267 | 1 | * @return string Last message sent to server |
|
268 | 1 | */ |
|
269 | 1 | public function getLastMessage() |
|
273 | |||
274 | 14 | /** |
|
275 | * Increment a metric |
||
276 | * |
||
277 | * @param string|string[] $metrics Metric(s) to increment |
||
278 | * @param int $delta Value to decrement the metric by |
||
279 | * @param float $sampleRate Sample rate of metric |
||
280 | * @param string[] $tags List of tags for this metric |
||
281 | * |
||
282 | * @return Client This instance |
||
283 | */ |
||
284 | public function increment($metrics, $delta = 1, $sampleRate = 1.0, array $tags = []) |
||
302 | |||
303 | 3 | /** |
|
304 | * Decrement a metric |
||
305 | 3 | * |
|
306 | 3 | * @param string|string[] $metrics Metric(s) to decrement |
|
307 | * @param int $delta Value to increment the metric by |
||
308 | 3 | * @param int $sampleRate Sample rate of metric |
|
309 | * @param string[] $tags List of tags for this metric |
||
310 | * |
||
311 | * @return Client This instance |
||
312 | */ |
||
313 | public function decrement($metrics, $delta = 1, $sampleRate = 1, array $tags = []) |
||
317 | |||
318 | /** |
||
319 | * Timing |
||
320 | 1 | * |
|
321 | * @param string $metric Metric to track |
||
322 | 1 | * @param float $time Time in milliseconds |
|
323 | 1 | * @param string[] $tags List of tags for this metric |
|
324 | 1 | * |
|
325 | 1 | * @return Client This instance |
|
326 | 1 | */ |
|
327 | public function timing($metric, $time, array $tags = []) |
||
336 | |||
337 | /** |
||
338 | * Time a function |
||
339 | 2 | * |
|
340 | * @param string $metric Metric to time |
||
341 | 2 | * @param callable $func Function to record |
|
342 | * @param string[] $tags List of tags for this metric |
||
343 | 2 | * |
|
344 | 2 | * @return Client This instance |
|
345 | */ |
||
346 | 2 | public function time($metric, callable $func, array $tags = []) |
|
354 | |||
355 | /** |
||
356 | * Gauges |
||
357 | * |
||
358 | 2 | * @param string $metric Metric to gauge |
|
359 | * @param int $value Set the value of the gauge |
||
360 | 2 | * @param string[] $tags List of tags for this metric |
|
361 | * |
||
362 | 2 | * @return Client This instance |
|
363 | 2 | */ |
|
364 | public function gauge($metric, $value, array $tags = []) |
||
373 | |||
374 | /** |
||
375 | * Histogram |
||
376 | * |
||
377 | * @param string $metric Metric to send |
||
378 | * @param float $value Value to send |
||
379 | * @param float $sampleRate Sample rate of metric |
||
380 | * @param string[] $tags List of tags for this metric |
||
381 | * |
||
382 | * @return Client This instance |
||
383 | */ |
||
384 | public function histogram($metric, $value, $sampleRate = 1.0, array $tags = []) |
||
397 | |||
398 | 5 | /** |
|
399 | 2 | * Sets - count the number of unique elements for a group |
|
400 | 2 | * |
|
401 | 2 | * @param string $metric |
|
402 | 5 | * @param int $value |
|
403 | * @param string[] $tags List of tags for this metric |
||
404 | 5 | * |
|
405 | * @return Client This instance |
||
406 | 5 | */ |
|
407 | 5 | public function set($metric, $value, array $tags = []) |
|
416 | |||
417 | /** |
||
418 | * Send a event notification |
||
419 | * |
||
420 | * @link http://docs.datadoghq.com/guides/dogstatsd/#events |
||
421 | * |
||
422 | * @param string $title Event Title |
||
423 | * @param string $text Event Text |
||
424 | * @param array $metadata Set of metadata for this event: |
||
425 | * - time - Assign a timestamp to the event. |
||
426 | 6 | * - hostname - Assign a hostname to the event |
|
427 | * - key - Assign an aggregation key to th event, to group it with some others |
||
428 | 6 | * - priority - Can be 'normal' or 'low' |
|
429 | 1 | * - source - Assign a source type to the event |
|
430 | * - alert - Can be 'error', 'warning', 'info' or 'success' |
||
431 | * @param string[] $tags List of tags for this event |
||
432 | 5 | * |
|
433 | 5 | * @return Client This instance |
|
434 | * @throws ConnectionException If there is a connection problem with the host |
||
435 | 5 | */ |
|
436 | 5 | public function event($title, $text, array $metadata = [], array $tags = []) |
|
459 | 31 | ||
460 | 20 | /** |
|
461 | * Service Checks |
||
462 | * |
||
463 | 11 | * @link http://docs.datadoghq.com/guides/dogstatsd/#service-checks |
|
464 | 11 | * |
|
465 | 11 | * @param string $name Name of the service |
|
466 | 10 | * @param int $status digit corresponding to the status you’re reporting (OK = 0, WARNING = 1, CRITICAL = 2, |
|
467 | 10 | * UNKNOWN = 3) |
|
468 | 2 | * @param array $metadata - time - Assign a timestamp to the service check |
|
469 | * - hostname - Assign a hostname to the service check |
||
470 | 11 | * @param string[] $tags List of tags for this event |
|
471 | * |
||
472 | 11 | * @return Client This instance |
|
473 | * @throws ConnectionException If there is a connection problem with the host |
||
474 | */ |
||
475 | public function serviceCheck($name, $status, array $metadata = [], array $tags = []) |
||
500 | |||
501 | 31 | /** |
|
502 | * @param string[] $tags A list of tags to apply to each message |
||
503 | 31 | * |
|
504 | 31 | * @return string |
|
505 | 2 | */ |
|
506 | 1 | private function formatTags(array $tags = []) |
|
523 | |||
524 | /** |
||
525 | * Send Data to StatsD Server |
||
526 | * |
||
527 | * @param string[] $data A list of messages to send to the server |
||
528 | * @param string[] $tags A list of tags to apply to each message |
||
529 | * |
||
530 | * @return Client This instance |
||
531 | * @throws ConnectionException If there is a connection problem with the host |
||
532 | */ |
||
533 | protected function send(array $data, array $tags = []) |
||
543 | |||
544 | /** |
||
545 | * @param string[] $messages |
||
546 | * |
||
547 | * @return Client This instance |
||
548 | * @throws ConnectionException If there is a connection problem with the host |
||
549 | */ |
||
550 | protected function sendMessages(array $messages) |
||
566 | |||
567 | /** |
||
568 | * Creates a persistent connection to the udp host:port |
||
569 | * |
||
570 | * @return resource |
||
571 | */ |
||
572 | protected function connect() |
||
587 | |||
588 | public function __destruct() |
||
594 | } |
||
595 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.