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 |
||
14 | class WC_Cart_Item implements ArrayAccess { |
||
15 | |||
16 | /** |
||
17 | * Cart Data array. |
||
18 | * @since 2.7.0 |
||
19 | * @var array |
||
20 | */ |
||
21 | protected $data = array( |
||
22 | 'product_id' => 0, |
||
23 | 'quantity' => 0, |
||
24 | 'variation' => array(), |
||
25 | ); |
||
26 | |||
27 | /** |
||
28 | * Product this item represents. |
||
29 | * @var WC_Product |
||
30 | */ |
||
31 | protected $product = null; |
||
32 | |||
33 | /** |
||
34 | * Constructor. |
||
35 | * @param array $data |
||
36 | */ |
||
37 | public function __construct( $data = array() ) { |
||
40 | |||
41 | /** |
||
42 | * offsetGet for ArrayAccess/Backwards compatibility. |
||
43 | * @deprecated Add deprecation notices in future release. |
||
44 | * @param string $offset |
||
45 | * @return mixed |
||
46 | */ |
||
47 | public function offsetGet( $offset ) { |
||
56 | |||
57 | /** |
||
58 | * offsetSet for ArrayAccess/Backwards compatibility. |
||
59 | * @deprecated Add deprecation notices in future release. |
||
60 | * @param string $offset |
||
61 | * @param mixed $value |
||
62 | */ |
||
63 | public function offsetSet( $offset, $value ) { |
||
76 | |||
77 | /** |
||
78 | * offsetExists for ArrayAccess |
||
79 | * @param string $offset |
||
80 | * @return bool |
||
81 | */ |
||
82 | public function offsetExists( $offset ) { |
||
88 | |||
89 | /** |
||
90 | * offsetUnset for ArrayAccess |
||
91 | * @param string $offset |
||
92 | */ |
||
93 | public function offsetUnset( $offset ) { |
||
96 | |||
97 | /** |
||
98 | * Gets price of the product. |
||
99 | * @return float |
||
100 | */ |
||
101 | public function get_price() { |
||
104 | |||
105 | /** |
||
106 | * Gets price of the product. |
||
107 | * @return float |
||
108 | */ |
||
109 | public function get_weight() { |
||
112 | |||
113 | /** |
||
114 | * Gets price of the product. |
||
115 | * @return float |
||
116 | */ |
||
117 | public function get_tax_class() { |
||
120 | |||
121 | /** |
||
122 | * Set product. |
||
123 | * @param int $value |
||
124 | */ |
||
125 | public function set_product( $value ) { |
||
129 | |||
130 | /** |
||
131 | * Get product object. |
||
132 | * @return WC_Product |
||
133 | */ |
||
134 | public function get_product() { |
||
137 | |||
138 | /** |
||
139 | * Get all item data. |
||
140 | * @return array |
||
141 | */ |
||
142 | public function get_data() { |
||
145 | |||
146 | /** |
||
147 | * Product or variation ID this item represents. |
||
148 | * @return int |
||
149 | */ |
||
150 | public function get_product_id() { |
||
153 | |||
154 | /** |
||
155 | * Get quantity in cart. |
||
156 | * @return int |
||
157 | */ |
||
158 | public function get_quantity() { |
||
161 | |||
162 | /** |
||
163 | * Get variation data. |
||
164 | * @return array |
||
165 | */ |
||
166 | public function get_variation() { |
||
169 | |||
170 | /** |
||
171 | * Set product ID. |
||
172 | * @param int $value |
||
173 | */ |
||
174 | public function set_product_id( $value ) { |
||
178 | |||
179 | /** |
||
180 | * Set Quantity. |
||
181 | * @param int $value |
||
182 | */ |
||
183 | public function set_quantity( $value ) { |
||
186 | |||
187 | /** |
||
188 | * Set variation data. |
||
189 | * @param array $value |
||
190 | */ |
||
191 | public function set_variation( $value ) { |
||
194 | |||
195 | /** |
||
196 | * Set all data. |
||
197 | * @param array $value |
||
198 | */ |
||
199 | public function set_data( $values ) { |
||
211 | } |
||
212 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: