JAVA新手入门01

JAVA新手入门01

这篇文章给新入门的程序员看的,高手就不要看了,对于刚开始参加工作,或者在大学学习了计算机的编程知识,不管是学的C语言,还是JAVA,还是C# 等等,都迫切的想要提高自己,这篇文章将结合本人多年的编程经验,说一说新手在编程中,应当注意的一些事项。这些代码,可能工作了很多年的程序员还在写,有可能你也在写,有可能是你不得不这么做,看完了这篇文章,相信你对程序 员为什么写出了屎山一样的代码,就知道点原因了。这可能是一个沉重的话题,不该新手来承担,每个程序员优不要随意的写if else,那么代码就更好维护了。

你真的学会了if else 了吗?

关注我的博客,获取更多Java编程知识: https://www.epoooll.com/

场景1,我们有1个变量的值type:

type =0 表示A种情况 type=1 表示另外一种情况,可能会有更多的情况,在不用switch的情况下,你会有以下2种写法(java版本的,且省略了大括号,你们写代码的时候,即使只有1行代码,也要写{}):

推荐写法:

if(type == 0)
	do something;
else if(type == 1)
	do something
throw new RuntimeException("类型错误,请检查:" + type);

不推荐写法:

if(type == 0)
	do something
else
	do something

这种写法,在某一天,如果type的值增加了1个,测试的时候容易出现诡异的BUG,如果你不测试,直接上线了,那可能会更糟糕。

严格检查类型的值,否则容易出错,当type的类型是固定的几个值的时候,即使是用switch case when实现,也要注意这种类似的错误,尤其是以后typ的值增加了,错误的写法还不容易发现,尽量让代码早报错,可以避免不少BUG

核心思想:严格检查类型的值,程序要早报错

延伸 你对抽象的理解对吗?

我们接着上文,假设有变量a b,a、b在不同的情况下,有不同的业务场景,例如:

a == 1 && b== 1 表示客户现金支付
a == 1 && b == 2 表示客户信用卡支付

推荐写法:

if(a == 1 && b == 1) {
	do something
}

if(a == 1 && b == 2) {
	do something
}

不推荐写法:

if(a == 1 && b == 1) {
	do something
} else if( a == 1 && b == 2) {
	do something
}

这2种写法会有细微的区别,看起来功能是一样的,在逻辑简单的时候,几乎一样,当以后的逻辑更复杂的时候,会有不同,例如 增加了1个变量c,前面1种情况,可以更好的处理增加了c的这种情况, 后面的写法,就需要慎重的考虑,c应该放在哪个位置,增加了else,测试的时候就复杂了很多。

一种更好的办法是抽象逻辑

int type;
if(a == 1 && b == 1) {
	type = 0; //客户现金支付
}
if( a == 1 && b == 2) {
	type = 1; //客户信用卡支付
}
switch(type) {
	case 0:
		do something;
		break;
	case 1:
		do something;
		break;
	default:
		do somthing;
		break;
}

这样就能在众多复杂的代码中,把业务发生代码的前缀,和业务的实际处理逻辑,剥离开来,将代码抽象成2部分,1部分用来描述业务发生的条件,1部分用来描述业务条件触发之后的逻辑。

上述的代码,只是为了演示使用,不能作为实际的支付逻辑的处理。

如果对上述代码,再进行修改的话:

if(a == 1 && b == 1) {
	type = 0; //客户现金支付
}

修改为:

if(cash(a,b)) {
	type = 0; //客户现金支付
}

这样是不是代码更容易阅读了呢? 我们是不是可以更进一步,把type的值用枚举来表示呢?

enum PAY_CHANNEL {
	CASH,CREDIT_CARD;
}

PAY_CHANNEL channel = PAY_CHANNEL.CASH;

if(cash(a,b)) {
	channel = PAY_CHANNEL.CASH;
}

if(credit_card(a,b)) {
	channel = PAY_CHANNEL.CREDIT_CARD;
}

switch(channel) {
	case PAY_CHANNEL.CASH:
		do something;
		break;
	case PAY_CHANNEL.CREDIT_CARD:
		do something;
		break;
	default:
		do something;
		break;
}

当然,要不要把一个if else写到如此的复杂,就要看实际的需求的情况了。

还有一种比较容易出错的地方是,只写了if ,不写else ,这种写法,也会带来一些隐蔽的错误,当然,并不是任何情况下,不写else,都会出错,只是写代码的时候,要考虑下,到了else,我该怎么办? 所以:

if( cond ) {
	do something
}

结果等同于

if( cond ) {
	// cond == true
	do something
} else {
	// cond == false 时候,是不是真的什么都不做
	// do nothing
}

总是要确认,是不是真的在else中什么都不做。

DEBUG 可以有一些技巧

在JAVA中,你可以定义一个测试类,叫DebugConstant,然后其中可以定义很多debug的常量信息,例如:

public static boolean DEBUG = false;
public static int DEBUG_SKU = 12345; // 表示遇到该SKU时候,打印DEBUG日志信息

然后在业务代码中,写:

if(DEBUG)
	do something

这样在单元测试中,就可以开启DEBUG或者,你也可以设置Java的启动参数 -DDEBUG=true 来启动DEBUG信息,当然,如果你学习的是C语言,那就可以使用条件编译了,定义1个变量DEBUG,需要DEBUG的时候就开启

