原文在此

校园级别的程序员的标志:

代码中最多的是嵌套if(null == xxx),还要告诉你,null必须写在前面,我靠。

防止把==写成=,c语言时代常犯的错误。由于null不能做左值,在写=的时候出现编译错误。一般来讲,在java中,由于boolean和其他类型不会作隐式转换,因此这么写没有意义。

写着写着突然想起来这么个代码:

Boolean b = true;

if(b=null)
{

}

顺利编译通过,也许把null写在==的左侧还是有意义的。

后台满是system.out.println("--------程序应该会运行到此处的。。。userId:")。

调试程序过程中,如果想在控制台中打印什么东西,最好用log工具,如已经在多少年前就俗到家了的log4j。好处是:打印日志的语句和控制是否打印日志、控制怎样打印日志的语句是解耦的,可以在程序中随便写打印log的语句,然后在正式上线后,通过某个选项,令其全部失效。

当年流行的组合是log4j+apache commons logging,在程序中引用commons logging的api,build path中放一个log4j的jar包然后再写个log4j的配置文件并且初始化一下,实际生效的就是log4j了。这样做的好处是,想换日志实现类的时候,不用修改程序代码。

今年的流行款是logback+slf4j,对应上面那两个东西。logback的实现据说效率高了多少倍,不过除了非常关键的模块外,这点开销基本可以忽略不计。
html页面总是对不起一两个div的线,老用firefox去框框显示那个div。

搞前端的都是神,我到现在也对不齐那堆div。另提一句,bootstrap是良心作,好人一生平安。
IO异常处理那个就是叠罗汉啊。

异常处理是个技术活,我当年的思路是,根本不知道有非受控异常这件事,出现受控异常未处理的编译错误时,点开eclipse的自动处理选项,然后按照心情选一个。

一点经验:

数据库异常、io异常就直接上抛,如果框架非得搞成checked的话(譬如ibatis2.x),发现了就给封一层RuntimeException,一直抛到顶层让这个事务挂了就好了。然后客户会明确的知道这个程序sb了,怒不可遏的给维护打电话,然后维护远程ssh,重启数据库了事。如果项目经理稍稍良心一点的话,针对这种错误可以做的包括:1、打异常log,2、给客户一个明确的提示“系统挂掉了,请联系系统维护人员电话是13xxxxxxxxx”而不是显示一堆异常堆栈然后再让客户翻电话本。想写段代码自动处理这些异常的想法不是不能实现,但对于业务定制类的系统来说,代价太大。

nullpointerexception、各种illegelxxxexception,其它各种开发人员懒得去学的异常,这些基本上都是程序的bug,开发测试阶段出现了就调整,打各种补丁,直至所有的测试流程都走通。实际运行阶段再出的话,类比上一条。

在业务基本走通,正常流程都没问题了,而项目组又恰好有足够的时间投入在异常架构上,可以做下面的事:分析业务,找出需要处理的业务异常,如根据身份证号查出了两个完全不同的人等,定义处理这些异常的逻辑,定义项目级别的异常基类api,之后就可以从底层一层层的加各种if判断,抛出异常,再向上找到该处理异常的地方,写catch代码。最重要的就是在抛异常的时候,把所有有意义的信息都记录下来,比如上面说的身份证号的异常,起码要记录身份证号是什么、找出的两个人的主键,另外还可以记录操作时间、操作人等信息。只要在异常抛出的时候做到这一点,随便你决定在哪一层catch,哪怕只做个log,都会让维护人员、后续开发人员感谢你的良心。

一般级别的程序员标志:
会struts+spring+hibernate|mybatis,面试神器。

曾经的观点:

怎样用这些东西:找个文档读一点,都能学会。

为什么要用这些东西:体现真正水平的问题。

现在的观点:

怎样用这些东西:做到随便给给技术,读读文档就能用上的,都是水平已经不错了的人。

