Post

一个有趣的程序员

switch

事情起因是在codewars练习的时候,一个很简单的题目,用switch方法就能普通解决的,大概描述下题目,就是有个服务员,如果你认为服务员服务的好,你就会把小费提高点,

1
2
3
4
5
Terrible: tip 0%
Poor: tip 5%
Good: tip 10%
Great: tip 15%
Excellent: tip 20%

要求给两个参数,amountrating,返回一个最终的小费整数,其中rating是不区分大小写的,且如果不在5种评价的话,返回null, 这是一个非常基础的题目,考察switch或者if else,正常代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TipCalculator {

  public static Integer calculateTip(double amount, String rating) {
   
    switch(rating.toLowerCase()) {
      case "terrible": return 0;
      case "poor": return (int) Math.ceil(amount * 0.05);
      case "good": return (int) Math.ceil(amount * 0.1);
      case "great": return (int) Math.ceil(amount * 0.15);
      case "excellent": return (int) Math.ceil(amount * 0.2);
      default: return null;
    }   
  }
}

可以看到,就是最基础的逻辑,查阅他人解答后,发现有一兄弟不走寻常路,且收获了不少点赞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
  This attempt uses best practices learned from:
  Code Complete 2nd Edition by Steve McConnell (CC2E)
  TDD by Example by Kent Beck (TDD)
  The Art Of Unit Testing by Roy Osherov (ARTOF)
  
  See the comments below for references to the suggestions from these books.
*/

public class TipCalculator {

  // NOTE: I prefix line comments with a carriage return which would help readers of your 
  // code quickly grok the intent of the application - CC2E Chapter 31.6
  
  // Enumerated types helps with readability, reliability, and modifiability - CC2E Chapter 12.6
  private enum ServiceRating {
    TERRIBLE,
    POOR,
    GOOD,
    GREAT,
    EXCELLENT
  }

  // Using Named Constants helps with Maintainability and Readability - CC2E Chapter 12.7
  static final Integer Terrible_Tip = 0;
  static final Double POOR_PERCENTAGE_MULTIPLIER = 0.05;
  static final Double GOOD_PERCENTAGE_MULTIPLIER = 0.10;
  static final Double GREAT_PERCENTAGE_MULTIPLIER = 0.15;
  static final Double EXCELLENT_PERCENTAGE_MULTIPLIER = 0.20;
  public static Integer calculateTip(double amount, String rating) {
  
    // We have to wrap this in a try catch because valueOf will throw an InvalidArgumentException if the Enum does not exist
    try {
      var ratingEnum = ServiceRating.valueOf(rating.toUpperCase());
      switch(ratingEnum){
        case TERRIBLE: 
            return Terrible_Tip;
        case POOR:
        
            // Possible refacoring here is removing the duplicationby creating a private method and passing
            // in the amount and - TDD Chapter 1
            return (int)Math.ceil(amount * POOR_PERCENTAGE_MULTIPLIER);
        case GOOD:
            return (int)Math.ceil(amount * GOOD_PERCENTAGE_MULTIPLIER);
        case GREAT:
            return (int)Math.ceil(amount * GREAT_PERCENTAGE_MULTIPLIER);
        case EXCELLENT:
            return (int)Math.ceil(amount * EXCELLENT_PERCENTAGE_MULTIPLIER);
        
        // You should use the default only for error detection unless every possible input is valid. - CC2E Chapter 15.2  
        default:
        
            //The code will technically never get here but I left it in for demonstration purposes, please read below.
            throw new IllegalArgumentException();
        }
     }
     catch(IllegalArgumentException e){
     
       /* 
         Here you could log your exceptions but we don't want the program to crash, so we return a null value.
         You could argue that we should just return NULL from default, but I wanted to show this as a possible implementation
         and it is required because of how we implemented the name checking using valueOf on the enum
       */ 
       return null;
     }
  }
}

别问,学

也不知道这哥们是不是在_防御性编程_,或者这就是规范性编程,有时间应该好好研究学习下!!!

This post is licensed under CC BY 4.0 by the author.