论坛首页 Java企业应用论坛

用enum代替if.这个设计大家怎么看

浏览 29664 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-10-10  
过度设计也是病。应该到真正应该重构的时候再重构,否则就是把本来简单的事情弄复杂,到时候别人看类结构就头晕,那比if else爆炸更头疼
0 请登录后投票
   发表时间:2012-10-10  
cpszgy 写道
devroller2 写道
cpszgy 写道
devroller2 写道
cpszgy 写道
模式最重要的一点就是不要为了模式而模式,
我觉得原来的代码的可读性和扩展的问题都不是特别大。
目前的重构确实没有多大的必要。如果到时候真的一下子超过5种情况了再重构也不迟。当让你用了enum我第一想到的是用switch去替换if,结果用了for。。。那还不如原来的。要是真重构,最好还是根据value值来自动生成不同对象。比较合理。

为了模式而模式有何不好?没有人凭空想象就能学到东西,这也许是一些人实践模式的学习方法。总之,楼主有想法,敢做,其中的体会只有做了的人才知道。而且比原来的代码要强一些。


不过话说回来,模式不过是实现OO目标的具体方法、途径而已,请抛开模式!设计时心中多想想你的代码如何做到符合OO的目标就可以了,如果达到OO的目标,你的代码自然接近于那些模式。






简单的东西能解决,就用简单的。没必要一个3个if判断就能解决的问题非要用个设计模式。而且用了模式后会会增加类层次和理解的复杂度。再说这里还没到非要用到需要重构的时候。目前这么使用if判断我觉得是丝毫没有问题。


所谓上梁不正下梁歪,不好的东西会传染的,好的东西也会传染。这样的设计如果一个刚接手的人被分配任务在此段代码上处理,多数情况是这样:晕啊,我不熟悉业务,如果我要重构有担心出问题而且工作量大,所以最好的方法再加一个if。

结果if越来越多,我们项目就是这样。

我只是就这段代码而言,那如果现实就是这么3种情况呢,以后又不会扩展了呢。那目前所做的工作的实用性有多大呢。所以说未来的情况未来再说,在没必要做修改的情况下做出的修改带来的效果又不是很明显,我觉得实在不必。那后面接手的人不愿意修改难道会怪原来的人写的考虑不周全么。如果当时的情况就只有2到3个if判断,我非弄个3 ,4个类出来,再来个继承什么的。代码是不是写的过于复杂了呢。

不要幻想后面的人能够下决心来重构,他自己不愿意(我来挣钱,干嘛做吃力不讨好的事),老板不同意(我花钱是让你做开发,不是来美化代码)。

再说了,代码量一大,错综复杂的调用关系,重构不是一个简单的任务!

所以说过度设计比不设计好很多。

至于判断以后会不会扩展,设计人员的判断了。我觉得本例子中以后会有从不同页面进来的情况出现。

0 请登录后投票
   发表时间:2012-10-10   最后修改:2012-10-10
devroller2 写道
cpszgy 写道
devroller2 写道
cpszgy 写道
devroller2 写道
cpszgy 写道
模式最重要的一点就是不要为了模式而模式,
我觉得原来的代码的可读性和扩展的问题都不是特别大。
目前的重构确实没有多大的必要。如果到时候真的一下子超过5种情况了再重构也不迟。当让你用了enum我第一想到的是用switch去替换if,结果用了for。。。那还不如原来的。要是真重构,最好还是根据value值来自动生成不同对象。比较合理。

为了模式而模式有何不好?没有人凭空想象就能学到东西,这也许是一些人实践模式的学习方法。总之,楼主有想法,敢做,其中的体会只有做了的人才知道。而且比原来的代码要强一些。


不过话说回来,模式不过是实现OO目标的具体方法、途径而已,请抛开模式!设计时心中多想想你的代码如何做到符合OO的目标就可以了,如果达到OO的目标,你的代码自然接近于那些模式。






简单的东西能解决,就用简单的。没必要一个3个if判断就能解决的问题非要用个设计模式。而且用了模式后会会增加类层次和理解的复杂度。再说这里还没到非要用到需要重构的时候。目前这么使用if判断我觉得是丝毫没有问题。


所谓上梁不正下梁歪,不好的东西会传染的,好的东西也会传染。这样的设计如果一个刚接手的人被分配任务在此段代码上处理,多数情况是这样:晕啊,我不熟悉业务,如果我要重构有担心出问题而且工作量大,所以最好的方法再加一个if。

结果if越来越多,我们项目就是这样。