为什么要用这些东西:网上答案一搜一大把,需要分辨是直接拿的结论,还是真被某些雷炸过然后很良心的告诉你,struts2真操蛋。

struts1、2、spring mvc这一层,用的并不多。由于没做过什么访问量特别高的项目,因此对struts2的效率并没有太多吐槽。现在的选择标准:1、是否提供了足够的语法糖让一般水平的人也能够快速开发 2、是否没有提供不恰当的语法糖,从而大幅度的增加维护难度。annotation、零配置这些东西,个人觉得最好用于元属性设置,而不要用于流程控制。曾经有个同事发现前台传进来的参数莫名其妙的会丢一个,后来发现在引用的某个jar包中有一个annotation方式定义的filter。尽管实际上的问题是架构组没有写完善的文档,没有做培训,但是经过那件事之后我也同意,这种东西放在一个统一的配置文件里面看着会更清楚一点,控制粒度也更细一点。

当年实训初学spring就觉得这东西很蛋疼,迄今为止一直没遇到复杂度高到有大批量属性需要注入的地方。aop的应用场景倒是遇到几个,不过出于对庞大的spring以及配置文件膨胀的恐惧,我宁愿改变整个的框架,定一个抽象层然后用各种各样的strategy模式。倒是觉得有完善annotation支持的轻量级aop应该是个不错的选择。

hibernate用的也不多,我好像对主流的s2sh有本能的抗拒……一直对sql的结构化有深深的执着,因为你真的不想没事总给别人调那一堆动辄五六行变量名很奇怪大小写都有的sql语句。所以在看到hibernate做某些复杂查询必须用hql的时候就放弃了这门技术了,sql本身就不想看,再发现这sql实际上是在java里面用String拼起来的……

ibatis/Mybatis一系用的比较多的原因是,职业生涯用到的首套一站式框架的作者就用的这玩意儿,属于马屁股性质的事情。这东西的好处就是把sql和java代码分离开了,程序看起来比较干净。但是让每个模块的程序员都去决定要写哪些sql,怎样写,同样是个很可怕的事情。所以当年我定义了一套针对每张表的标准sql列表,几项最基本的CRUD操作。select操作只支持id查询和各个属性的and相等查询。这个基本上已经可以满足80%的需求了,剩下20%,定好了配置文件分割策略后,找个sql好点的人慢慢写就是了。另外,这东西的一大槽点是只支持假分页,我们的处理方式一般是忽悠客户买个内存大点的机器就得了,不具备这种忽悠机制的同行们请慎重选择,ibatis想解决这个问题需要hack jar包,mybatis也需要自己写个插件支持,大概有个半天到一天的工作量。

再后来觉得配置文件有些繁琐,所以又在apache commons dbutils基础上封装了一套,不用写配置文件,定义好列名和属性名的映射关系后,自动生成CRUD操作并作db访问操作。在封装复杂的select操作时发现了nutz这个东西,觉得思路基本一致,就懒得再继续写了。

nutz提供的dao工具实现了用比较结构化的方法拼sql语句,试了试,用着还不错。事务管理机制据说有槽点,没细看。

决定我没有实际使用的槽点:1、不支持手动配置db和java的名称映射,而我给项目组定的映射规则又比较奇葩,给每个属性都写个annotation有点蛋疼。2、貌似是用反射方式直接读写java属性,而不是用java bean规范的get、set方法,而我的很多工具类都是做的虚拟属性,只有两个无比复杂的get/set方法,没有实际的属性。当发现annotation只能加在字段上时,欲哭无泪只好放弃了。

现在项目中用着的还是mybatis,用官方提供的mybatis generator生成配置文件,单表操作支持得很完善,多表操作自己写sql解决。

能分清楚group和having的区别。

关于db另一个要说的问题:复杂的东西尽量别放sql里面。orm层提供基本操作就够了,剩下的逻辑交给java层表达。做好封装,实在有效率问题,再专门进行优化。好吧,我承认我不知道这哥俩到底有什么区别。
数据库里的字段必须只能2个长度,不能32个长度,性能问题。表名要以T开头,蛋快碎了。

