锁定老帖子 主题:关于用异常控制程序流程的看法
精华帖 (3) :: 良好帖 (0) :: 新手帖 (5) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-07-28
很难说哪种方式更好,个人经验IO处理或者数据库处理异常情况很多,很难全部照顾到,所以通过异常来控制流程很方便的。
|
|
返回顶楼 | |
发表时间:2011-07-28
个人经验
一个涉及了很多处理,多个service的业务 在某一处发现数据或者状态异常,如果用返回枚举的方式的话感觉真的麻烦死 每个调用判断状态,然后决定下个流程 一堆的枚举状态以及对应的状况需要维护 不如所有流程当作正常状态处理 一旦发现有问题就抛异常中断执行 上层调用负责捕获处理 代码反而干净简洁 |
|
返回顶楼 | |
发表时间:2011-07-29
同意 kdlan 的观点, 使用 err_code 这样的返回值在某些情况下, 的确是很麻烦, 使用异常会方便点, 其实异常和err_code应该是可以统一的, 例如在异常中定义err_code, 不知道有没有人在项目这么作。
|
|
返回顶楼 | |
发表时间:2011-07-29
runfriends 写道
不要说为了遵守第三范式什么的,数据量太大的时候,使用字符串做主键和增加太多约束,效率肯定降低。我参与过的所有项目,除了long型主键其它字段一律都不添加任何约束。
当然上面那个例子的返回值还可以改成枚举,个人更推荐使用枚举。不过这里只是个例子,本人太懒不想写太多代码。
1.看数据库和业务;一般还是推荐遵守范式,然后有效率问题的再优化;而且,数据库本身对数据的一致性保证,肯定比程序做的好,而且效率也优化的好
2.我觉得使用异常,比使用枚举好;异常拥有继承关系,是一个类,可以捎带异常信息,这是枚举没有的优势(当然枚举也可以这样使用,但是那样就违背了枚举的语义了);举个简单的例子: try{ // 异常A // 异常B }catch(Exception e){ return e.getMessage(); } 如果是枚举的话,可能就没有这样简单了
|
|
返回顶楼 | |
发表时间:2011-07-29
最后修改:2011-07-29
huainansto 写道 同意 kdlan 的观点, 使用 err_code 这样的返回值在某些情况下, 的确是很麻烦, 使用异常会方便点, 其实异常和err_code应该是可以统一的, 例如在异常中定义err_code, 不知道有没有人在项目这么作。
在异常中定义err_code来做区分感觉很实在啊,比如用一个模板来定义业务的处理流程,各自业务对模板中的方法实现不一定都会有结果码返回的,但是可以抛出异常,还可以将异常适当分类,比如参数异常、业务异常、系统异常,然后不同的异常中带上err_code,在模板中针对不同的异常类型做统一处理就可以了。 |
|
返回顶楼 | |
发表时间:2011-07-29
sslaowan 写道 引用 定义了太多的业务异常,然后依不同的业务情况去抛出它们,然后在方法的调用处捕获它们。个人一直觉的这是一种蛋疼的做法 。
引用 至少直到目前为止我还没在开发过程中发现非用异常做流程控制不可的理由。
只能说lz很初级,做过的系统都太小太简单,抑或是不知道异常究竟应该怎么用 你把你的观点提出来,别总是说别人初级。。你这种回答有意思么。 是否捕获异常,robbin不建议拿异常来控制业务流程,我也曾经这么试过,就性能方面,已经有人钻研过并澄清了try catch性能损耗过高的问题(实际上,其消耗是可以忽略的),但我个人用着比较别扭,因为变成习惯上讲,总觉得其有点歪门邪道的感觉。针对lz的代码,枚举稍好,但有更好的选择,比如做一些重构甚至是模式来转移return语句。由于时间原因,逢合适的时候我会试验一下看看并发帖分享。 |
|
返回顶楼 | |
发表时间:2011-07-29
异常处理还是看的出水平的。。
|
|
返回顶楼 | |
发表时间:2011-07-29
flounders 写道 sslaowan 写道 引用 定义了太多的业务异常,然后依不同的业务情况去抛出它们,然后在方法的调用处捕获它们。个人一直觉的这是一种蛋疼的做法 。
引用 至少直到目前为止我还没在开发过程中发现非用异常做流程控制不可的理由。
只能说lz很初级,做过的系统都太小太简单,抑或是不知道异常究竟应该怎么用 你把你的观点提出来,别总是说别人初级。。你这种回答有意思么。 是否捕获异常,robbin不建议拿异常来控制业务流程,我也曾经这么试过,就性能方面,已经有人钻研过并澄清了try catch性能损耗过高的问题(实际上,其消耗是可以忽略的),但我个人用着比较别扭,因为变成习惯上讲,总觉得其有点歪门邪道的感觉。针对lz的代码,枚举稍好,但有更好的选择,比如做一些重构甚至是模式来转移return语句。由于时间原因,逢合适的时候我会试验一下看看并发帖分享。 其实errorcode才是歪门邪道, 你说robbin不建议拿异常来控制业务流程,我记得我07年看过一篇关于errorcode和异常的辩论, robbin还是支持使用异常来处理错误的业务流程的 errorcode和可捕获异常一样,并且比异常携带的信息更少 |
|
返回顶楼 | |
发表时间:2011-07-31
最后修改:2011-07-31
好吧,看了各位的发言,我突然觉的自己蛋疼了,我的公司也蛋疼了。
不过可别说我经历的项目初级。 从日pv超百万的论坛和价值几亿的银行项目我都经历过。现在我经历的最大项目,整个工程都将近2g了。 从几个人的小项目到几百人的项目我都有经历,不过都没有用异常控制业务子流程的,甚至我现在的公司在代码规范里面都严格禁止了使用异常做业务子流程控制。 之前我列出两种实现新增记录的方式,都是指分别在有惟一键和没有惟一键的情况下说的,我并没有说一定不要用哪种方式,一定要用哪种方式。只是要根据实际情况选择。如果数据表里面就是没有建惟一索引你怎么办呢?有时候你的选择余地很小,并不是自己想怎样就能怎样,也并不是自己认为哪种方式好就能用哪种方式,甚至也不是业内公认的哪种方式好就能用哪种方式。难道要求采用的那种方式你认为不好,你还不干了吗?当然只是举例代码,没有考虑更多可能。另一方面确实很多教材都不建议自己维护数据一致性,之所以这么要求是因为这么做对程序员水平要求很高;但是并不是完全禁止这么做。自己用程序实现维护数据一致性,极大程度降低了数据库压力,这是自实现维护数据一致性的优势。 曾看过有老外写的书,建议设计数据表的时候采用惟一键做主键;书里的意思就是像用户表这一类表就用不能重复的用户名做主键,但是数据量一旦超50000,字符串查询效率就会明显降低了,而使用主键查询是最频繁的。考虑到分表的情况,动辙十几万到上亿的记录,你要分多少表?更何况谁见过哪家博客的url里面出现过用户名。我想iteye博客的url那一串数字一定博主的用户名主键。 有同学说异常能包含更丰富的信息,这倒是不假,抛出异常能更有效更快速的定位问题和对非正常情况做出简单明了的说明。不过我始终认为异常就是用来指示程序运行的非正常情况的,而不是用来参与程序运行的正常流程的。 比如说登录用户不存在,密码错误,新注册用户名已被注册等是程序运行时的正常业务情况,不应该用异常处理。网络连接断开,数据库连接断了,违反数据约束了,本来应该存在的文件却没找到,本来应该存在的引用却是null,传递了错误的参数类型或错误的参数数量,这是非正常情况应该用异常。不知诸位注意过没有,在jdk里面状态码和异常是都有定义的,难道大家平时只注意到异常,没意识到jdk里面还定义了状态码和标识码? 至于究竟是用数据库自身的机制维护数据一致性还是自己实现,我明晚另开新帖再说吧,毕竟这个问题偏离了这个帖的主题。顺便在新帖介绍下我看过的一篇介绍ebay架构的文章。人家用不用数据库约束维护数据一致性,和dba有什么关系?人家的dba肯定很牛,只是架构设计是那样的。谷歌的搜索引擎还是自己实现的数据存储算法和文件系统,它内部的一些管理功能只用的mysql,难道你要说谷歌用不起商业数据库吗?我现在的一个同事,他以前的一家公司嫌数据库太慢,完全用c++实现的操作文件系统和磁盘阵列,用来存储和读取数据;用算法立即定位到要读写指定硬盘、指定磁道、指定扇区,连解析sql的时间都省了。难道你要说那家公司连数据库都不会用?当然这是针对特定领域的优化实现,我同事的上家公司不在意数据一致性和安全性,所以可以那么做。搜索引擎更多考虑搜索有效性,即使某些页面的数据没有了还可以重新用蜘蛛机器人爬到,还可以通过增加备份提高数据安全性。数据库更多考虑通用性和低成本可维护性。 至于究竟是采用业务码和异常来处理业务子流程。个人并不喜欢使用异常来处理子流程。以前我也用异常处理过子流程,后来觉的麻烦,每个子流程都要创建一个新的类,而业务一旦确定了,能发生的情况是极有限的,用业务编码或枚举能很容易的穷举出来。况且你难道连自己要用程序处理的业务有多少子流程都不清楚?即使抛开效率问题不谈,这难道不是最简单的方式?只是用于业务子流程之间的跳转,只是不同状态之间的转换,你还需要跳转的时候传递多少信息? 处理有多种状态的业务流程的时候,简单的情况可以使用业务状态码、枚举;复杂一点的可以使用状态模式,再复杂的可以使用工作流引擎,再复杂的可以使用有限状态机。不论是业务的可扩展性、可维护性和降低耦合、提高内聚,都比使用异常要好的多。 至于errorcode是用在出现了非正常情况的,这种时候用异常当然更方便些,也更容易标识出了哪类错误。这个时候使用错误码和枚举来标识非正常情况,自然有些捉襟见肘。我个人也喜欢使用异常处理非正常情况。但是在某些极端情况,比如系统资源极端紧张的环境下使用错误码显然是更好的选择。究竟使用什么,得视具体情况而定,并不能一概而论。不知回帖的各位有多少看过《代码大全》这本书。里面讲过业务状态码、错误码和异常究竟该在什么情况下使用。尽管书已经有些年头了,但是个人认为里面的观点并没有随着时间而老化。 最后再说一点,如果你实现的业务里面有众多业务子流程还有可能因为各种原因抛出不同的异常;如果要用异常处理业务子流程,那么就必然会把正常的业务子流程和各种非正常情况都用异常处理了。在这种时候你还能分的清哪些是为处理非正常情况自定义的异常,哪些是为处理业务子流程定义的异常?使用异常处理业务子流程就一定能保证稳定性和可维护性吗?一堆try catch你不觉的乱吗?从多个异常里面理清哪些是处理业务的异常,哪些是处理非正常情况的异常才会让人生不如死。使用业务状态码或枚举难道可维护性和稳定性就差吗?如果你对枚举很熟你会发现它是个很好用的东西,现在我就觉的它就是为处理各种不同状态而生的,你甚至可以借助枚举针对特定业务应用状态模式,而且我已经借助枚举实现了一个处理特定业务的流水线模式。如果你去阅读下状态机、工作流引擎的源码,想信你一定不会看到有用异常处理子流程和各种状态的情况。它们得为通用性考虑,即然通用情况下能不用异常处理,而且能工作的很好,很方便开发。相信在特定情况下也能一样工作的很好,很方便开发。也不会让人觉的不用异常会让人生不如死。 让各种技术和语法特性去处理它们该处理的,拿个扳手拧螺丝不觉的工具不合适吗?难道你没有更合适的工具? |
|
返回顶楼 | |
发表时间:2011-07-31
ppgunjack 写道 add的时候尽量不要引入一次额外读,这不是update,并且这种额外读如果没有事务性其实也靠不住,有了事务性成本又会提高
没有参照性索引的需求和数据条目唯一性需求是可以不要索引 自己实现外部唯一索引不是不可能,但面临的另一个问题就是要解决索引和数据同步和实现分布式防止主机crash,这实际是为了扩缩能力花更多成本做同样的事情,这和中小公司不用索引根本是两回事 应用系统的表多数表都是检索用的,没有索引基本就没可用性 try{ userService.add(user); }catch(UserExistException e){ //在此处同名添加用户已存在的处理逻辑 } 这个实现实际很合理,因为你会发现,user一定会携带某个需要一致性约束的字段,并且这个字段也肯定会因为其他操作需要而建立了一致性要求索引,比如delete 这个回贴我看了三遍。也联想到一些问题。 大概是我没表达清楚,我并没有说完全不用索引,只是说创建索引时要慎重。更多情况下还是基于主键的查询。如果是互联网应用,完全可以使用key-value服务器,索引服务器分担数据库压力,这样就把对数据库索引的需求降到最低,极大降低数据库压力。 如果是大数据量的oa、crm、erp等软件也可根据实际情况及时备份旧数据,在保证读写效率的情况下,针对最多的查询建立索引。 我并没有说一定完全放弃索引不用。 最后个人认为用不用索引跟公司大小并没有关系,这很大程度上应该是由业务需求和架构设计决定的。不知ppgunjack是做什么领域的? |
|
返回顶楼 | |