我只是就这段代码而言,那如果现实就是这么3种情况呢,以后又不会扩展了呢。那目前所做的工作的实用性有多大呢。所以说未来的情况未来再说,在没必要做修改的情况下做出的修改带来的效果又不是很明显,我觉得实在不必。那后面接手的人不愿意修改难道会怪原来的人写的考虑不周全么。如果当时的情况就只有2到3个if判断,我非弄个3 ,4个类出来,再来个继承什么的。代码是不是写的过于复杂了呢。

不要幻想后面的人能够下决心来重构,他自己不愿意(我来挣钱,干嘛做吃力不讨好的事),老板不同意(我花钱是让你做开发,不是来美化代码)。

再说了,代码量一大,错综复杂的调用关系,重构不是一个简单的任务!

所以说过度设计比不设计好很多。

至于判断以后会不会扩展,设计人员的判断了。我觉得本例子中以后会有从不同页面进来的情况出现。



嘿,设计本身就是一个复杂的关系(设计模式怎么都得用2个以上的类把?),然后你每个不必要的地方都去过度设计,那不用代码量大,自己就把代码弄的错综复杂了。而且你怎么知道你的设计能正好适合以后的扩展?每种设计适合的扩张方面是不同的,有的地方能灵活有的灵活不起来。万一将来需要的改动正好和你的设计背离,那改起来更是伤经动骨,说不定就如你所说的,后来的人嫌麻烦也不跟你重构,到时候就会留下一个无比别扭的代码,恶心的要死。

0 请登录后投票
   发表时间:2012-10-10  
对于他所说的情况跟本无解
只能等重写
0 请登录后投票
   发表时间:2012-10-10  
albeter 写道
evanzzy 写道
albeter 写道
evanzzy 写道
albeter 写道
evanzzy 写道
if else是程序中避免不了的写法,为什么非要去掉呢?而且从理论上讲也去不掉啊。

这个修改我看没什么实际意义,而且策略模式也不是这样用的。真要把if else去掉,还是map来的实惠,和spring搭配,能够直接往map里面注入行为实现类,比这个写法好看得多。


我可没说一定要把if else去掉。并不是说把if去掉代码就多好了,但是有时候if/else过多会影响代码的可读性,也就是在特定的情况下过多的if能反应出一些问题.你说的策略模式不是这样用的,那请问你的意思是不应该使用枚举策略呢?还是在这个情景下不应该这样使用?以及原因?


if else太多了当然不好,不过不是你这种解决办法。你这种办法只不过把if else的形式变了一下,翻译成汇编语言,还是一堆if else。你想想,如果有300个if else,那么你这个办法也要枚举300次,不对的。太多的分支,在java里面,就用map处理比较好,策略的实现类作为value注入到map里面,别说300个,300万个都可以的。

另外恕我技能拙劣,还真不知道有个叫枚举策略的写法,switch case倒是用过。策略模式是行为模式的一种,是以实现接口为基础的,不是你这样用的。

如果我们写程序的时候,第一反应是这个情况我应该用一种什么模式,那么证明你对设计模式还不熟悉,使用的时候就要慎重。


关于枚举策略的写法你可以参照effective java第二版的30条,另外策略模式通俗的理解可以理解为传递方法,接口实现只是实现该模式的一种具体方法,你可以比较下有指针的语言在实现策略模式的不同。另外也可以参照effective java第二版的21条。


Effective java2存在大量蛋疼的例子,在实践中根本遇不到,比如注释里面有\uXXXX会报错。比原来effective C++的水平差多了


就枚举策略这个用法来说thinking in java 中也有列举。既然两位大师都在自己的书中提到这个设计,我想这个设计会有些值得我们参考的地方。


Rod Johnson也是大师,而且是实践中证明过的大师。使用反向注入map的方式,既可以消灭if else,又可以不用那些蛋疼的模式,代码量也要小。说实话,大师所谓的枚举策略,还不如switch case来的直接和简单呢。要我说,3、5个if else根本没事儿,什么策略都不用,就写在那里就可以。而且,太多了的话,你要先检查一下设计了。
0 请登录后投票
   发表时间:2012-10-10  
woshiykk1 写道
devroller2 写道
cpszgy 写道
devroller2 写道
cpszgy 写道
devroller2 写道
cpszgy 写道
模式最重要的一点就是不要为了模式而模式,
我觉得原来的代码的可读性和扩展的问题都不是特别大。
目前的重构确实没有多大的必要。如果到时候真的一下子超过5种情况了再重构也不迟。当让你用了enum我第一想到的是用switch去替换if,结果用了for。。。那还不如原来的。要是真重构,最好还是根据value值来自动生成不同对象。比较合理。

为了模式而模式有何不好?没有人凭空想象就能学到东西,这也许是一些人实践模式的学习方法。总之,楼主有想法,敢做,其中的体会只有做了的人才知道。而且比原来的代码要强一些。