长度问题没看懂要说什么。前两天遇到一个问题,在oracle中如果用char类型的,而实际内容又不正好等于char长度的时候,select出来的数据是带空格的……各种trim都感觉不太好使之后,果断varchar2了。反正这点效率差异,早就被各种奇葩的业务逻辑给抵消了,还是那句话,有问题的时候再优化。

表名问题,我觉得加前缀还是为了跟视图进行区分。当表只有几张时,什么区分也不用做,当表有一百七十张时,什么区分都不管用。所以,战略上看需求决定就行了……

一点经验:通通加T跟没加是一个效果。现在项目中的做法:数据库中大部分的表都是对应了一个业务实体,这些类直接写名字就行,在这些表上建的视图统一加一个V_前缀,也就能起到区分效果了。一般来讲,一百七十张表中至少有一百五十五张以上都是这种表。其他的表,则大多对应了某些特殊场景或算法,实际开发中一般由专门的核心人员负责,可以按照权限控制、事务控制等实际用途,加个什么前缀,谁负责哪个模块就关注哪个前缀就好了。
会用jquery.ajax获取数据,不知道ajax的同步锁。

我也不知道。对于一切锁,我的意见都是,上个最大粒度的,保证数据一致性。出现的所有问题具体分析,逐个减小锁的粒度。

一会显示的表格有数据,一会又没数据啊,太生气了。

遇到此类抱怨时:1、告诉他,工业界没有玄幻故事,2、再提同样的问题的话,辞了他。让这种人觉得自己还有混在程序员界的错觉是对他的不负责。

详细记录当时的运行环境,一般都会找到原因的。

骚年级别的程序员标志:

懂div的float,clear的含义。

1、上一套bootstrap,解决80%的问题。2、剩下20%的问题,找个跟你关系不错的前端,没事多请人家吃吃饭,然后就解决了。
数据库超过n记录表横向纵向分表。

问题在于,n等于几。高估n无所谓,反正要出现的问题肯定会出现。低估n的话,造成的进度损失会让你有自杀的冲动,造成的数据损失会让项目经理有杀了你的冲动。

知道oracle的用with,这个sql写起来看起就舒服了。

这个也不会,粗略google了一下,确实有点用途。

看到aop能说一大堆废话,又是代理又是反射,就是没写过。

你的错误在于,不知道用途就研究实现原理。

DateUtil一定写过好多次,简直太复杂了,非常多的格式定义,那个static格式变量,必须要深刻理解才能知道。

1、有句评价说的好:把一个工具包的几乎所有方法都写到标记过时,这是得有多仇视这个社会。

2、自从有了JodaDate,妈妈再也不担心我的日期处理了。当一个同事又一次熬通宵写出一个DateUtil然后我拿出了JodaDate之后……

砥柱级别的程序员标志:

会架构程序,能用extjs或者easyui写个框架frame,还能写个递归menu。

所有的知识点都很基础,但是能把这一切都完整写出来,完成debug之后让项目组用上,一段时间之后还能维护或者添加点新功能的,都是中流砥柱。说白了,这是个情商要求大于智商要求的活。业务系统定制开发,实际上都是这种类型的活。你并不需要有特别高深的技术,也不会突然面对多么巨大的困难,只会在一个个看似不起眼的bug中,把所有激情都消磨殆尽。

会用ps处理图片,还能写上几个字,XXXX系统beta版本。

会ps的都是神,不解释。

基本上util包的作者,用log或者拦截器记录日志。

并且,愿意跟一切动过你util包的人玩命。

能用fiter或者Interceptor处理权限,但是搞不懂如何处理button的权限。

在业务级别去掉button权限的需求就好了。