需要debug的时候,直接

#define DEBUG 1

if(DEBUG) {
    do something
}

核心思想: 善用条件编译,来实现DEBUG

finally只用来释放资源

看看这段代码会返回什么?

try {
	return true;
} finally {
	return false;
}

实际会返回false,所以给我们的启示就是finally中,不能返回值只可以用来做释放资源(文件流、锁等)

谨慎修改常量的值

如果你修改了1个常量的值,一定要全局搜索所有使用这个常量的地方,仔细判断这个修改,是否有副作用。需要注意的是,注解里面不可以使用常量,一定要特别注意,尤其是mybatis的多数据源配置。

思考下return的位置

在日常的开发中,经常会写1个函数,返回1个值,在函数执行的过程中,会有各种各样的判断,各种情况,可能会中途跳出,如果是C语言,可以使用goto,如果是Java的话,就需要仔细思考下,把return的位置放在哪里,接下来仔细研究,该怎么做:

提前声明返回值,并在最后返回。

这种方法是1种最常见的写法,不容易出错,而且代码容易看懂,也容易跟踪变量的变化,如果业务十分复杂,难免会增加复杂度,但是不论如何增加复杂度,
在AB之间,都不要写return就行了。

public int sum(int a,int b) {

	int res = 0; // A
	try {
		res = a + b;
	} catch(Exception e) {
		res = -1; // 不要纠结这个-1,只是为了演示
	}
	return res; // B
}

上面的代码在稳定运行之后,需求有变化,需要判断一些特殊值,而且这个业务,可能和这个方法没有特别大的关系,当然,且不论是否应该修改sum方法,更好的办法当然是在调用sum方法的地方,去处理特殊值,这里我们假设,我们必须修改sum方法,可能是因为有很多的地方都调用了sum方法,导致如果不修改sum方法,而是去修改调用sum方法的地方,会修改很多处代码。

从现在开始,就有2种写法了:

方法1(不推荐):

public int sum(int a,int b) {

	int res = 0; // A
	try {
		if(a <= 0 ) {
				return 2 * b;
		}
		res = a + b;
	} catch(Exception e) {
			res = -1;
	}
	return res; // B
}

方法2(推荐):

public int sum(int a,int b) {

	int res = 0; // A
	try {
		if(a <= 0 ) {
				res = 2 * b;
		} else {
				res = a + b;
		}
	} catch(Exception e) {
			res = -1;
	}
	return res; // B
}

这2个方法是完全不同的编码习惯,相信我,在你的编程生涯中,你会无时不刻的面临这个选择,所以需要慎重的考虑下,到底应该采用哪种方法来处理这种情况,接下来,我们稍微把刚才的例子,再增加一些变化,这里我们选择使用推荐的方法2来做变化,增加了1个需求,如果a = 15,那么就固定的返回错误-1,该怎么做呢?

方法1: 在方法开头的地方直接判断并返回

public int sum(int a,int b) {

	// a == 15表示程序异常了,需要直接返回
	if( a == 15 ) {
			return -1;
	}
	int res = 0; // A
	try {
		if(a <= 0 ) {
				res = 2 * b;
		} else {
				res = a + b;
		}
	} catch(Exception e) {
			res = -1;
	}
	return res; // B
}

方法2: 在逻辑运算中增加1种情况

public int sum(int a,int b) {

	int res = 0; // A
	try {
		if(a == 15 ) {
				res = -1;
		} else if( a <= 0 ) {
				res = 2 * b;
		} else {
				res = a + b;
		}
	} catch(Exception e) {
			res = -1;
	}
	return res; // B
}

现在,我们拥有了1个相对来说比较复杂的方法,有正常的业务逻辑,但是代码的量不多,有异常处理,有特殊业务的处理,这个方法已经比最开始的代码,复杂了不少,在实际的开发中,可能此时这个方法已经不是30行左右了,而是300行 600行了,恭喜你,你已经在制造所谓的“代码屎山”了,多年以后,当你再看到这段代码的时候,可能你也会在心里狠狠的咒骂一句,那个XX写的代码,然后看了代码的提交记录,发现是自己写的,默默的把它关闭了。也可能是某位已经离职/在职/升职的同事写的,不过无论是谁写的,这都是一个不美好的一天。

然后我们来思考以下对策,该怎么处理,这里我们仍然坚持最开始的初衷,AB之间不返回值(如果代码中途返回值会大大增加复杂度),此时需要处理的是,判断哪些是异常情况,哪些是正常情况,也就是说,对参数进行检查,是可以方法的开头的,这并不影响:

if(a == 15) {
	return -1;
}

或者是

if(checkParam(a,b) == false) {
	return -1;
}

可以在方法的开头,增加参数的有效性的检查,同时,要把各种业务情况抽象出来,走不同的分支,具体的做法,可以参考本文开头的if else的部分,总之,不能在方法的中间随意的return,但这也仅仅是一家之言,如果不同意这个看法,也可以不考虑这个准则。

结论: 尽量不在方法体中间return

全文完。

关注我的博客,获取更多Java编程知识: 双King的技术博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值