不过话说回来,模式不过是实现OO目标的具体方法、途径而已,请抛开模式!设计时心中多想想你的代码如何做到符合OO的目标就可以了,如果达到OO的目标,你的代码自然接近于那些模式。






简单的东西能解决,就用简单的。没必要一个3个if判断就能解决的问题非要用个设计模式。而且用了模式后会会增加类层次和理解的复杂度。再说这里还没到非要用到需要重构的时候。目前这么使用if判断我觉得是丝毫没有问题。


所谓上梁不正下梁歪,不好的东西会传染的,好的东西也会传染。这样的设计如果一个刚接手的人被分配任务在此段代码上处理,多数情况是这样:晕啊,我不熟悉业务,如果我要重构有担心出问题而且工作量大,所以最好的方法再加一个if。

结果if越来越多,我们项目就是这样。

我只是就这段代码而言,那如果现实就是这么3种情况呢,以后又不会扩展了呢。那目前所做的工作的实用性有多大呢。所以说未来的情况未来再说,在没必要做修改的情况下做出的修改带来的效果又不是很明显,我觉得实在不必。那后面接手的人不愿意修改难道会怪原来的人写的考虑不周全么。如果当时的情况就只有2到3个if判断,我非弄个3 ,4个类出来,再来个继承什么的。代码是不是写的过于复杂了呢。

不要幻想后面的人能够下决心来重构,他自己不愿意(我来挣钱,干嘛做吃力不讨好的事),老板不同意(我花钱是让你做开发,不是来美化代码)。

再说了,代码量一大,错综复杂的调用关系,重构不是一个简单的任务!

所以说过度设计比不设计好很多。

至于判断以后会不会扩展,设计人员的判断了。我觉得本例子中以后会有从不同页面进来的情况出现。



嘿,设计本身就是一个复杂的关系(设计模式怎么都得用2个以上的类把?),然后你每个不必要的地方都去过度设计,那不用代码量大,自己就把代码弄的错综复杂了。而且你怎么知道你的设计能正好适合以后的扩展?每种设计适合的扩张方面是不同的,有的地方能灵活有的灵活不起来。万一将来需要的改动正好和你的设计背离,那改起来更是伤经动骨,说不定就如你所说的,后来的人嫌麻烦也不跟你重构,到时候就会留下一个无比别扭的代码,恶心的要死。


类似这样的场景是过度设计吗?我觉得不是。
设计好不好唯一的检验标准是可扩展性、可维护性、可理解性是否好。这个“好”每个人体验都不一样。

也许你觉得有个地方让我加个if代码块就好了。

相比楼主没有重构的代码,所谓的过度设计至少是经过思考的产物。那些做了过度设计的人至少渴望用OO的思想设计系统,人都是不断摸索才进步的。不会有因为过度设计而失败的系统,相反失败的系统多是没有设计的。
0 请登录后投票
   发表时间:2012-10-10   最后修改:2012-10-10
xiaoyu64814361 写道
albeter 写道
夜神月 写道
公司给你放假,还不出去玩,闲来无事你咋不去把妹子去呢,活脱一个屌丝

屌丝的命,没办法。


  哥,你就那么看不起我啊! 理都不理我啊! switch 就能解决的问题难道是我理解错了,导致你不理我?

 

public class HandleSomething  {   
  
	private Manager manager;   
  
    private  Logger subLogger = LoggerFactory.getLogger(this.getClass());   
  

    protected void work( int entryType, long userId,Context context)  {   
  		switch(entryType){
				case 1: {
					context.put("type", vipFlow(userId,context)); 
					return;
				}
				case 2:{
					context.put("type", indexFlow(userId, context));   
				    return;   
				}
				case 3:{
					context.put("type", othersFlow(userId,context));   
				}
			}	
	
}

  private int vipFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/}   
  private int indexFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/}   
  private int othersFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/}   
}  

 

1.重构成这样就足够了

很好懂了

 

2.如果能把所有

context 赋值操作挪到一起

不论是一个enum中

还是放在某个查表法中

完成context的赋值

代码就好读了.

 

3.如果

有manager 需要传入那么就应该把对应manager 传给 enum 中的 method去完成

有logger 也传入就可以了.

 

4.有可能if变多

很多时候把一个操作切片的代价就是if变多.

但由于一个类内是可以自解释的

所以读懂很简单.

 

 

PS:楼上众位.

你们说的东西太抽象了

取舍之间差别太模糊

不如写写这个代码看看怎么个清爽法?

0 请登录后投票
   发表时间:2012-10-10  