真正的解决方案没有实际执行过,只是一个想法:系统建模的时候,权限模型直接建到操作级,比方说每个Action处理函数对应一个操作,针对这个操作定义每个角色的权限。button在概念上同样映射到权限就可以了。至于怎么针对函数做权限控制,随便你用xml或者annotation定义一下就行。

明白了异常处理转换成RuntimeExcetion太好了,不会丢失而且好处理。

异常处理真是个技术活。当我说,我也不知道我的方案好在哪,只是觉得你们的方式不优雅时,我清楚的听到了对方心里的嗤笑声。往往我的结论都会在大概三个模块开发周期之内被确认。

page分页里代码和css样式和类class都在jsptag里,认为没法分啊,这个是典型。

前端用于提交参数,目测所说的代码是计算page、rowperpage这些属性的。随便找套js grid控件,看看他们的参数提交方式,前端不依赖任何jsp,分到那个份上我觉得就足够了。

小牛级别的程序员:

知道url资源树和menu的区别。

不明觉厉。这种概念性的东西其实挺多人都挺不重视的,曾经很反对这种不重视,但是重视了很多年还真没重视到什么收获。现在的观点就是,用到了再说。

能手写css,懂important能拿来做啥,这个好玩得很。

又是前端,上bootstrap吧

能够理解数据库必须用主外键,否则那帮家伙一定会乱写程序。

只要是实体类,必须有主键,并且一定要有物理主键,不能只依赖于逻辑主键。id这东西,找不到其他用途的话就简单的当个快速查询定位的工具就行。随着业务复杂度的增加,你会发现它的表现力越来越强。在大部分依赖于持久化的业务类系统中,可以简单的定义,有id就代表这东西存在,没id就代表不存在,顺着这条思路往下想,很多业务都会简化。

只用id做外键,不要用神马身份证号、订单编号之类的东西。然后你的程序随便怎么写都能写得下去。

会设计数据库模型,几百张表的小意思。

针对真实世界,只作抽象,不作修改,保持整个系统概念上的一致性。然后你会发现,设计的模型会恰好符合数据库设计的各种准则。这时候这个数据库结构就能用了。

如果你设计出一张自认为很有用的关系表,却起不出合适的名字来;或者数据库中有一个不是纯粹为了效率问题而设置的冗余字段,相信我,你终将遇到一个你的模型无法表现的业务需求。

注释用//只有一行,不用/**多行,因为程序即注释。

jdk标准注释都不用,那javadoc咋办?

好吧,程序即注释这东西,几个水平相当、思路相近的人,通过不定期的结对编程、互相重构代码,还是可以做到的。如果是大规模的开发,还是建议通过架构层面合理的分层解决。

知道struts模型驱动代替属性注入,方便太多事了。

又一个语法糖。有了实际需求再用,到底用不用不要争论起来没完,遵循这两点就行了。这个真心不是核心问题。

用过this做参数传递,哈好多人都没用见过。

哈真神奇!这话真有人对我说过。

技术上this就是个指向自身的引用。某些具体的场景确实用起来很有意思,高层面的意义还没太想清楚,只有一个模模糊糊的印象,大概就是做了一件把自身委托给其他对象的事,封装了某个参数传递的过程,也就是封装了自身和被委托类的关系。

se级别的程序员:

研究过struts,hibernate的源代码,ui里有颜色互补概念,看起来是要舒服点啊。

学源代码要跟写代码结合起来执行,学到了新的模式之后,多想想有什么应用场景,但是真的实际使用要慎重。譬如说看到struts2的层层wrapper模式后就用了一次,被喷了好长时间

觉得struts,hibernate,spring,要扔掉一个框架,一定是spring,这个废啊。

让我选的话,我扔hibernate。

写过mvc,知道前端拦截器,中心分发器,后置处理,bean映射。

要知道就算没有这些概念,代码层面也一定会实现mvc的全部功能。然后找到没有这些概念的代价,哪些东西就耦合了,哪些变更就应对不了了等等。最后你的水平就提高了。

