`
fjlyxx
  • 浏览: 23061 次
  • 性别: Icon_minigender_1
  • 来自: 福建
文章分类
社区版块
存档分类
最新评论

编程中一个很常见的问题,有帮助的

阅读更多
说一个开发中经常犯的错误。在实际的开发中请注意你的代码结构。
直接 给出一段代码吧。各位发表下自己的看法和见解。(随便写的)
这是一个描述 用:A调用B B调用C C调用D
还是由A同一去调用B C D的问题。


给个具体的应用场景吧:

就拿简单的 根据  用户输入条件 --》拼装一句SQL==》 执行数据库查询 -》 返回结果。

上面的方法就对应以下的几个testx函数吧。
表达不行,如果不明白下面的伪代码请看 http://www.iteye.com/topic/290788?page=5 中我的回复,

第一个:

public void test() throws E2,E3,E4,E5,E6{
   test1();
}

public void test1() throws E2,E3,E4,E5,E6{
 test2();
}

public void test2() throws E3,E4,E5,E6{
test3()
}

public void test3() throws E4,E5,E6{
test4()
}

public void test4() throws E5,E6{
test5()
}
public void test5() throws E6{
.....
}

第二个:


public void test() throws E1{
   test1();
   test2();
   test3();
   test4();
   test5();
}

public void test1() throws E2{
.....
}

public void test2() throws E3{
.....
}

public void test3() throws E4{
......
}

public void test4() throws E5{
.....
}
public void test5() throws E6{
.....
}



从段代码中反应了一个很严重的问题。可以从架构和程序实现上进行分析。
分享到:
评论
60 楼 kevinwong 2008-12-16  
多数情况下选第一种 这也是比较符合项目实际的 关键是log记好 异常处理和实际情况紧密结合啊 这样泛地讨论很累 不挑战了
59 楼 samm 2008-12-15  
fjlyxx 写道
难道你们的系统都没有进行过重构吗?  好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
//      |                      |                                                          | 
//   返回结果       组装SQL并执行数据库操作                         根据用户输入

这完全是一个不合格程序员写的代码。

去看看自己作的系统中有多少这样的情况,不是我自大,我只是想提醒这么一种常见的错误,让后辈人少走点弯路。



这是一个工具式方法,我觉得很好啊,spring的uncheck exception的初衷就是为了避免不必要的exception check.  具体业务处理时去检查异常,service里面dou不需要

action (){

try{
service.do..;
}catch(..){
//todo
}

}

58 楼 ohp1975 2008-12-15  
初看第二种好
57 楼 fjlyxx 2008-12-14  
恩,希望每个程序员有时间的时候都能够去重构下自己的代码,我个人觉得这一点很重要,它可以快速的提高你的编程能力。如果把好的结构提高一个层次到架构上,那么将对设计有帮助。 个人肤浅的见解,不过千万不要小看重构。
56 楼 Laynepeng 2008-12-14  
puroc 写道
看了6页,有点累,总结如下:

1.多数人应该都听过重构这个词儿,了解他的概念和基本手段,真正做过的应该也不占少数。

2.针对这个贴的问题,我认为具体问题具体分析。如果test1和test2干的是两件事,那应该用第一种方法,如果test2是为test1工作的,那应该用第二中方法。


同意。。。
55 楼 puroc 2008-12-14  
看了6页,有点累,总结如下:

1.多数人应该都听过重构这个词儿,了解他的概念和基本手段,真正做过的应该也不占少数。

2.针对这个贴的问题,我认为具体问题具体分析。如果test1和test2干的是两件事,那应该用第一种方法,如果test2是为test1工作的,那应该用第二中方法。
54 楼 tianzhou0374 2008-12-13  
问题很难回答,
我05年设计一个架构之前也被这个问题为难过.
最后也没什么好的解决方案,采用了第一种.
其中参数和Exception是这样定义的.参数统一用一个Param类这个类继承于HashMap,用法类似于HttpRequest.getParameter,在方法注释中写明需要什么参数
Exception统一继承于一个根Exception,其它Exception用这个类的transException转换为当前Exception.
用了一段时间发现这个方案也不怎么好...呵呵.
具体问题具体分析吧.
53 楼 gordonAtJava 2008-12-13  
具体情况具体分析
良好的代码应该是尽量降低耦合
第一种调用,A->B->C->D->E->....
明显是代码有强烈的耦合嘛,每个调用都要保持状态等待子调用结束来继续,这样就需要保持一个很深的call stack
第二种调用,BCDE...之间没有耦合,每个function调用结束就return了,call stack就一个A的被一直保持着,这样会比较好吧

假设BCDEFGH...是同样的一个function的话,明显就是一个
recursive process 和 iterative process的区别
尾递归的优化结果就跟第二种类似嘛

除非是没办法,不然代码应该尽量往第二种靠
52 楼 erikchang 2008-12-13  
抛出异常的爱 写道
如果让我来选.
我会选第二种

由于没有逻辑可言的情况下
第二种的代码信息含量更接近5这个数....
更易让人记忆与查寻.....


如果第一种更合乎业务逻辑
那么就选第一种.
那样子,业务逻辑与代码逻辑总共只需要记忆一次
比另一种少记忆一次.

OO的主要目的就是少记忆 ,快速查找
OO的选择就是把自己当作一个有限大小 的一个cacahe要尽量提高命中率


第二种写法是正常的写法!!!
51 楼 damoqiongqiu 2008-12-13  
我觉得,这是一个"方法调用深度"的问题
有时候从整个项目来看
代码结构上出现第一种情况是难以避免的
比如,一般我们这么干的时候:Action-->Service-->DAO
那么就已经三层的调用深度了,然后在某个类的某个方面里面又可能再次地深度调用
那么方法调用的深度就非常深了
用过Spring的人都知道,一旦出现异常的时候,打印出来的异常堆栈是很长的
有时候会到几十个,那么它可能就出现了非常深的方法调用
不是吗?
所以我觉得,只要在设计和大框架上没有大的问题
不必刻意去避免深度调用
50 楼 fdqzq 2008-12-13  
第一种层次感强,各层依赖调用,不过方法多了深度太大,中间环节出现问题不好处理第二种统一调度,灵活性会比较大,相当与用一个大脑,调度了每个肢体。便于组合和复用。对于异常也能从全局的角度去分析处理。我比较会倾向第二种。
49 楼 crazy.j 2008-12-13  
这不好说,分什么情况了。没有具体的场景,这两种都有自己的优势。
如果就是简单的拼个SQL,执行个查询,组装个对象,等等等等等等等。。。。还是后一个清晰一些。而且方法也容易被其他地方重用。
48 楼 qxhzzz 2008-12-13  
fjlyxx 写道
qxhzzz 写道
个人感觉第一种就是在讲一种分层调用view->sevice->dao。这种业务下敢不敢写成第二种?
第二种感觉很有业务逻辑性,我一般同层调用中喜欢这样写,直观上看到了业务的逻辑。
不过还是要根据业务需求来做。
ps:很寒的异常抛出,喜欢BaseException的方式,不过要明确有那些异常抛出很头疼。最后说一句重构很重要。


呵呵 这是在同一个类里面的方法 你说是哪种呢?view->sevice->dao  他本来就是一个顺序执行过程,你可以这么理解 在你的view->sevice->dao之上还有一个 调用的方法TEST(), 这个方法在用了SPRING的应用中 就体现为你的SpRINGBEAN的配置。 你觉得呢?

同一个类中倾向于第二种,Test()是暴露给上层的接口,test()1,test()2就像是实现该业务功能错做,逻辑上应该是平等的。逻辑上有上下级还是调用吧。
ps:写的太烂的东西重构很难,也太费时。我都不敢看我的代码。曾今见过800行的case语句。见过jsp里取log的和写jsp的成员函数。那时刚学java,影响大概到现在还在吧。
47 楼 fjlyxx 2008-12-13  
qxhzzz 写道
个人感觉第一种就是在讲一种分层调用view->sevice->dao。这种业务下敢不敢写成第二种?
第二种感觉很有业务逻辑性,我一般同层调用中喜欢这样写,直观上看到了业务的逻辑。
不过还是要根据业务需求来做。
ps:很寒的异常抛出,喜欢BaseException的方式,不过要明确有那些异常抛出很头疼。最后说一句重构很重要。


呵呵 这是在同一个类里面的方法 你说是哪种呢?view->sevice->dao  他本来就是一个顺序执行过程,你可以这么理解 在你的view->sevice->dao之上还有一个 调用的方法TEST(), 这个方法在用了SPRING的应用中 就体现为你的SpRINGBEAN的配置。 你觉得呢?
46 楼 qxhzzz 2008-12-13  
个人感觉第一种就是在讲一种分层调用view->sevice->dao。这种业务下敢不敢写成第二种?
第二种感觉很有业务逻辑性,我一般同层调用中喜欢这样写,直观上看到了业务的逻辑。
不过还是要根据业务需求来做。
ps:很寒的异常抛出,喜欢BaseException的方式,不过要明确有那些异常抛出很头疼。最后说一句重构很重要。
45 楼 fjlyxx 2008-12-12  
发现需要重构的代码工具

SourceMonitor是个源代码衡量工具,由http://www.campwoodsw.com/研发,免费下载。

这个工具只能从深度和覆盖面去说明,具体的还要和业务进行结合。

以上只是比较容易碰见的问题,希望对初学者有帮助。
44 楼 fjlyxx 2008-12-12  
2.重新组织数据 用对象代替数据值 用对象取代数字 这样比较容易明白什么意思
比如  String system_app_name="xxxxx" 和你直接写 xxxxxx 虽然逻辑上一样 但是 我怎么知道这个xxxxxx是什么意思呢 如果有
system_app_name这个说明下 就很容易理解了。

4.简化函数表达式  可以将条件判断语句,计算语句等改为函数  if(a==b) 你不能看出为什么a==b的时候要这么做,如果写成
private boolean  isXXXX(a,b) 那么你就能从isXXXX 去明白 a==b要表达的意思
简化函数表达式 是说不要写 a=a+b*(c+d*D)这样的东西  最好能明确表示出d*D是什么意思,类推。

5.合并重复的条件片段 比如下面的m();
  if(p==q){
     a=b;
     m();
}else{
      a=c;
     m();
}
6.对于返回如果有可能if语句只写一层  这个不是很有必要的。

7.工具(ECLIPSE有带)
1.Extract Method 抽取方法
2.Push down 下移 将父类的东东移到子类
3.Pull up 上移 将子类的东东移到父类
4.Extract SubClass提取子类
5.Extract SuperClass提取超类
6.提取接口
7.生成委托
43 楼 fjlyxx 2008-12-12  
这个帖子 其实就是要描述 隐藏委托关系 的坏处  不好意思表达不清楚

关于委托:
虽然第一种方法和第二重方法实现功能完全一样,但是你想想 第一种方法的每个方法间 比如A B C D  B是和A去约定的 C是和B去约定的 类推,第二种不一样 B C D都和A进行约定。在结构上 这已经是很大的差别了。
42 楼 fjlyxx 2008-12-12  
1.难点
1
修改接口(调用函数重命名)
需要修改相应的调用代码片段,建议保留旧接口,用旧接口去调用新方法. 类似适配器

2
增加异常处理throws语句
需要修改相应的调用代码片段,这个比较难解决.(我在帖子里加这么多异常也就是要说明这个问题)
3
数据库  一般不考虑,除非你有很成熟的设计了
4
颗粒度  和业务相关,帖子里的testx()可以抽象为业务颗粒度,横向和纵向的把我 就在这里,最难把握的地方,不过如果你有成熟的设计文档可以根据那个走。

5
入参和返回值定义  对于委托关系是很难的,我曾经说过如果你发现你的接口定义很简单 那么就只有两种可能,第一 你考虑的不全面,第二 用不用接口无所谓。 接口的定义是复杂的如果要和扩展以及兼容性联系在一起。
第一种实现接口定义很简单  因为当TESTX直接把自己的处理结果给TESTX+1 这里有又一个问题当TESTX逻辑改变了 那么是否会影响TESTX+1 。
写程序的时候 经常会这样做的,就比如SQL的执行,A生成了SQL 它不返回 直接把SQL传到B B拿到后就执行查询生成结果集RS C又直接将RS给D  这样是做已经司空见惯了。可是这里面出现了多少问题,最起码安全和健壮就没可更别说可读性和扩展,维护性。


3.方法重构 Extract Method
将能独立的代码片段独立出来,并且用函数名来解释这个代码片段是干什么的.颗粒度要尽可能的小.函数命名规则应该是说明这个函数是做什么而不是怎么做.检查变量,考虑入参和返回值.(变量有局部变量和公共变量的区别.如果是局部变量必须声明临时变量)
4.长表达式 将复杂表达式的结果存放在一个临时变量里面,并且用这个临时变量的名词来解释这个表达式的意义
5.提炼类  超类,子类,同级别的类,辅助类等  你都需要进行提炼。 假设A B两个类  A B如果有共同的方法 那么你需要提炼出一个父类,不同的方法是同级类,一些无状态通用的 可以进行辅助类的提炼。
6.隐藏委托关系  就是我要重点说明的问题 
41 楼 xiakq 2008-12-12  
第一种相当于一个A调B,B调C,C调D。。。。,只有等到调用最后一个结束之后才能回归,这是浪费资源的,也就是说前面的 test必须等到它所调用的test结束之后才能继续;而第二种做同样的事就必免了类似的浪费,它是依次调用,直到结束。
如果是我,我就选第二种。

相关推荐

    108种编程中常见的问题及解决办法

    "108种编程中常见的问题及解决办法" 是一个非常实用的资源集合,旨在帮助程序员们高效地处理各种编程难题。这个压缩包包含了108个具体问题的源代码示例,涵盖了多种编程语言和技术领域,对于初学者和经验丰富的...

    PB常见问题汇编;PowerBuilder编程俱乐部常见问题;PB常见函数;PowerBuilder常见问题集;PowerBuilder使用技巧集;PB常见问题;PB技巧100例;PB技巧及经验。是个集成包。

    2. **PowerBuilder编程俱乐部常见问题**:这可能是一个社区或论坛的问题汇总,包含了用户在实际编程过程中遇到的问题和解决方案。这些问题往往具有实践性,能够帮助开发者解决实际遇到的难题。 3. **PB常见函数**:...

    C++语言99个常见编程错误pdf

    它不仅对初学者有帮助,对经验丰富的C++程序员来说也是一个很好的参考资料。 在标签中,“C++ 常见编程错误”直接点明了本书的内容重点,即专注于C++编程中的错误。这个标签强调了读者学习这本书的目标是了解和预防...

    商业编程-源码-VC常见问题集.zip

    在商业编程领域,Visual C++(简称VC)是一款...综上所述,"商业编程-源码-VC常见问题集.zip"很可能包含了这些主题的解答,对于遇到问题的开发者来说,这是一个宝贵的资源库,能帮助他们解决实际工作中遇到的各种挑战。

    PowerBuilder编程常见问题分析与解决

    “PowerBuilder编程俱乐部常见问题.chm”是一个Windows帮助文档,很可能包含了社区成员在实践中遇到的典型问题及解决方案。通过阅读这个文档,你可以找到各种问题的具体解答,包括错误代码的含义、问题的原因分析...

    c语言编程常见问题解答

    c语言编程常见问题解答 对初学者帮助很大 强力推荐

    经典VC期刊(C与VC及常见编程问题)

    《经典VC期刊:深入理解C与VC及常见编程问题》 C语言和Visual C++(简称VC)是软件开发中的重要工具,它们各自拥有独特的特性和应用领域。本期刊聚焦于这两个领域的经典问题,旨在帮助程序员提升编程技能,解决实际...

    50道Java常见编程题(有精力的同学看看).rar

    这份"50道Java常见编程题(有精力的同学看看).rar"压缩包文件提供了学习者一个宝贵的资源,涵盖了Java的基础编程练习,旨在帮助他们巩固基础知识并提升编程技能。 在Java的世界里,面向对象编程(Object-Oriented ...

    win10S7200plc编程帮助文件补丁.zip

    标题中的“win10S7200plc编程帮助文件补丁.zip”指的是一个针对Windows 10操作系统的补丁,专门用于解决在该系统下S7-200 PLC(可编程逻辑控制器)编程软件的帮助文件无法正常打开的问题。S7-200 PLC是西门子的一款...

    Unix编程常见问题解答.rar_UNIX

    本资料"Unix编程常见问题解答"显然是针对这些领域的常见问题进行了解答,帮助开发者解决实际编程中的困难。 首先,我们可以从"Unix编程常见问题解答.htm"这个文件名推测,这是一个HTML格式的文档,通常包含了详细的...

    精彩编程与编程技巧-VB常见问题解答(1)...

    根据提供的文件信息,我们可以总结出以下关键知识点,这些知识点主要涉及Visual Basic(简称VB)中的编程技巧以及解决常见问题的方法。 #### 标题:精彩编程与编程技巧—VB常见问题解答(1) 此标题表明文章将聚焦于...

    欧姆龙ST编程中文手册

    本章将对欧姆龙ST语言编程中需要注意的一些问题进行讲解,包括安全注意事项、应用注意事项等。 3.1 安全注意事项 在编程过程中,需要遵守一定的安全规则,以避免人身伤害或财产损失。例如,在编程过程中,需要注意...

    C语言编程错误处理:常见问题与解决方案

    本文将介绍C语言中常见的编程错误,并提供相应的解决方案。C语言的编程错误多种多样,从内存管理到逻辑错误,再到并发和安全性问题。通过理解这些错误的成因和掌握相应的解决方案,程序员可以编写更健壮、更安全的C...

    编程珠玑 编程珠玑 编程珠玑 编程

    书中涵盖了一系列实用的编程问题和解决方案,这些“珠玑”般的编程智慧,无论对于初学者还是经验丰富的开发者,都有着极高的参考价值。 编程珠玑的核心概念之一是数据结构与算法的选择和设计。书中的例子多以实际...

    PLC常见编程问题点总结.ppt

    本文针对PLC编程中常见的问题进行了归纳和总结,旨在帮助工程师避免这些问题,提升编程质量和效率。 首先,PLC的组态设置是整个系统的基础。常见问题包括订货号与实际不一致,编程软件可能没有实际设备的订货号选择...

    java常见的面试编程题

    本压缩包文件包含了一系列常见的Java编程题目,旨在帮助学习者巩固基础,提高解决问题的能力。 1. **冒泡排序**:冒泡排序是最基础的排序算法之一,通过不断交换相邻的逆序元素来逐步完成排序。在Java中,可以使用...

    vector(容器)、 c &c++编程规范doc、495个c问题.pdf、c常见问题.pdf

    《495个C问题.pdf》可能包含了C语言中常见的陷阱和误区,这些问题可能涉及到类型转换、指针操作、内存管理、预处理器等方面。理解和避免这些问题有助于写出更健壮的代码。例如,C语言中的类型转换可能导致精度损失或...

    西门子常见编程错误.rar

    这个名为"西门子常见编程错误.rar"的压缩包文件包含了一个PDF文档——"S7-200常见编程错误.pdf",很显然,它是为了帮助用户识别和解决在使用西门子S7-200系列PLC编程时遇到的典型错误。下面我们将详细探讨这些编程...

    问题探究法在Java编程求解趣味题中的应用.pdf

    问题探究法是指在编程过程中,遇到一个大型或复杂的问题时,将其分解成多个小问题,然后逐一解决这些小问题,最终解决整个大问题。这种方法可以帮助开发者更好地解决问题,提高编程效率和质量。 在Java编程中,问题...

    分析C语言编程中常见错误及解决办法 (1).pdf

    本文将对C语言编程中常见的错误及解决办法进行分析,以帮助编程者提高编程技能,避免重复犯错。 首先,C语言编程中的错误通常可以分为编译错误和运行时错误两大类。编译错误是指代码在编译阶段就被识别出的错误,...

Global site tag (gtag.js) - Google Analytics