反SSH架构,我开发J2EE项目为什么只需要一层就足够了
有些话想说很久了,一直忙于工作和学习,很少写博客,今天下午天气晴朗,楼下很多小孩子在打篮球,自家的也睡午觉去了,一个人在书房里很惬意,暂时从繁重的工作中抽出心情来放松一下,把自己心中想说的话整理成文字表达出来,可能很多人听得不中意,要批评一下我,我会很虚心接受的。
我做J2ee开发也快9年了,加上1年的DELPHI,我的程序员生涯也有十年了,我做了不少J2EE的项目,从物流ERP,进销存ERP或电子商务之类都做,最长的项目做了5年,最短的做了3个月。我在2005年spring兴起的时候就一直关注它,现在2011年SSH已经大行其道,很多J2EE同行都认为现在这么流行SSH而不用是不可想像的。持这种看法的同行越来越多,我也跟很多同行刨根问底地讨论这个问题,我在此想表达一些我的观点和实践。请大家给点热烈的反对掌声,谢谢大家。
1.spring的xml配置太多,发生错误难以调试,程序员都成了配置工人了。
2.在tomcat中启动spring要花20秒以上,加上Hibnerate,启动时间在30秒以上,可怜java不是php或asp.net,人家改了后台代码是不用重启的,而我经常因为增加或删除了一个java的方法而需要重启,一天至少要重启tomcat10次,最多会超过30次。次数多了就烦人。
3.spring在单元测试时要加载和hibernate的所有配置,每次加载都要30秒,曾经统计过一天需要跑100次单元测试,浪费了大量的时间在等待启动,为此我很少写单元测试。
4.Spring的AOP配置我到现在还没学会,一看那几十行的xml配置,我就怕了,不就是记录系统日志和方法调用嘛,用得着AOP吗?而且我查找AOP所拦截Serivce的方向日志,数量大得惊人,如大海捞针,有意义吗?有价值吗?
5.spring配置Quartz挺麻烦的,我花了一天时间去配置,花了一天时间去找错,问题虽然解决了,但是现在还偶而看到有人问Quartz配置出错怎么办的问题。其实,我就写了个EasySchedule.java实现了quartz的定时执行功能,也只是花了5个小时就完成了,很实用,经常用到,我上传了,大家有兴趣可以看一下。
6.Hibernate启动加载配置大约要10到30秒,我曾经做个大中型项目用到200个表,100多个视图,后来改用hibernate之后加载时间长达30秒以上,偏偏开发经理很注重单元测试,每次跑都要等30秒,痛苦得不得了,跟经理上诉无效,也找不到延迟加载的方法,单独自定义加载POJO的做法太机械了,为此我不想再浪费生命选择离开公司,听说现在这项目一直招不到合适的程序员来维护,旧人全走光了,新人也干不长,这Hibernate不是害人吗?
7.Hibernate的一对多多对一关联配置和hql听起来不错,用起来还是很有成本的,也很死板,耗内存,N+1等性能问题还是要手工解决,对于新人来说要掌握的太多,能用好的不多。而且做报表时hql极不好用,基本上都会用sql做报表或复杂查询。但有经验的程序员都知道sql不好维护,所以,hql并没有解决问题,而是增加问题。
8.hibernate打印sql的参数的?号问题,做得太差了,我现在是用p6spy或jdbcdslog解决sql的日志问题。但是那很长的select column1 as columns_1...的问题,就无法解决了,看得让人不爽。
9.hibernate的没有提供ORM查询类,就因为这个,所以才有dao类存在的理由,我所说的查询类,大家可能不太理解,举例来说,我需要一个查询职员列表,条件是05年入职的有效男性职员, 那我期望会有以下语句实现查询:
StaffSelect staffSelect=new StaffSelect(conn);
staffSelect.setValid(true).setJoinDate(2005,2006).setSex('男');
StaffResultSet rs=staffSelect.toStaffResultSet();
这个ResultSet有许多实用的方法为你节省了写代码的时间,例如
输出的有:toList(),toXml(),toCsv(),toExcel()等,
处理的有:filter("sex=男 or age>50"), union(otherRs), sum(fields...), sort(fields...)等。
我想如果查询可以这么简单,就Action一层就足够了。当然,如果需要重用的话,放到Serivce层会好一些。
10.分Action,Service,Dao三层,并且Service层还有分接口和实现类的问题:
10.1.在查询上Action和Service层几乎都是做转发,带来的问题是参数传递不灵活,service和dao层不能很方便地得到Action层的参数,本来很简单的问题因为分层而复杂化了,而且为此还要在spring配置一堆bean,重构时还麻烦一个个改配置。如果这个dao只是被一个serive调用,这个service只是被一个Action调用,这三个类在外部都没有重用的价值,配置的内容比具体代码还多,那还搞个Service接口干嘛,还分成三层干嘛。
10.2.在提交修改上,数据保存很少重用的,只要写一个通用的保存处理就足够了,如有业务逻辑,那就在Action层写,然后super.save(),把余下的部分交给父类处理就好了,这么简单的处理,有必要分三层吗?
10.3.在报表处理上或一些业务逻辑处理上,如有分层的需要,那应该从业务逻辑去分层,实现类的更高的重用性和封装性,而不是SSH这样固定(也叫规范)的物理方式去分层。
11.用一个标准的SSH三层框架写后台,经比较,代码量是只有一层框架的4倍,主要是配置文件和配置类过多,中间有太多的转发方法。一个新人学习j2ee,花费大量的时间在配置上,而没有很好的提升业务理解能力和逻辑算法能力,一般来说,一年经验的j2ee程序员是刚熟悉SSH的配置,三年经验的非常熟悉配置,但是真的去让有经验的j2ee程序员去写核心的代码,还是有太多的问题。很多J2EE程序员的基本功不扎实,这是我面试别人时发现普遍的现象。
j2ee的复杂是人为造成的,这些复杂性为项目的成功埋下了隐患,j2ee的复杂是很多因素造成的,往往是被利益所驱动,而不完全是符合事实和程序员主观意愿的。很多大公司都宣传自己的技术框架多么的规范,标准,我觉得这些都是虚的,做为了一个合格的程序员,应该更多的从客户需求,市场价值去看待自己的工作,关注客户真正的想法,而不是为了自己的技术喜好,职业发展而选择复杂的技术去解决问题。程序员的思想应该是创造性的,应该用简单的方式解决复杂问题,我们的价值在于为客户解决问题,而不是为自己制造麻烦。
我很认同一个同事曾经说过的话,现在做开发其实并不复杂,如果你觉得很难,那很可能是方向错了。。。