会用模型驱动user.save(),代替dao。

少传一个参数,概念上优雅了一些。模型驱动太考验建模能力,一定要在一个范围内把所有问题想清楚再使用。建议把DDD那本书看个两三遍再说。

不过这东西看上去真的很吸引人。

能用metadata生成一堆乱七八杂的代码,这下爽多了。

metadata的解释是“描述数据的数据”,比方说数据库的表结构定义可能就算是一种metadata。在写代码过程中能正确的抽象出元数据之后,眼光会提高一个层次,至于是不是要搞生成代码的工具,因项目而异。

曾经用过一段时间的freemarker,写一些轻量级的代码生成工具还是挺好用的。

研究过Annotation,用Annotation写过注解,知道Annotation如何继承,太复杂搞不懂。

拿Annotation实现过一套Model工具,没有深入了解过ejb,可能有点entity bean的思路在里面把。

前面说过一部分annotation了。这东西的好处就是把元数据跟java代码放到一起了,于是好找也好改了,坏处也是放在一起所以耦合了。如果代码量大到一定程度之后,最好把所有主力都集合到一块儿商量一下,到底是xml好还是annotation好。

在代码量没大到一定程度,或者annotation配置的数据仅仅是annotation所在的类自己用的话,可以在开发效率上考虑一下这个问题。jdk提供了语言层面的annotation操作工具,使用简单,有一部分的编译期检查,写起来比xml要舒服。另外,个人认为annotation的语法不太适合定义层次太深的结构,在类前面写上四层annotation再用ide做个formatter,说实话挺愁人的。

Boss级别的程序员:

仰慕一下。。。。

以上经验建立在如下基础上:

我做的项目是大部分是技术要求特别简单,业务要求中等复杂,需求变更特别频繁,开发人员平均素质不足,工期不是很紧的类型,所以关注点集中在如何通过分层隔离业务复杂度,以及如何通过语法糖来降低开发复杂度。bug方面,比较关注的是影响数据一致性的bug,只要不影响数据一致性,哪怕系统直接挂了,都不是影响项目的生死因素。

在做技术方案的时候,比较倾向于:

1、通过各种设计模式封装复杂度,提供尽量简单,甚至无脑开发的接口

2、忽略一切效率问题,在业务打通之后再想优化的事

3、能在编译器做的事就不往运行期放,哪怕会影响开发的灵活性