抛出异常的爱 写道
xiaoyu64814361 写道
albeter 写道
夜神月 写道
公司给你放假,还不出去玩,闲来无事你咋不去把妹子去呢,活脱一个屌丝

屌丝的命,没办法。


  哥,你就那么看不起我啊! 理都不理我啊! switch 就能解决的问题难道是我理解错了,导致你不理我?

 

public class HandleSomething  {   
  
	private Manager manager;   
  
    private  Logger subLogger = LoggerFactory.getLogger(this.getClass());   
  

    protected void work( int entryType, long userId,Context context)  {   
  		switch(entryType){
				case 1: {
					context.put("type", vipFlow(userId,context)); 
					return;
				}
				case 2:{
					context.put("type", indexFlow(userId, context));   
				    return;   
				}
				case 3:{
					context.put("type", othersFlow(userId,context));   
				}
			}	
	
}

  private int vipFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/}   
  private int indexFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/}   
  private int othersFlow(long userId, Context context) {/*这里的逻辑用到manager和subLogger*/}   
}  

 

1.重构成这样就足够了

很好懂了

 

2.如果能把所有

context 赋值操作挪到一起

不论是一个enum中

还是放在某个查表法中

完成context的赋值

代码就好读了.

 

3.如果

有manager 需要传入那么就应该把对应manager 传给 enum 中的 method去完成

有logger 也传入就可以了.

 

4.有可能if变多

很多时候把一个操作切片的代价就是if变多.

但由于一个类内是可以自解释的

所以读懂很简单.

 

 

PS:楼上众位.

你们说的东西太抽象了

取舍之间差别太模糊

不如写写这个代码看看怎么个清爽法?

是的,"talk is cheap ,show me the code"

0 请登录后投票
   发表时间:2012-10-11  
说过度设计的人还是闭嘴吧,不要误导别人。多看看人家优秀的源代码,比如apache  roller中有自己的任务调度框架,设计者怎么知道有人会拿他们的源代码做二次开发,而且也需要定时任务;再比如,roller应用velocity作为渲染页面引擎,怎么知道有人在二次开发式也需要velocity生成个性化的邮件、短信,而且还不用直接调用velocity的api?

人家roller可能也没有以后要换模版引擎,但是为什么人家还是设计为可切换呢?而且对其api进行封装,难道这些都是过度设计了吗?

对第三方软件进行封装的好处是可以却换到其他软件,解除应用自身代码对具体第三方软件api的依赖,方便以后可以切换,更主要的是可以提高工作效率,因为同个项目中其他人也用到这个第三方软件,只要一个人去深入研究并提高封装后的api即可。

所以,我们开发新项目不可能不用到第三方软件,比如水晶报表、poi等等这些要封装一下。也就是你们所谓的过度设计吧。

我参加的十几个项目,难以维护,不是因为过度设计,而是没有设计,随意写代码。

0 请登录后投票
   发表时间:2012-10-11  
devroller2 写道
说过度设计的人还是闭嘴吧,不要误导别人。多看看人家优秀的源代码,比如apache  roller中有自己的任务调度框架,设计者怎么知道有人会拿他们的源代码做二次开发,而且也需要定时任务;再比如,roller应用velocity作为渲染页面引擎,怎么知道有人在二次开发式也需要velocity生成个性化的邮件、短信,而且还不用直接调用velocity的api?

人家roller可能也没有以后要换模版引擎,但是为什么人家还是设计为可切换呢?而且对其api进行封装,难道这些都是过度设计了吗?

对第三方软件进行封装的好处是可以却换到其他软件,解除应用自身代码对具体第三方软件api的依赖,方便以后可以切换,更主要的是可以提高工作效率,因为同个项目中其他人也用到这个第三方软件,只要一个人去深入研究并提高封装后的api即可。

所以,我们开发新项目不可能不用到第三方软件,比如水晶报表、poi等等这些要封装一下。也就是你们所谓的过度设计吧。

我参加的十几个项目,难以维护,不是因为过度设计,而是没有设计,随意写代码。



不要不承认有过度设计这回事,如果没有这回事,也就不会有这个词

另外你举的例子真心好笑。像roller这样的,本身就是个运行框架,设计时不考虑扩展性的话,能玩得转吗?又比如maven,本身就是基于插件运作,那当然设计时也考虑扩展性。这些都是优秀设计,不是过度设计

至于你去封装poi,明显就是过度封装。没错,如果换了第三方组件,你自行封装那层的API是不受影响,问题是组件都换了,你封装那层不改就能跑吗?只是在哪里改的问题,你觉得你封装的API,一定比第三方组件的原生API好用吗?

设计是好的,但是过度设计是有问题的,并且要承认这个事实的存在
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics