目 录
第一章、概述 4
1.1、目的 4
1.2、范围 4
1.3、文档约定 4
1.4、相关概念及词汇列表 4
1.5、相关角色 5
第二章、协作规范 6
2.1、参与协作开发 6
2.2、进行协作开发 8
2.3、相关规范 12
第三章、设计规范 13
3.1、JAVA存放位置 13
3.2、页面存放位置 14
3.3、配置文件存放位置 14
3.4、业务代码位置 15
3.5、数据库设计 15
3.6、Model规范 16
3.7、Design配置规范 16
3.8、JAVA类规范 17
3.9、JSP界面规范 18
3.10、properties资源文件规范 19
第四章、代码规范 20
4.1、命名规范 20
4.2、风格规范 25
文档授权 30
更多资料请查阅
对于代码,首要要求是它必须正确,能够按照程序员的真实思想去运行;第二个的要求是代码必须清晰易懂,使别的程序员能够容易理解代码所进行的实际工作。
通过建立开发规范,形成开发小组编码约定,提高程序的可靠性、可读性、可修改性、可维护性、可继承性和一致性,可以保证程序代码的质量,继承软件开发成果,充分利用资源,使开发人员之间的工作成果可以共享。
1、项目组成员;
2、蓝凌公司相关技术开发人员;
3、其他经公司认可的必要知情的人员。
本文档采用MS Word2003软件编写,采用统一风格排版,正文风格为:五号中文宋体、五号英文Arial字体、行距1.5行;
针对需要重点注意的段落,采用红色描色。
一般来说,各章内容相对独立,构成全文的有效组成部分。
【同步代码】
在进行开发的过程中将本地的代码和SVN服务器的代码进行同步,在eclipse中的操作叫Synchronize whit Repository。
【合并代码】
在同步的过程中,发现本地的代码和服务器上的代码都有所改变,这个时候会产生冲突,就需要合并代码。
【签入】
在进行开发的过程中将代码放入SVN服务器的操作叫签入(check-in),在eclipse中的操作叫提交。
【签出】
在进行开发的过程中将代码从SVN服务器下载下来的操作叫签入(check-out),在eclipse中的操作叫更新。
【开发人员】
根据开发规范,进行日常开发工作。
【SVN管理员】
管理SVN服务器,包括开通帐号、停止帐号、处理SVN遇到的问题。
开发人员编写程序的过程中,每个程序都会有很多不同的版本,这就需要开发人员很好的管理代码,在需要的时间可以取出需要的版本,并且每个版本都需要一个完成的说明和标记。我们公司采用Sub Version(简称SVN,主要用于定制项目管理)和Rational team concert(简称RTC,主要用于产品管理)做为版本管理工具,在多个开发人员开发同一段代码的过程中,版本的管理和协作规范显得尤为重要。
如何参与协作开发,具体参考以下文档:
注:开发人员必须遵守以上规范,如发现未遵守以上规范,导致代码丢失或者影响其他开发人员正常工作的行为,会给予相应的处罚
开发人员在编程过程代码目录结构、业务逻辑在什么地方、配置文件存放位置等都需要规范,以便其他开发人员快速查找文件,减少开发过程中的沟通,减少维护成本。
src是存放JAVA代码的目录,我们公司所有的项目的包名前面都有com.landray.kmss,后面接的是项目名称,如HR项目就是com.landray.kmss.hr,下面是HR的各个模块,如绩效考核模块:com.landray.kmss.hr.pm。
我们公司采用三层架构(struts、hibernate、spring),JAVA代码分成五个目录存放,目录包括action、form、dao、model、service,还有一个ApplicationResources.properties资源文件文件,每个模块都包含五个目录和一个资源文件。代码结构如下:
com.lanray.kmss.项目名称
—— 模块1
——子模块(如归档模块)
——action
——constant
——dao
——hibernate
——form
——model
——service
——spring
——util
——ApplicationResources.properties
—— 模块2
—— 模块3
例子:
com.landray.kmss.hr.pm.action
com.landray.kmss.hr.pm. archive(绩效考核归档模块)
com.landray.kmss.hr.pm.dao
com.landray.kmss.hr.pm.dao.hibernaete
com.landray.kmss.hr.pm.form
com.landray.kmss.hr.pm.model
com.landray.kmss.hr.pm.service
com.landray.kmss.hr.pm.service.spring
com.landray.kmss.hr.pm.ApplicationResources.properties
页面文件存放在WebContent目录下面,代码结构如下:
WebContent
——项目名称
——模块1
——模块2
——模块3
例子:
WebContent
——hr
——pm
——hr_pm_action
——hr_pm_angle
——resources(可选)
——retain
——salary
发现多个模块使用的文件的直接存放在模块下
resources存放JS、图片、样式、静态HTML
配置文件名 |
放置路径样例 |
spring配置文件 |
WebContent/WEB-INF/KmssConfig/sys/organization/spring.xml |
枚举类型文件 |
WebContent/WEB-INF/KmssConfig/sys/organization/enums.xml |
设计信息配置文件 |
WebContent/WEB-INF/KmssConfig/sys/organization/design.xml |
struts配置文件 |
WebContent/WEB-INF/KmssConfig/sys/organization/struts.xml |
校验配置文件 |
WebContent/WEB-INF/KmssConfig/sys/organization/validation.xml |
Hibernate配置文件 |
WebContent/WEB-INF/KmssConfig/sys/organization/hibernate.xml |
design、spring.xml等文件应存放WebContent\WEB-INF下的KmssConfig目录下面,代码结构如下:
WebContent
——WEB-INF
——KmssConfig
——项目名称
——模块1
——data-dict
——模块2
例子:
WebContent
——WEB-INF
——KmssConfig
——hr
——pm
——data-dict
——HrPmAction.xml
——design.xml
——spring.xml
——hibernate.xml
——struts.xml
——validation.xml
——enums.xml
——retain
业务代码均在spring或者dao中开发,action只用于页面的跳转,禁止在action写大量业务代码,禁止对model进行赋值操作,禁止多次调用service的更新操作,禁止直接调用dao
注:开发人员在开发过程中请严格遵循以上代码结构
数据库设计在开发中如有更改,要及时维护PowerDesigner
没有必要情况不要写数据库特性的sql语句,尽量使用HQL语句,如有特殊情况特殊处理
model里面不能使用基础类型,只能使用对象类型,如:double类型、int类型等是不能使用,要使用Double类型、Integer类型等
hbm中String的length大于1500的不能超过5个,否则使用clob属性
针对类似Clob、Blob等大字段类型的字段,必须采用字段延时加载的模式,修改样例如下:
<property
name="docContent"
column="doc_content"
update="true"
insert="true"
not-null="false"
type="com.landray.kmss.common.dao.ClobStringType"
lazy="true"
length="1000000" />
protected String docContent;
public String getDocContent() {
return (String) readLazyField("docContent", docContent);
}
public void setDocContent(String docContent) {
this.docContent = (String) writeLazyField("docContent",
this.docContent, docContent);
}
-design中配置模块首页(homepage)
例如:
urlPrefix="km/doc" url="/moduleindex.jsp?nav=/km/doc/tree.jsp&main=%2Fkm%2Fdoc%2Fkm_doc_knowledge%2FkmDocKnowledge.do%3Fmethod%3DlistChildren%26s_path%3D%25E6%2589%2580%25E6%259C%2589%25E6%2596%2587%25E6%25A1%25A3" messageKey="km-doc:kmDoc.tree.title" /> 注意:url需要转码,并且不能将s_css=default配置在里面 错误的配置: urlPrefix="km/doc" url="/moduleindex.jsp?nav=/km/doc/tree.jsp& main=/km/doc/km_doc_knowledge/kmDocKnowledge.do?method=listChildren&s_path=%E6%89%80%E6%9C%89%E6%96%87%E6%A1%A3&s_css=default" messageKey="km-doc:kmDoc.tree.title" /> -design中portlet配置需要添加morlUrl,默认配置为模块首页地址 例如: moreURL="/km/doc.index" -有“我的工作”、“系统配置”、“草稿”等属性需要在design中配置myjob、config、darft等treenode for(i=0; i<2; i++){ Test1(); } for(i=0; i<2; i++){ Test2(); } for(i=0; i<2; i++){ … } for (i=0; i<2; i++){ for(j=0; j<2; j++){ for(k=0; k<2; k++){ for…. } } } } 例如: -没有使用过的方法需要删除 -已经不需要的代码不要长篇幅的注释放在那里 -方法体需要添加注释 -jsp不允许直接写中文 例如: if(fdBeforeStartTimeReminds==null||fdBeforeStartTimeReminds==""){ alert(" document.getElementById("fdBeforeStartTimeRemind").focus(); return false; } 错误的写法: if(fdBeforeStartTimeReminds==null||fdBeforeStartTimeReminds==""){ alert("日程开始前提醒的时间不能为空"); document.getElementById("fdBeforeStartTimeRemind").focus(); return false; } 例如: 错误的写法: 创建时间
-单选按钮或多选按钮需要添加 -jsp中需要import一个jsp时需要在import中指定编码格式UTF-8,避免出现乱码问题 例如: value="com.landray.kmss.km.bam.model.KmBamDocKnowledge" /> -js中alert使用的资源文件中若含有双引号,alert必须使用单引号。 例如: km.doc.subject=当前操作为“修改当前处理人”! alert(' 错误的写法: alert(" -properties不允许写入含有单引号或双引号的html语句,如必要资源文件需拆语句 例如: 资源文件中 sysNotifyTodo.home.you=您 sysNotifyTodo.home.notHave=没有 sysNotifyTodo.home.todo=待办事宜 jsp中 错误的写法: 资源文件中 sysNotifyTodo.home.havenot=您 没有 待办事宜 jsp中 表和字段全部小写,用“_”分隔表名或字段名中的多个词 表:[产品简称_模块简称_表简称] 样例:hr_org_dept 每个数据库的主表:表:[产品简称_模块简称_main] 样例:km_review_main 子表名称:[产品简称_模块简称_主表简称_子表简称] 样例:km_review_main_keyword 中间表名称:[产品简称_模块简称_主表简称_字段简称] 样例:km_review_main_post 主键:[fd_id] 外键:[fd_字段名_id] 样例:fd_creator_id 字段:[fd_字段名] 样例:fd_order 字段类型: 主外键:VARCHAR2(36) 布尔:NUMBER(1) 枚举:NUMBER(2) 普通的多行文本:VARCHAR2(1500)或VARCHAR2(2000) RTF:CLOB 排序号:NUMBER(10) 注:表名长度、字段名长度均不能超过30个字符 类名:[产品简称+模块简称+表内容简称] 样例:HrOrgDept 普通属性:[fd字段名] 样例:fdOrder、docCreator 特殊对象属性:直接属性的类名(首字母小写) 说明:特殊对象指该对象通过类名已经可以明确对象的含义,该对象无二义性,如:hrOrgPostType(岗位性质)。但类似SysOrgElement(组织架构元素)的对象,它既可以表示创建者,也可以表示修改者或其他实际的业务属性,这种情况下,该对象必须以“普通属性”的格式命名,如创建者命名为fdCreator。 样例:hrOrgPostType 普通列表属性:[fd字段名的复数] 样例:fdEditors 特殊列表属性:直接属性的类名的复数 说明:特殊列表属性类似于特殊对象属性,与普通列表属性的区别是该类含义无二义性。 样例:hrOrgPostTypes 含义 表名 样例 备注 模板-类别中间表 [产品简称_模块简称_tmp_category] km_review_tmp_category 如果有多种模板则根据需要修改单词:tmp 相关岗位中间表 [产品简称_模块简称_主表简称_post] km_review_main_post 相关属性中间表 [产品简称_模块简称_主表简称_property] km_review_main_property 关键字中间表 [产品简称_模块简称_主表简称_keyword] km_review_main_keyword 管理员中间表 [产品简称_模块简称_主表简称_admin] km_review_main_admin 可阅读者/可使用者中间表 [产品简称_模块简称_主表简称_reader] km_review_main_reader 可编辑者/可维护者中间表 [产品简称_模块简称_主表简称_editor] km_review_main_editor 其他可阅读者 [产品简称_模块简称_主表简称_oreader] km_review_main_oreader 其他可编辑者 [产品简称_模块简称_主表简称_oeditor] km_review_main_oeditor 所有可阅读者 [产品简称_模块简称_主表简称_areader] km_review_main_areader 所有可编辑者 [产品简称_模块简称_主表简称_aeditor] km_review_main_aeditor 附件可拷贝者 [产品简称_模块简称_主表简称_attcopy] km_review_main_attcopy 附件可下载者 [产品简称_模块简称_主表简称_attdl] km_review_main_attdl 附件可打印者 [产品简称_模块简称_主表简称_attprint] km_review_main_attprint 普通类型 含义 字段名 Java属性名 数据库字段类型 Java字段类型 必须 名称 fd_name fdName VARCHAR2(200) String Y 排序号 fd_order fdOrder NUMBER(10) Integer 描述 fd_description fdDescription VARCHAR2(1500) String 父类别 fd_parent_id hbmParent VARCHAR2(36) IbaseTreeModel 所属部门 fd_dept_id fdDept VARCHAR2(36) SysOrgElement 通知类型 fd_notify_type fdNotifyType VARCHAR2(100) String 内容管理 含义 字段名 Java属性名 数据库字段类型 Java字段类型 必须 标题 doc_subject docSubject VARCHAR2(200) String Y 状态 doc_status docStatus VARCHAR2(2) String 创建者 doc_creator_id docCreator VARCHAR2(36) SysOrgPerson Y 修改人 doc_alteror_id docAlteror VARCHAR2(36) SysOrgPerson 作者 doc_author_id docAuthor VARCHAR2(36) SysOrgPerson 创建时间 doc_create_time docCreateTime DATE Date Y 最后修改时间 doc_alter_time docAlterTime DATE Date 发布时间 doc_publish_time docPublishTime DATE Date 所属分类 doc_category_id docCategory VARCHAR2(36) ISysCategoryTemplate Y 所属部门 doc_dept_id docDept VARCHAR2(36) SysOrgElement 关键字 doc_keyword docKeyword VARCHAR2(200) String 相关岗位 doc_post_id docPosts VARCHAR2(36)-中间表 List 相关属性 doc_property_id docProperties VARCHAR2(36)-中间表 List 点击率 doc_hits docHits NUMBER(10) Integer 文档内容 doc_content docContent CLOB String 权限相关 含义 字段名 Java属性名 数据库字段类型 Java字段类型 必须 管理员 auth_admin_id authAdmins VARCHAR2(36)-中间表 List 可阅读者 auth_reader_id authReaders VARCHAR2(36)-中间表 List 可编辑者 auth_editor_id authEditors VARCHAR2(36)-中间表 List 其他可阅读者 auth_other_reader_id authOtherReaders VARCHAR2(36)-中间表 List 其他可编辑者 auth_other_editor_id authOtherEditors VARCHAR2(36)-中间表 List 所有可阅读者 auth_all_reader_id authAllReaders VARCHAR2(36)-中间表 List 所有可编辑者 auth_all_editor_id authAllEditors VARCHAR2(36)-中间表 List 所有人可阅读标记 auth_reader_flag authReaderFlag NUMBER(1) Boolean 所有人可编辑标记 auth_editor_flag authEditorFlag NUMBER(1) Boolean 附件可拷贝者 auth_att_copy_id authAttCopys VARCHAR2(36)-中间表 List 不可拷贝标记 auth_att_nocopy authAttNocopy NUMBER(1) Boolean 附件可下载者 auth_att_download_id authAttDownloads VARCHAR2(36)-中间表 List 不可下载标记 auth_att_nodownload authAttNodownload NUMBER(1) Boolean 附件可打印者 auth_att_print_id authAttPrints VARCHAR2(36)-中间表 List 不可打印标记 auth_att_noprint authAttNoprint NUMBER(1) Boolean 注:创建人、创建时间必须为docCreator和docCreateTime 字段名称 值列表 备注 doc_status(文档状态) 10 草稿; 20 待审; 11 驳回; 00 废弃; 30 发布; 40 过期(该状态可选) 如果同等状态下有多种形式的,请修改第二位的编码,如发布状态下也会有已反馈等,可将其置为31 默认角色:ROLE_模块名(英文)_DEFAULT 定义于:模块的默认校验 名称:模块名(中文)_默认权限 描述:可访问模块名(中文)中的其他页面以及可以进行模块名(中文)中的其他操作 样例: 角色:ROLE_SYSORG_DEFAULT 名称:组织架构_默认权限 描述:可访问组织架构中的其他页面以及可以进行组织架构中的其他操作 基础信息维护者:ROLE_模块名(英文)_SETTING 定义于:简单的基础信息维护(注意:简单的基础信息一般指单表) 名称:模块名(中文)_维护基础信息 描述:可维护模块名(中文)中的基础信息 样例: 角色:ROLE_SYSORG_SETTING 名称:组织架构_维护基础信息 描述:可维护组织架构中的基础信息 新增角色:ROLE_表名(英文)_CREATE 定义于:表的add、save、saveadd页面 名称:模块名(中文)_新增表名(中文) 描述:可新增模块名(中文)中的表名(中文)信息 样例: 角色:ROLE_SYSORGDEPT_CREATE 名称:组织架构_新增部门 描述:可新增组织架构中的部门信息 删除角色:ROLE_表名(英文)_DELETE 定义于:表的delete、deleteall页面 名称:模块名(中文)_删除表名(中文) 描述:可删除模块名(中文)中的表名(中文)信息 样例: 角色:ROLE_SYSORGDEPT_DELETE 名称:组织架构_删除部门 描述:可删除组织架构中的部门信息 查阅角色:ROLE_表名(英文)_VIEW 定义于:表的view和list页面,注意跟READER的角色区分,一般用于无权限过滤的表 名称:模块名(中文)_查阅表名(中文) 描述:可查阅模块名(中文)中的表名(中文)信息 样例: 角色:ROLE_SYSORGDEPT_VIEW 名称:组织架构_查阅部门 描述:可查阅组织架构中的部门信息 编辑角色:ROLE_表名(英文)_EDIT 定义于:表的edit和update页面,注意跟EDITOR的角色区分,一般用于无权限过滤的表 名称:模块名(中文)_编辑表名(中文) 描述:可编辑模块名(中文)中的表名(中文)信息 样例: 角色:ROLE_SYSORGDEPT_EDIT 名称:组织架构_编辑部门 描述:可编辑组织架构中的部门信息 读者角色:ROLE_表名(英文)_READER 定义于:表Model的数据过滤器,一般用于有权限过滤的表 名称:模块名(中文)_查看所有的表名(中文) 描述:可查看模块名(中文)中的所有表名(中文)信息(无论是否有授权) 样例: 角色:ROLE_SYSORGDEPT_READER 名称:组织架构_查看所有的部门 描述:可查看组织架构中的所有部门信息(无论是否有授权) 读者角色:ROLE_表名(英文)_EDITOR 定义于:表Model的数据过滤器,一般用于有权限过滤的表 名称:模块名(中文)_编辑所有的表名(中文) 描述:可编辑模块名(中文)中的所有表名(中文)信息(无论是否有授权) 样例: 角色:ROLE_SYSORGDEPT_EDITOR 名称:组织架构_编辑所有的部门 描述:可编辑组织架构中的所有部门信息(无论是否有授权) 结合部门的角色:ROLE_表名(英文)_DEPT_OPT 定义于:表的OPT相关页面 名称:模块名(中文)_操作名本部门下的表名(中文) 描述:可操作名模块名(中文)中本部门下的表名(中文)信息 样例: 角色:ROLE_SYSORGDEPT_DEPT_ADD 名称:组织架构_增加本部门下的部门 描述:可增加组织架构中本部门下的部门信息 程序结构清析,简单易懂,单个函数的程序行数避免超过100行,单个类避 免超过1000行。 尽量使用标准库函数和公共函数。 不要随意定义全局变量,尽量使用局部变量。 使用括号以避免二义性,如:if和else 基础数据对象如:Long、Double等不能使用new方法直接初始化,要使用 ValueOf()方法 集合类要声明集合元素的类型,如:Map Java源文件还遵循以下规则: 1.1包和引入语句(Package and Import Statements) 在多数Java源文件中,第一个非注释行是包语句。在它之后可以跟引入语句。例如: package com.landray.kmss.common.actions; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionMapping; 1.2文件注释(Beginning Comments) 所有的源文件都应该在有一个C语言风格的注释,其中列出该类的使用说明、作者、版本信息、日期: /** * Action基类,不建议直接继承,仅当ExtendAction完全无法满足实际业务需求时才继承该类。 * 使用范围:Action层代码,作为基类继承。 * * @author 叶中奇 * @version 1.0 2006-04-02 */ 在处理过程的每个阶段都有相关注释说明,特殊变量(结构、联合、类或对象)定义或引用时,也应写注释,有注释有便于其他开发人员或自己下次查看代码时候能很明白程序的意思,读懂程序,可以减少内部的沟通。 程序可以有4种实现注释的风格:块(block)、单行(single-line)、尾端(trailing)和行末(end-of-line)。 块注释通常用于提供对文件,方法,数据结构和算法的描述。块注释被置于每个文件的开始处以及每个方法之前。它们也可以被用于其他地方,比如方法内部。在功能和方法内部的块注释应该和它们所描述的代码具有一样的缩进格式。 块注释之首应该有一个空行,用于把块注释和代码分割开来,比如: /* * Here is a block comment. */ 短注释可以显示在一行内,并与其后的代码具有一样的缩进层级。如果一个注释不能在一行内写完,就该采用块注释(参见"块注释")。单行注释之前应该有一个空行。以下是一个Java代码中单行注释的例子: if (condition) { /* Handle the condition. */ ... } 极短的注释可以与它们所要描述的代码位于同一行,但是应该有足够的空白来分开代码和注释。若有多个短注释出现于大段代码中,它们应该具有相同的缩进。 以下是一个Java代码中尾端注释的例子: if (a == 2) { return TRUE; /* special case */ } else { return isPrime(a); /* works only for odd a */ } 注释界定符"//",可以注释掉整行或者一行中的一部分。它一般不用于连续多行的注释文本;然而,它可以用来注释掉连续多行的代码段。以下是所有三种风格的例子: if (foo > 1) { // Do a double-flip. ... } else { return false; // Explain why here. } //if (bar > 1) { // // // Do a triple-flip. // ... //} //else { // return false; //} 注:代码的注释只能使用单行注释,不能使用块注释 变量的声明应注意其使用范围,不要什么变量都定义为public 推荐一行一个声明,因为这样以利于写注释,如下: int level; // indentation level int size; // size of table int level, size; //最好不要这样声明 定义一个集合,如:map的时候要说明key,value是什么 语句是包含在大括号中的语句序列,形如"{ 语句 }"。例如下面各段。 - 被括其中的语句应该较之复合语句缩进一个层次 - 左大括号"{"应位于复合语句起始行的行尾;右大括号"}"应另起一行并与复合语句首行对齐。 - 大括号可以被用于所有语句,包括单个语句,只要这些语句是诸如if-else或for控制结构的一部分。这样便于添加语句而无需担心由于忘了加括号而引入bug,并且方便其他开发人员阅读。 例如: for(int i =0; i <10; i ++){ i++ ; if(i==5) break ; } if (condition) { statements; } if (condition) { statements; } else { statements; } 避免为了偷懒写成 if (condition) statements; else statements; -case语句的结尾需要加break -switch需要写default分支 例如: switch (runType) { case RUNTYPE_ALLNODE: sysQuartzScheduler.scheduleJob(jobModel); break; case RUNTYPE_ALLSERVER: if (channel.isServerMaster()) sysQuartzScheduler.scheduleJob(jobModel); break; default: sysQuartzScheduler.scheduleJob(jobModel); break; } 例如: "failure".equals(para) 例如: Map 例如: whereBlock = "kmMissiveSendMain.docStatus != " + SysDocConstant.DOC_STATUS_DRAFT; 避免为了偷懒写成 whereBlock = "kmMissiveSendMain.docStatus != 10"; 注:开发人员在开发过程中请注意按ctrl+shift+o(去除引用多余的包)和ctrl+shift+f(自动排版) 本文档仅供蓝凌内部使用,未经蓝凌许可,不得以任何形式将本文档转发、拷贝给其他方。 [全文完]