java编程之美(一)

实践编程已经有足足6年多时间,也算是有一定经验,经常在工作中遇到各种让人不爽的代码编写方式,今天忍不住要来唠叨下。

为什么叫编程之美? 在我看来,代码有丑陋难看和赏心悦目两类,当然还有介于两者之间的。优秀开源框架的源码,让人看了就觉得舒服;而有些新手写的代码,让人看了别扭、添堵。本人也是从新手一步步过来的,想想自己早年写得代码,也是很丑的。当年丑不要紧,一直丑就要命了。

废话不多说,上干货。咱们就以java语言为例,对比说明”丑”跟”美”的代码(其实跟具体语言没有关系,仅以java语言举例)

一、全局静态常量满屏飞

此话怎讲,就是定义了很多静态常量,不适用的情况也在用。就举表设计中常有的status(状态)字段,一般有正常、删除、禁用这三种状态

丑的实现如下:

    public static final int NORMAL = 0;//正常
    
    public static final int DELETED = 1;//删除
    
    public static final int FORBIDDEN = 2;//禁用

然后在代码各个地方引用这些静态常量,然后我就醉了,原因先不说,先说怎么改进

美的实现如下:

/**
 * <数据状态枚举类>
 */
public enum StatusEnum {
    NORMAL(0, "正常"), DELETED(1, "删除"), FORBIDDEN(2, "禁用");

	private int code;

	private String meaning;

	StatusEnum(int code, String meaning) {
		this.code = code;
		this.meaning = meaning;
	}

	/**
	 * @return 返回 code
	 */
	public int getCode() {
		return code;
	}

	/**
	 * @return 返回 meaning
	 */
	public String getMeaning() {
		return meaning;
	}

	/**
	 * 可读的状态
	 * 
	 * @param code
	 * @return
	 */
	public static String readableInfo(int code) {
		StatusEnum ret = null;
		for (StatusEnum e : StatusEnum.values()) {
			if (e.code == code) {
				ret = e;
				break;
			}
		}
		return ret == null ? "" : ret.meaning;
	}
}

很显然,我们改用了枚举类来实现,因为状态就那么几种,是可以列举完的。实际中很多情况都是适用枚举类来实现,而不是静态常量,比如用户性别(只有男/女/保密三种可能)、用户类型(比如普通/会员制)、用户职业(有很多职业,但肯定是个有限确定的范围)等等。

那么这么改进的好处是什么呢?

简单说,这么改符合程序设计的开闭原则。所谓开闭原则,就是指对扩展开放、对修改关闭。

请注意StausEnum类的公有静态方法readableInfo,作用就是将status的int值转换成可读的字符串,以方便在web页面展示。假设将来新增了一个状态3,代表已审核,美的实现中只需要新加一个枚举常量

CHECKED(3, "已审核")

其它任何地方都不需要做修改,是不是很酷啊。

而如果是丑的实现,则需要在页面或action中修改类似判断(如果是jsp页面,判断的方式可能是<c:if>或<c:choose>方式)

        String statusReadable = "";
        if(status == NORMAL){
            statusReadable = "正常";
        }else if(status == DELETED){
            statusReadable = "正常";
        }else if(status == FORBIDDEN){
            statusReadable = "正常";
        }else if(status == CHECKED){
            statusReadable = "已审核";
        }

如果很多地方都写了类似的代码,就意味着你需要改N个地方,是不是想死的心都有了。

通过封装StatusEnum枚举类,将status的修改局限在这个类的内部,内部状态的增减或修改对外部是完全透明的,这就是开闭原则的一个典型例子。

下面说下修改这种情况,虽然不常见,但还是可能出现。

诡异情况举例

假如状态改为-1表示删除,对于丑的实现,只要修改下常量定义就可以,即改为

    public static final int DELETED = -1;//删除

这没什么问题。但是在升级时,千万不要以为只升级这个类的class文件就行了,而是需要将引用到这个静态常量的所有相关类的class文件都进行升级,不然就会出现开发环境正常,到了线上就是不正常的诡异事情。

这个情况是怎么来的呢?

这就要说到java编译了,java编译就是将java源代码编译成java字节码文件,即class文件。只有编译成class文件,才能在JVM上运行,程序才能跑起来。

而在java编译时,会将类中引用的静态常量(该静态常量必须是基本数据类型或String常量)用他们的字面量代替,也就是编译后的class文件中,只存在字面量(比如int类型的字面量0,-1,1等),并不存在对该静态常量的引用。如果光升级定义静态常量的类的class文件,实际上引用到这个静态常量的其它class文件中的字面量并没有更新,就会造成升级失败。

而如果采用的是StatusEnum类的实现,就不会出现这个情况,修改为

    DELETED(-1, "删除")

升级时,也只需要升级StatusEnum类对应的class文件即可。


总结

项目中很多情况适用枚举类,而不是静态常量方式。好好利用枚举实现,你会发现代码比以前简洁明了了,扩展和可维护性增强了,而且不容易犯错。

假如方法的接收参数类型是StatusEnum类型,你不可能传成状态范围之外的值

而如果接收的参数是int类型,则完全有可能传成0,1,2之外的值,这样就有可能产生隐藏BUG。


编程之美,未完待续,欢迎大家拍砖


    原文作者:一汪清水
    原文地址: https://blog.csdn.net/tang9140/article/details/49560335
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