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 WC_Stripe_Helper 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 WC_Stripe_Helper, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
11 | class WC_Stripe_Helper { |
||
12 | const LEGACY_META_NAME_FEE = 'Stripe Fee'; |
||
13 | const LEGACY_META_NAME_NET = 'Net Revenue From Stripe'; |
||
14 | const META_NAME_FEE = '_stripe_fee'; |
||
15 | const META_NAME_NET = '_stripe_net'; |
||
16 | const META_NAME_STRIPE_CURRENCY = '_stripe_currency'; |
||
17 | |||
18 | /** |
||
19 | * Gets the Stripe currency for order. |
||
20 | * |
||
21 | * @since 4.1.0 |
||
22 | * @param object $order |
||
23 | * @return string $currency |
||
24 | */ |
||
25 | public static function get_stripe_currency( $order = null ) { |
||
32 | |||
33 | /** |
||
34 | * Updates the Stripe currency for order. |
||
35 | * |
||
36 | * @since 4.1.0 |
||
37 | * @param object $order |
||
38 | * @param string $currency |
||
39 | */ |
||
40 | public static function update_stripe_currency( $order = null, $currency ) { |
||
47 | |||
48 | /** |
||
49 | * Gets the Stripe fee for order. With legacy check. |
||
50 | * |
||
51 | * @since 4.1.0 |
||
52 | * @param object $order |
||
53 | * @return string $amount |
||
54 | */ |
||
55 | View Code Duplication | public static function get_stripe_fee( $order = null ) { |
|
74 | |||
75 | /** |
||
76 | * Updates the Stripe fee for order. |
||
77 | * |
||
78 | * @since 4.1.0 |
||
79 | * @param object $order |
||
80 | * @param float $amount |
||
81 | */ |
||
82 | public static function update_stripe_fee( $order = null, $amount = 0.0 ) { |
||
89 | |||
90 | /** |
||
91 | * Deletes the Stripe fee for order. |
||
92 | * |
||
93 | * @since 4.1.0 |
||
94 | * @param object $order |
||
95 | */ |
||
96 | View Code Duplication | public static function delete_stripe_fee( $order = null ) { |
|
106 | |||
107 | /** |
||
108 | * Gets the Stripe net for order. With legacy check. |
||
109 | * |
||
110 | * @since 4.1.0 |
||
111 | * @param object $order |
||
112 | * @return string $amount |
||
113 | */ |
||
114 | View Code Duplication | public static function get_stripe_net( $order = null ) { |
|
133 | |||
134 | /** |
||
135 | * Updates the Stripe net for order. |
||
136 | * |
||
137 | * @since 4.1.0 |
||
138 | * @param object $order |
||
139 | * @param float $amount |
||
140 | */ |
||
141 | public static function update_stripe_net( $order = null, $amount = 0.0 ) { |
||
148 | |||
149 | /** |
||
150 | * Deletes the Stripe net for order. |
||
151 | * |
||
152 | * @since 4.1.0 |
||
153 | * @param object $order |
||
154 | */ |
||
155 | View Code Duplication | public static function delete_stripe_net( $order = null ) { |
|
165 | |||
166 | /** |
||
167 | * Get Stripe amount to pay |
||
168 | * |
||
169 | * @param float $total Amount due. |
||
170 | * @param string $currency Accepted currency. |
||
171 | * |
||
172 | * @return float|int |
||
173 | */ |
||
174 | public static function get_stripe_amount( $total, $currency = '' ) { |
||
185 | |||
186 | /** |
||
187 | * Localize Stripe messages based on code |
||
188 | * |
||
189 | * @since 3.0.6 |
||
190 | * @version 3.0.6 |
||
191 | * @return array |
||
192 | */ |
||
193 | public static function get_localized_messages() { |
||
220 | |||
221 | /** |
||
222 | * List of currencies supported by Stripe that has no decimals |
||
223 | * https://stripe.com/docs/currencies#zero-decimal from https://stripe.com/docs/currencies#presentment-currencies |
||
224 | * |
||
225 | * @return array $currencies |
||
226 | */ |
||
227 | public static function no_decimal_currencies() { |
||
247 | |||
248 | /** |
||
249 | * Stripe uses smallest denomination in currencies such as cents. |
||
250 | * We need to format the returned currency from Stripe into human readable form. |
||
251 | * The amount is not used in any calculations so returning string is sufficient. |
||
252 | * |
||
253 | * @param object $balance_transaction |
||
254 | * @param string $type Type of number to format |
||
255 | * @return string |
||
256 | */ |
||
257 | public static function format_balance_fee( $balance_transaction, $type = 'fee' ) { |
||
276 | |||
277 | /** |
||
278 | * Checks Stripe minimum order value authorized per currency |
||
279 | */ |
||
280 | public static function get_minimum_amount() { |
||
317 | |||
318 | /** |
||
319 | * Gets all the saved setting options from a specific method. |
||
320 | * If specific setting is passed, only return that. |
||
321 | * |
||
322 | * @since 4.0.0 |
||
323 | * @version 4.0.0 |
||
324 | * @param string $method The payment method to get the settings from. |
||
325 | * @param string $setting The name of the setting to get. |
||
326 | */ |
||
327 | public static function get_settings( $method = null, $setting = null ) { |
||
336 | |||
337 | /** |
||
338 | * Checks if Pre Orders is available. |
||
339 | * |
||
340 | * @since 4.1.0 |
||
341 | * @return bool |
||
342 | */ |
||
343 | public static function is_pre_orders_exists() { |
||
346 | |||
347 | /** |
||
348 | * Checks if WC version is less than passed in version. |
||
349 | * |
||
350 | * @since 4.1.11 |
||
351 | * @param string $version Version to check against. |
||
352 | * @return bool |
||
353 | */ |
||
354 | public static function is_wc_lt( $version ) { |
||
357 | |||
358 | /** |
||
359 | * Gets the webhook URL for Stripe triggers. Used mainly for |
||
360 | * asyncronous redirect payment methods in which statuses are |
||
361 | * not immediately chargeable. |
||
362 | * |
||
363 | * @since 4.0.0 |
||
364 | * @version 4.0.0 |
||
365 | * @return string |
||
366 | */ |
||
367 | public static function get_webhook_url() { |
||
370 | |||
371 | /** |
||
372 | * Gets the order by Stripe source ID. |
||
373 | * |
||
374 | * @since 4.0.0 |
||
375 | * @version 4.0.0 |
||
376 | * @param string $source_id |
||
377 | */ |
||
378 | View Code Duplication | public static function get_order_by_source_id( $source_id ) { |
|
389 | |||
390 | /** |
||
391 | * Gets the order by Stripe charge ID. |
||
392 | * |
||
393 | * @since 4.0.0 |
||
394 | * @since 4.1.16 Return false if charge_id is empty. |
||
395 | * @param string $charge_id |
||
396 | */ |
||
397 | View Code Duplication | public static function get_order_by_charge_id( $charge_id ) { |
|
412 | |||
413 | /** |
||
414 | * Gets the order by Stripe PaymentIntent ID. |
||
415 | * |
||
416 | * @since 4.2 |
||
417 | * @param string $intent_id The ID of the intent. |
||
418 | * @return WC_Order|bool Either an order or false when not found. |
||
419 | */ |
||
420 | View Code Duplication | public static function get_order_by_intent_id( $intent_id ) { |
|
431 | |||
432 | /** |
||
433 | * Gets the order by Stripe SetupIntent ID. |
||
434 | * |
||
435 | * @since 4.3 |
||
436 | * @param string $intent_id The ID of the intent. |
||
437 | * @return WC_Order|bool Either an order or false when not found. |
||
438 | */ |
||
439 | View Code Duplication | public static function get_order_by_setup_intent_id( $intent_id ) { |
|
450 | |||
451 | /** |
||
452 | * Sanitize statement descriptor text. |
||
453 | * |
||
454 | * Stripe requires max of 22 characters and no |
||
455 | * special characters with ><"'. |
||
456 | * |
||
457 | * @since 4.0.0 |
||
458 | * @param string $statement_descriptor |
||
459 | * @return string $statement_descriptor Sanitized statement descriptor |
||
460 | */ |
||
461 | public static function clean_statement_descriptor( $statement_descriptor = '' ) { |
||
471 | } |
||
472 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.