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:
1 | <?php declare(strict_types=1); |
||
23 | private string $key; |
||
24 | |||
25 | private TransportInterface $transport; |
||
26 | |||
27 | private MessageHandlerList $messageHandlers; |
||
28 | |||
29 | private Closure $guard; |
||
30 | |||
31 | private MetadataEnricherList $metadataEnrichers; |
||
32 | |||
33 | 7 | public function __construct( |
|
34 | string $key, |
||
35 | TransportInterface $transport, |
||
36 | MessageHandlerList $messageHandlers, |
||
37 | Closure $guard = null, |
||
38 | MetadataEnricherList $metadataEnrichers = null |
||
39 | ) { |
||
40 | 7 | $this->key = $key; |
|
41 | 7 | $this->transport = $transport; |
|
42 | 7 | $this->messageHandlers = $messageHandlers; |
|
43 | 7 | $this->guard = $guard ?? fn(): bool => true; |
|
|
|||
44 | 7 | $metadataEnrichers = $metadataEnrichers ?? new MetadataEnricherList; |
|
45 | 7 | $this->metadataEnrichers = $metadataEnrichers->prependEnricher(self::METADATA_KEY, $this->key); |
|
46 | 7 | } |
|
47 | |||
48 | 3 | public function publish(EnvelopeInterface $envelope, MessageBusInterface $messageBus): void |
|
49 | { |
||
50 | 3 | $envelope = $this->enrichMetadata($envelope); |
|
51 | 3 | if ($this->accepts($envelope)) { |
|
52 | 2 | $this->transport->send($envelope, $messageBus); |
|
53 | } |
||
54 | 3 | } |
|
55 | |||
56 | 3 | public function receive(EnvelopeInterface $envelope): void |
|
57 | { |
||
58 | 3 | $this->verify($envelope); |
|
59 | 1 | foreach ($this->messageHandlers as $messageHandler) { |
|
60 | 1 | $messageHandler->handle($envelope); |
|
61 | } |
||
62 | 1 | } |
|
63 | |||
64 | 1 | public function getKey(): string |
|
65 | { |
||
66 | 1 | return $this->key; |
|
67 | } |
||
68 | |||
69 | 3 | private function enrichMetadata(EnvelopeInterface $envelope): EnvelopeInterface |
|
70 | { |
||
71 | 3 | return $envelope->withMetadata(array_reduce( |
|
72 | 3 | $this->metadataEnrichers->unwrap(), |
|
73 | function (MetadataInterface $metadata, MetadataEnricherInterface $metadataEnricher): MetadataInterface { |
||
74 | 3 | return $metadataEnricher->enrich($metadata); |
|
75 | 3 | }, |
|
76 | 3 | $envelope->getMetadata() |
|
77 | )); |
||
78 | } |
||
79 | |||
80 | 3 | private function accepts(EnvelopeInterface $envelope): bool |
|
81 | { |
||
82 | 3 | return (bool)call_user_func($this->guard, $envelope); |
|
83 | } |
||
84 | |||
85 | 3 | private function verify(EnvelopeInterface $envelope): void |
|
86 | { |
||
87 | 3 | $metadata = $envelope->getMetadata(); |
|
88 | 3 | if (!$metadata->has(self::METADATA_KEY)) { |
|
89 | 1 | throw new EnvelopeNotAcceptable( |
|
90 | 1 | "Subscription key '".self::METADATA_KEY."' missing in metadata of Envelope ". |
|
91 | 1 | "'{$envelope->getUuid()->toString()}' received by subscription '{$this->key}'.", |
|
92 | 1 | EnvelopeNotAcceptable::SUBSCRIPTION_KEY_MISSING |
|
93 | ); |
||
94 | } |
||
95 | 2 | $subscriptionKey = $metadata->get(self::METADATA_KEY); |
|
96 | 2 | if ($subscriptionKey !== $this->key) { |
|
97 | 1 | throw new EnvelopeNotAcceptable( |
|
98 | 1 | "Subscription '{$this->key}' inadvertently received Envelope ". |
|
99 | 1 | "'{$envelope->getUuid()->toString()}' for subscription '$subscriptionKey'.", |
|
100 | 1 | EnvelopeNotAcceptable::SUBSCRIPTION_KEY_UNEXPECTED |
|
101 | ); |
||
102 | } |
||
103 | 1 | } |
|
104 | } |
||
105 |