劣质代码的产生原因(2)编程语言知识不足 (续2)

 

3.正则表达式

    a. 白名单

    下列代码是用来进行白名单校验的,即如果输入的文字符合条件的话就返回true,否则返回false。

 1 private static final String[] ENABLED_TEXTS = new String[]{"a", "b", "c", "d", "e"};

 2 

 3 public boolean isEnabled(String input) {

 4     for (String text : ENABLED_TEXTS) {

 5         if (text.equals(input)) {

 6             return true;

 7         }

 8     }

 9     return false;

10 }

    当改成使用正则表达式进行校验的时候,代码变成下面这样:

1 public boolean isEnabled(String input) {

2     return input.matches("a|b|c|d|e");

3 }

 

4.用异常代替错误号

   有一段报名课程的代码:

 1 public String register(int userId, int lessonId) {

 2     int ret = checkUser(userId);

 3     if (ret != 0) {

 4          return "User does not exist.";

 5     }

 6 

 7     ret = checkLesson(lessonId);

 8     if (ret != 0) {

 9          return "Lesson does not exist.";

10     }

11 

12     ret = checkLessonExpire(lessonId);

13     if (ret != 0) {

14          return "Lesson is expired.";

15     }

16 

17     ret = register(userId, lessonId);

18     if (ret != 0) {

19          return "Register failed.";

20     }

21 

22     return "";

23 }

    其中有若干处用到了ret这个变量,ret的值检查代码使得代码变长,而且业务流程代码距离拉开了,变得不容易理解。

1 public void register(int userId, int lessonId) throws BusinessException {

2     checkUser(userId);

3     checkLesson(lessonId);

4     checkExpire(lessonId);

5     registerLesson(userId, lessonId);

6 }

    当把上述方法原来的int类型返回值去掉,改成throws BusinessException。修改之后的代码变得紧凑多了。

5.位运算

    计算机表示数据是采用二进制的,几乎所有的计算机培训课程都从二进制开始,但是当写程序到一定程度之后,却忘记了利用二进制的基本运算来简化代码,加快效率。

    a.奇偶运算

     思路1:常见做法是数字除以2求余数

 1 public class OddEven {

 2 

 3     public boolean isEven(int num) {

 4         return num % 2 == 0;

 5     }

 6     

 7     public static void main(String[] args) {

 8         OddEven instance = new OddEven();

 9         System.out.println("3 is " + (instance.isEven(3)?"Even":"Odd"));

10     }

11 }

   思路2:采用位运算之后,代码变成下面这样:

 1 public class OddEven {

 2 

 3     public boolean isEven(int num) {

 4         return (num & 1) == 0;

 5     }

 6     

 7     public static void main(String[] args) {

 8         OddEven instance = new OddEven();

 9         System.out.println("3 is " + (instance.isEven(3)?"Even":"Odd"));

10         System.out.println("36 is " + (instance.isEven(3)?"Even":"Odd"));

11     }

12 }

进一步,我们来看一个斑马线的例子。
    思路1的做法:

 

 1 import java.awt.Color;

 2 

 3 public class Zembra {

 4 

 5     public Color getZembraColor(int index) {

 6         if (index % 2 ==0) {

 7             return Color.GRAY;

 8         } else {

 9             return Color.WHITE;

10         }

11     }

12     

13     public static void main(String[] args) {

14         Zembra zembra = new Zembra();

15         System.out.println(zembra.getZembraColor(23).toString());

16     }

17 }


思路2的做法:

 1 import java.awt.Color;

 2 

 3 public class Zembra {

 4 

 5     public Color getZembraColor(int index) {

 6         Color[] colors = new Color[]{Color.GRAY, Color.WHITE};

 7         return colors[index & 1];

 8     }

 9     

10     public static void main(String[] args) {

11         Zembra zembra = new Zembra();

12         System.out.println(zembra.getZembraColor(23).toString());

13     }

14 }

代码行数比思路1短了,并且,代码的执行效率提高了。但是易懂性有所降低。

 b. Bit Mask

  有些时候我们需要有多种不同层级的属性来表征事物的属性,或者对于同一事物的多种可以并存的属性。

  比如:字体的下划线、粗体、斜体。

  如果采用若干个变量来定义各种属性则每种属性都要设立一个变量。随着可以扩展的属性越来越多,所需要的变量也越来越多,将降低代码的可读性,可理解性。

  为了防止这种属性扩大引起的变量增多的麻烦,以及为未来可能的扩展留有余地,可以采用Bit Mask。

  比如:字体来说每一位(bit)表示一种属性。例如从最后一位开始向左,依次为:下划线、粗体、斜体、删除线、双删除线、上标、下标...

   那么想要知道某一位是否被设置可以通过位运算来获取。

   例如:Font.style来定义那么,计算是否为粗体,那么下列算式用来计算。

   Font.style & 2 == 2

   同样,该技术被应用于窗口属性、文本框语种限制等处。

 c. 四则运算

  当需要计算一个中间值的时候,采用的是(a + b) / 2的形式,但是这个算法有一个Bug,当a+b > Integer.Max的时候,会将计算结果变成负数。

  正确的形式应该是 (a + b) >>> 1;

  具体可以参照Java的二分法Bug报告:

     http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5045582

你可能感兴趣的:(编程语言)