`
fjlyxx
  • 浏览: 23500 次
  • 性别: 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{
.....
}



从段代码中反应了一个很严重的问题。可以从架构和程序实现上进行分析。
分享到:
评论
80 楼 fjlyxx 2008-12-19  
我觉得上面的例子已经说的很明白了,认真看下就明白了。 退一步说吧,上面代码中 每个子代码块都是对 test()负责的 ,都是和它进行约定 返回值 入参  和 异常等。  如果你是连续调用的 就不一样了。

如果你做的是SOA服务,你希望你的调用的服务还会调用 你本来可以调用的服务吗?我想你不会把这个委托给别人的。
79 楼 downpour 2008-12-19  
恕我直言,你上面的例子实在无法说明你的重构思路。事实上,我不认为这样的代码会在我的代码中出现。

fjlyxx 写道
难道你们的系统都没有进行过重构吗?  好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
//      |                      |                                                          | 
//   返回结果       组装SQL并执行数据库操作                         根据用户输入

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

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


我更想听听你怎么重构这样的代码。
78 楼 fjlyxx 2008-12-19  
downpour 写道
frogfool 写道
fjlyxx 写道
难道你们的系统都没有进行过重构吗?  好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
//      |                      |                                                          | 
//   返回结果       组装SQL并执行数据库操作                         根据用户输入

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

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



合格的写法是啥?让我们看看重构理论大师如何实践重构的?


我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?

我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。


public String test(){
		String temp = "a|b|c|d|e|f";
		return test1(temp);
	}

	public String test1(String s){
		String[] p = s.split("\\|");
		return this.test2(p);
	}

	public String test2(String[] s){
		List list = new ArrayList();
		for(int i = 0;i < s.length;i++){
			list.add(s[i]);
		}
		return this.test3(list);
	}

	public String test3(List list){
		return list.toString();
	}


再看这种写法

public String test(){
		String temp = "a|b|c|d|e|f";
		String[] test1rs = this.test1(temp);
		List test2rs = this.test2(test1rs);
		String test3rs = this.test3(test2rs);
		return test3rs;
	}

	public String[] test1(String s){
		String[] p = s.split("\\|");
		return p;
	}

	public List test2(String[] s){
		List list = new ArrayList();
		for(int i = 0;i < s.length;i++){
			list.add(s[i]);
		}
		return list;
	}

	public String test3(List list){
		return list.toString();
	}


一样的功能 初看起来没有什么区别,如果我业务变化了 明显2的实现 容易改动。我在前面的回复中已经说了不是要怎么去解决实际的结构问题,问题是怎么去看重构。
77 楼 downpour 2008-12-19  
frogfool 写道
fjlyxx 写道
难道你们的系统都没有进行过重构吗?  好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
//      |                      |                                                          | 
//   返回结果       组装SQL并执行数据库操作                         根据用户输入

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

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



合格的写法是啥?让我们看看重构理论大师如何实践重构的?


我也非常好奇啊,请问这段代码的问题在哪里?应该如何重构?

我至今为之没有看到楼主给我们写出代码来,所以我完全不知道你所谓的重构到底是什么。
76 楼 frogfool 2008-12-19  


frogfool 写道
fjlyxx 写道
难道你们的系统都没有进行过重构吗?  好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
//      |                      |                                                          | 
//   返回结果       组装SQL并执行数据库操作                         根据用户输入

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

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



合格的写法是啥?让我们看看重构理论大师如何实践重构的?



fjlyxx 写道
我同意 抛出异常的爱的说法,因为软件是业务的抽象,OO的的作用是可以少记忆 ,快速查找 ,我个人觉得这点可以说是00的初衷(对于程序员来说)。



恳请先用实践证明一下前面的重构理论不是赋予表面的?!
75 楼 yangyi 2008-12-19  
fjlyxx 写道
我同意 抛出异常的爱的说法,因为软件是业务的抽象,OO的的作用是可以少记忆 ,快速查找 ,我个人觉得这点可以说是00的初衷(对于程序员来说)。

不敢苟同
OO语言可以很好的表述设计模式中的良好的设计思想(即更好的满足解耦合,易扩展等设计思想),正如C语言可以很好的描述经典数据结构和算法一样。这才是OO存在的意义。
74 楼 fjlyxx 2008-12-19  
我同意 抛出异常的爱的说法,因为软件是业务的抽象,OO的的作用是可以少记忆 ,快速查找 ,我个人觉得这点可以说是00的初衷(对于程序员来说)。
73 楼 frogfool 2008-12-19  
抛出异常的爱 写道

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


原来你还能写出不含逻辑的代码?

抛出异常的爱 写道

OO的主要目的就是少记忆 ,快速查找


这样都能混到5颗钻石?!
72 楼 nathanlee 2008-12-19  
果然有帮助
71 楼 frogfool 2008-12-19  
fjlyxx 写道
难道你们的系统都没有进行过重构吗?  好的系统是重构出来的,好好的看看重构的原则,如果你没有这么做过,你怎么会发现模式的重要。如果你的接口都是随便定义的那么你怎么能体会这两种方式的区别呢?
public Object findUser(final Map parameters) {
return this.getSqlMapClientTemplate().queryForObject("findUser", parameters);
//      |                      |                                                          | 
//   返回结果       组装SQL并执行数据库操作                         根据用户输入

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

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



合格的写法是啥?让我们看看重构理论大师如何实践重构的?
70 楼 frogfool 2008-12-19  
抛出异常的爱 写道
fjlyxx 写道

已经给出一个背景了,就是 根据用户输入--》组装SQL-》执行数据库操作-》返回结果(解析结果)

用第二种方式....
你说的已经是你的答案了.

但在现实中:
是用户输入,用户输出, 用户需求1,用户需求2,用户需求3.有可能还有用户需求4.....
现在没有需求4但很可能会加上需求4或需求5....
那么用第一种方式是最合适的....

用哪种方式,与你用的中文描述有直接的关系....

PS现在的系统大多用方式 1 主要还是由于每层的代码总量太大.合起来人类很难理解.

PS:楼上...链式写法我看了就想到了jquery.....等我出去吐一下先/



还在吐?!我还等着学习呢?!
69 楼 frogfool 2008-12-19  
fjlyxx 写道
bleakoasis 写道
两种结构都有道理,得看具体业务是什么啊
就拿楼主的A,B,C,D来说吧,关键是得综合业务来看,用谁调用谁合理。
第一种情况,A是一个整体协调者,业务需求在这里体现,A关系的是步骤(业务逻辑)与结果,降低了B,C,D之间的耦合度,换句话说,B,C,D直接没有交互,互相不关系对方的工作职责
第二种情况,A是一个命令发出着,将业务分散给B,C,D,A关心只是结果,将具体步骤(业务逻辑)分散到B,C,D中去
空洞的代码没有任何意义,需要结合业务才有最合理的结构,结构是死的,业务是活的


就是因为业务是活的所以结构不能是死的。


那你脱离业务举的两个死方式的对比意义何在?
68 楼 bleakoasis 2008-12-17  
fjlyxx 写道
bleakoasis 写道
两种结构都有道理,得看具体业务是什么啊
就拿楼主的A,B,C,D来说吧,关键是得综合业务来看,用谁调用谁合理。
第一种情况,A是一个整体协调者,业务需求在这里体现,A关系的是步骤(业务逻辑)与结果,降低了B,C,D之间的耦合度,换句话说,B,C,D直接没有交互,互相不关系对方的工作职责
第二种情况,A是一个命令发出着,将业务分散给B,C,D,A关心只是结果,将具体步骤(业务逻辑)分散到B,C,D中去
空洞的代码没有任何意义,需要结合业务才有最合理的结构,结构是死的,业务是活的


就是因为业务是活的所以结构不能是死的。

针对一个结构来说就是个死的,各种死结构符合不同的活业务,就拿你举的例子来说,难道两个结构是活的么??
我的意思是说,在举例子的时候应该结合着业务,不然哪个都是合理的。
67 楼 fantasybei 2008-12-17  
public void save(){
    saveInfo1();
    saveInfo2();
    saveInfo3();
}

public void saveInfo1(){
    //...
    organizeData1();
    saveData1();
}

public void organizeData1(){
    //....
    verfData1();
}
public void verfData1(){
    //
}
......

觉得好像是第二种好,但是...
这个。。。如果一次保存要保存3种不同信息,分别用saveInfo1(),saveInfo2(),saveInfo3()。
单独就一个saveInfo1()来说,是lz所说的第一种吧?如果用第二种的话,在save方法里就是类似
public void save{
    organizeData1();
    verfData1();
    saveData1();
    organizeData2();
    verfData2();
    saveData2();
    organizeData3();
    verfData3();
    saveData3();
}

要是saveInfo这些更复杂的话,那save不是越来越大了嘛,他的职责是不是太多了?
66 楼 basictk 2008-12-17  
个人感觉,这两种解决方案对应的不是同一类问题。

第一种方法,明显有利于层级调用、纵向分层,类似SSH的各层关系,各层本身对于自己需要完成的事情非常了解,各层本身也比较独立;
第二种方法,是各横向模块间的协同合作完成一个功能的例子,其中隐含着顺序逻辑,调用者需要十分了解各委派对象间实现的依赖关系,适合于在小范围代码内运用。
65 楼 yangyi 2008-12-17  
第一种相当于一种层次的模型,向稳定的方向依赖,看看操作系统和网络基础的模型就知道
第二种是一种策略的模型,这种模型容易扩展,架构开放,但是软件质量没法得到保障

对于层次模型,如果底层核心不抛出异常,难道要每层的代码都处理一次异常吗?
64 楼 阳光晒晒 2008-12-17  
fjlyxx 写道
bleakoasis 写道
两种结构都有道理,得看具体业务是什么啊
就拿楼主的A,B,C,D来说吧,关键是得综合业务来看,用谁调用谁合理。
第一种情况,A是一个整体协调者,业务需求在这里体现,A关系的是步骤(业务逻辑)与结果,降低了B,C,D之间的耦合度,换句话说,B,C,D直接没有交互,互相不关系对方的工作职责
第二种情况,A是一个命令发出着,将业务分散给B,C,D,A关心只是结果,将具体步骤(业务逻辑)分散到B,C,D中去
空洞的代码没有任何意义,需要结合业务才有最合理的结构,结构是死的,业务是活的


就是因为业务是活的所以结构不能是死的。

第一种也是没办法吧
是由于页面代码与数据库代码
与业务关系小所以分成三层.....
主要还是精化业务逻辑.

如果java的业务逻辑是可以后绑定的话....
就不用分成三层了.
63 楼 fjlyxx 2008-12-17  
bleakoasis 写道
两种结构都有道理,得看具体业务是什么啊
就拿楼主的A,B,C,D来说吧,关键是得综合业务来看,用谁调用谁合理。
第一种情况,A是一个整体协调者,业务需求在这里体现,A关系的是步骤(业务逻辑)与结果,降低了B,C,D之间的耦合度,换句话说,B,C,D直接没有交互,互相不关系对方的工作职责
第二种情况,A是一个命令发出着,将业务分散给B,C,D,A关心只是结果,将具体步骤(业务逻辑)分散到B,C,D中去
空洞的代码没有任何意义,需要结合业务才有最合理的结构,结构是死的,业务是活的


就是因为业务是活的所以结构不能是死的。
62 楼 hyxw5890 2008-12-16  
具体问题具体分析吧,没有具体的实现环境就评价是没用的,最近在读《重构》这本书,所以我还是倾向于第二种
61 楼 bleakoasis 2008-12-16  
两种结构都有道理,得看具体业务是什么啊
就拿楼主的A,B,C,D来说吧,关键是得综合业务来看,用谁调用谁合理。
第一种情况,A是一个整体协调者,业务需求在这里体现,A关系的是步骤(业务逻辑)与结果,降低了B,C,D之间的耦合度,换句话说,B,C,D直接没有交互,互相不关系对方的工作职责
第二种情况,A是一个命令发出着,将业务分散给B,C,D,A关心只是结果,将具体步骤(业务逻辑)分散到B,C,D中去
空洞的代码没有任何意义,需要结合业务才有最合理的结构,结构是死的,业务是活的

相关推荐

    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是西门子的一款...

    欧姆龙ST编程中文手册

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

    Unix编程常见问题解答.rar_UNIX

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

    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编程中,问题...

    青少年编程能力等级 第1部分:图形化编程.pdf

    根据常见的标准命名习惯,这个编号可能代表了该标准属于中国电子技术标准化研究院(CERACU)和相关的行业协会,如航空工业飞机强度和环境适应性标准化技术委员会(AFCEC),航天工业协会(SIA),以及中国青少年编程...

Global site tag (gtag.js) - Google Analytics