项目组J2ee程序员的标志,你中招没 转载+评论的更多相关文章

  1. J2EE程序员应该要掌握的linux知识

    J2EE程序员应该要掌握的linux知识 大型J2EE应用都在建构在linux环境下的.开发环境下我们可以通过samba映射成本地的网络驱动器,直接在windows环境下进行编程调试.但是最后的发布还 ...

  2. Github上安卓榜排名第2的程序员教你如何学习【转载,侵删】

    来自:峰瑞资本(微信号:freesvc)文章作者:代码家(微信 ID:daimajia_share) 软件早已吞噬整个世界,程序员是关键角色.过去 40 年中,许多伟大的公司都由程序员缔造,比如比尔· ...

  3. 2017年PHP程序员未来路在何方?(转载)

    PHP 从诞生到现在已经有 20 多年历史,从 Web 时代兴起到移动互联网退潮,互联网领域各种编程语言和技术层出不穷, Node.js . GO . Python 不断地在挑战 PHP 的地位.这些 ...

  4. PHP程序员的技术成长规划(转载)

    按照了解的很多PHP/LNMP程序员的发展轨迹,结合个人经验体会,抽象出很多程序员对未来的迷漫,特别对技术学习的盲目和慌乱,简单梳理了这个每个阶段PHP程序员的技术要求,来帮助很多PHP程序做对照设定 ...

  5. JavaScript 初学者容易犯的几个错误,你中招没?

    JavaScript 是对初学者比较友好的一门编程语言,基本上花个半小时看下语法就能写出能运行的代码.JavaScript 是动态脚本语言,对数据类型没有太多的限制,写起来非常灵活.但正因为如此,初学 ...

  6. 在培训机构花了好几万学Java,当了程序员还常被鄙视,这是招谁惹谁了?

    在之前的文章中说过,我是非计算机专业,通过参加培训进入程序员这行的. 入了程序员这行后,挺长一段时间在亲戚朋友中,我还是挺有面子的:家族里的第一个程序员,工作不用风吹日晒,收入比其他行业高不少,尤其是 ...

  7. [No000023]为何没有更多人从事程序员的工作?程序员常有,优秀程序员不常有!

    成为优秀的程序员是极其困难的,并且这个过程不可能一蹴而就. 我们不可能期待去种一些树,然后一夜间收获有着2000年树龄的红杉树,无论其需求有多大. 人格特点 一个人首先得是自学者来学习编程.仅仅是超过 ...

  8. 身为java程序员你需要知道的网站(包含书籍,面试题,架构...)

    推荐几本书<高级java程序员值得拥有的10本书>,     首页 所有文章 资讯 Web 架构 基础技术 书籍 教程 我要投稿 更多频道 » - 导航条 - 首页 所有文章 资讯 Web ...

  9. [Mac A]为什么国外程序员爱用 Mac?

    from http://www.vpsee.com/2009/06/why-programmers-love-mac/ Mac 在国外很受欢迎,尤其是在 设计/web开发/IT 人员圈子里.普通用户喜 ...

随机推荐

  1. MIT牛人解说数学体系

    https://www.douban.com/group/topic/11115261/ 在过去的一年中,我一直在数学的海洋中游荡,research进展不多,对于数学世界的阅历算是有了一些长进. 为什 ...

  2. PBOC金融IC卡,卡片与终端交互的13个步骤,简介-第一组(转)

    两个PPT结合起来--一些基础介绍--每一步的详细细节还要去研读文档 EMV-全球标准PBOC-国内标准 ----------------------一:必选:应用选择应用选择的方法:目录选择法.AI ...

  3. C# 发送qq邮箱

    注意: QQ邮箱的简单邮件传输协议(SMTP)使用了SSL加密,必须启用SSL加密.指定端口. QQ邮箱POP3/SMTP服务默认是关闭的,需要开启服务(设置=>账户=>开启服务). QQ ...

  4. ROS学习笔记(二)——ubantu 14.04 安装

    0.采用双系统安装(U盘安装) 1.安装文件在ubantu官网下载: ubantu官网 :https://www.ubuntu.com/ ubuntu的server版和desktop版有什么区? (来 ...

  5. Eclipse中全局搜索和更替

    Eclipse全局搜索步骤  使用快捷键"ctrl+H"打开文件搜索对话框,选择"File Search"标签,在Containing text中输入你需要搜索 ...

  6. 对HTML5校验 自定义验证信息

    在HTML5中,表单可以定义一个属性required来触发默认的校验机制,比如: <input type="text" required /> 弹出的错误提示默认为英文 ...

  7. bizagi simulation 仿真学习

    Level 1 - Process Validation 1. maximum arrival count Define the number of token instances the proce ...

  8. linux系统文件说明

    linux系统文件说明 bin 系统命令目录 dev 设备目录 home 用户的家(每个系统用户在home下都有一个自己家) root超级用户在根目录下 lib 系统库目录.so动态库文件 media ...

  9. JAVA RMI 实例

    下面我将介绍一个完整的实例,让初学者能快速体验RMI的功用. 分为以下四个步骤 1. 创建远程接口及声明远程方法(HelloInterface.java)2. 实现远程接口及远程方法(继承Unicas ...

  10. 简化通过classname查找 方法

    function getClass(oParent,sclass){ var aEle=oParent.getElementsByTagName('*'); var result=[]; for(va ...