3开发原则与约束Word格式.docx
《3开发原则与约束Word格式.docx》由会员分享,可在线阅读,更多相关《3开发原则与约束Word格式.docx(11页珍藏版)》请在冰豆网上搜索。
![3开发原则与约束Word格式.docx](https://file1.bdocx.com/fileroot1/2022-12/11/b34f9a17-aad0-475d-9e58-c4cb6b851269/b34f9a17-aad0-475d-9e58-c4cb6b8512691.gif)
V1.4
2014-09-15
3
增加数据库规范中部分内容
V1.5
2014-10-27
2.1.23.1.2
增加对MVC各层作用的描述与主键生成策略约束
1.前言
1.1.目的范围
1.1.1.目的作用
本规范的主要目的为指导、规范软件编程人员进行软件代码编写工作,提高软件开发工程师的软件编写能力。
代码规范相当重要,代码规范提高软件代码的可读性,使得开发人员快速和彻底的理解新代码。
好的代码风格不仅会提高可读性,而且会使代码更健壮,更为重要的是在修改时不容易出错。
1.1.2.应用范围
公司所有涉及程序编写的人员和部门。
本约定适用于可执行系统的源代码文件。
为了执行规范,每个软件开发人员必须一致遵守编程规范。
1.2.阅读说明
本规范主要分为设计原则与设计约束两大类。
●设计原则。
主要为设计建议,根据建议可以写出更优质的代码。
本文中为【非加粗字体】;
●设计约束。
指的是所有开发人员必须要严格遵守的规约,不允许有违规行为。
本文中规约以【加粗字体】标识。
其中【灰色的加粗字】表示产品组内部强制执行,各项目建议执行。
2.Java编码原则
2.1.类、接口
2.1.1.设计原则
●类的划分粒度要适当,不宜继承太深;
●建议一个类只做一件事,根据每个类的职责进行划分;
●多使用设计模式,尽量提高代码重用度;
●若多个类中使用相同方法时,请将其方法提到一个接口中或使用抽象类;
●在抽象类和接口都可实现的情况下建议选择使用接口,以更易于扩展及实现多重继承。
2.1.2.设计约束
●程序结构遵守MVC规则:
JSPACTIONSERVICEDAODB,即:
●DAO:
放置不包含业务逻辑的纯粹数据库操作,为Service提供服务;
●Service:
放置主要的业务逻辑代码,此类型代码一般为调用DAO提供的方法进行组合与包装。
为Action层提供服务。
若业务逻辑非常简单的情况下,Service层可以省略不写,同时业务逻辑代码写在Action层;
●Action:
主要放置数据转换、校验、转发与业务逻辑调用的代码,若对应存在Service层,则Action层不应包含具体的业务逻辑代码;
●Jsp:
分为前端代码与Java代码。
其中Java代码应仅负责数据的获取与解析,不应包含具体的业务处理逻辑代码,更不应该存在Jsp直接写SQL语句进行操作的行为。
2.2.方法
2.2.1.设计原则
●一个方法只完成一项职责,在定义系统的公共接口方法外的方法应尽可能的缩小其可见性;
●避免在一个较长的方法里提供多个出口;
●当多个方法中同时使用一套逻辑相近的代码时,请将此类型的逻辑代码抽象成一个独立的方法;
●一个方法代码行数建议不超过200行。
若超过,请将方法进行拆分。
2.3.变量
2.3.1.设计约束
●禁止在代码中出现无意义的数字(MagicNumber),应该为此类型的数字定义一个变量名,提高代码可读性;
●禁止将一个非final实例变量声明为public,实例变量的传递与修改应在方法中实现(构造函数、getter、setter)。
2.4.表达式与语句
2.4.1.设计约束
●所有if、for、where等语句的执行代码段必须使用{}包括起来,即便是只有一个语句;
●禁止在一行代码中进行多个变量的赋值,如a=(b=c+1);
●超过3个else分句请转成switch语句或创建子函数;
●switch语句的每个case中必须带有break;
●循环语句中必须有终止循环的条件或语句,否则容易导致死循环的情况。
2.5.序列化
2.5.1.设计约束
●创建序列化类时,serialVersionUID必须设置一个随机的哈希字段,不应笼统设置为-1L;
●若复制一个Serializable的类进行修改时,必须重新设置新类的serialVersionUID;
●针对瞬态的对象(如IO流对象、Thread对象等)与不希望被序列化的对象,必须在对象声明前加上transient关键字。
2.6.异常捕捉
2.6.1.设计原则
●必须尽可能的精确捕捉异常,而不能笼统使用Exception。
2.6.2.设计约束
●当捕捉到异常时,必须在catch代码区进行处理,并且在日志中记录错误信息(System.out、log4j、oa日志等);
●异常日志不应笼统提及抛出这个异常的方法的名字,应有使用说明性的文字描述与完整的异常栈输出(printStackTrace);
●禁止捕捉异常后不进行任何处理的写法。
2.7.日志
2.7.1.设计原则
●Debug日志记录尽量通用而全面,且与oa的Debug开关配合使用,例子如下:
booleanisDebug="
true"
.equals(System.getProperty(OAConstant.DEBUG))?
true:
false;
if(debug){
System.out.println("
Debug日志:
"
);
}
2.8.线程安全性
2.8.1.设计约束
●在JSP、Servlet及Struts的Action编程中,非final变量应尽量采用局部变量,减少使用实例变量。
由于这些情况都是多线程情况,容易产生线性不安全问题;
●使用synchronized关键字的代码段或函数之间禁止相互引用,以免引起死锁;
●应限制自定义线程个数上限,不设线程限制且并发的情况下(如在Action中start一个新线程),可能会由于线程量暴涨,从而导致native内存耗尽,服务器瘫痪崩溃;
●对于static关键字修饰的变量、synchronized关键字修饰的代码段或函数,必须考虑这部分代码能否在集群环境下正常运行。
因为static的变量变化时无法在集群中简单共享,synchronized的代码段不能阻塞并发在集群里其他节点的代码。
2.9.系统与资源安全性
2.9.1.设计原则
●与上传文件相关的功能(如上传附件等),必须针对后缀名进行判断与过滤:
js、jsp、*htm*(如html、shtml、htm等)、css;
●SQL语句提交时,由客户端传递的变量值必须使用传参形式传入,不允许使用字符串拼接方式实现,此举动容易产生SQL注入,造成安全隐患;
●针对插入与修改的功能,应校验由客户端提交的数据是否存在敏感的字符串:
<
style、<
script、<
!
--、<
%,防止产生JS注入。
2.9.2.设计约束
●涉及到流(IO流、NIO流等)、连接(Connection连接、HttpClient连接等)的函数,必须要在finally块中进行资源关闭,防止代码段异常时该执行的释放的资源代码没被执行到;
●禁止获取流后不在函数中持有对象的写法,如:
StreamUtils.getBytes(newFileInputStream(newFile(path))),此种写法无法对流对象进行资源关闭;
●文件路径分隔符(windows下的\与linux下的/)必须使用File.separator来获取,否则会产生操作系统平台更变时的文件读写错误。
2.10.性能
2.10.1.设计原则
●避免在循环中频繁构建和释放对象;
●避免一次客户端操作中多次操作数据库,大多数情况应尽量使用单次数据库查询以完成操作;
●尽可能早释放资源(IO流、占大内存的对象等),不要过分依赖JVM进行GC操作。
2.10.2.设计约束
●在不涉及线性不安全问题的情况下请勿使用synchronized关键字与同步类(使用StringBuilder代替StringBuffer、ArrayList代替Vector、HashMap代替Hashtable等)。
使用时应尽量控制范围,最好是块级控制;
●不需要重新赋值的变量(含类变量、实例变量、局部变量)声明成final,可提高程序响应效率;
●在编辑String的情况下(如多个字符串的累加)必须使用StringBuffer类,处理完成后将StringBuffer对象再转换为需要的String对象。
2.11.单元测试
2.11.1.设计原则
●单元测试前请尽量使用Findbugs等代码检查工具进行检查,可在一定程度降低代码中的低级错误,插件安装方法请参考《Findbugs插件操作手册(Eclipse版).docx》。
2.11.2.设计约束
●在代码提交前必须对更改的功能手工进行单元测试,提交的代码不能出现明显的错误(如点击后直接报500错等)。
若条件允许,建议使用自动化单元测试。
3.数据库设计原则
3.1.数据库设计规范
3.1.1.设计原则
●表设计时请尽量满足到3NF(即第三范式);
第一范式:
1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
第二范式:
2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;
第三范式:
3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。
●尽量降低表之间的低级冗余,降低操作时产生脏数据与不一致性的可能性,但允许出现高级冗余;
●低级冗余,即重复性的冗余。
如在A表定义的字段在B表重复出现。
主键与外键字段不属于低级冗余范畴;
●高级冗余,即派生性的冗余。
一般这种冗余的目的是为了提高处理速度。
如“单价、数量、金额”三个字段,“金额”就是由“单价”乘以“数量”派生出来的,这种冗余有助提高性能。
●新建表时,请合理考虑实际运行时可能会出现的情况,根据可能会频繁执行的SQL语句建立合理的索引。
3.1.2.设计约束
●禁止在create脚本中设置默认获取当前数据库服务器中的系统时间。
当前时间应该在程序中获取,否则容易由于中间件服务器与数据库服务器时间不一致导致问题;
●所有数据库表必须包含主键或复合主键;
●使用复合主键时,字段个数不能多于3个,否则可能会导致主键索引失效;
●主键生成策略只允许使用以KeyGenerator(common包中)生成的int类型主键或GUID主键,禁止使用数据库自增的int主键;
●所有建库脚本必须按模块分开,且所有的表结构发生更改时,建库脚本必须要有alter语句。
3.2.数据库开发规范
3.2.1.设计原则
●尽量减少使用数据库的特性,如Oracle的深度递归、分页函数等;
若必须要使用这种特性,请获取exoa-config中的数据库类型,添加针对不同数据库的特化处理代码。
数据库类型的获取方法如下(默认为Oracle):
StringdatabaseType=ConfigHelper.fastGetConfig("
common"
"
databaseType"
oracle"
).toLowerCase();
●使用where时必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小;
●若需要使用触发器时,必须要考虑触发器的写法是否会带来较大的性能损耗;
●经常出现在Where条件中的字段应建立索引,如外键字段。
Having后的条件索引是无效的;
●查询时应尽量减少多余数据的读取,通过使用where子句来减少返回的记录数;
●对索引列的比较,应尽量避免使用not或!
=,可拆分为几个条件。
因为“not”和“!
=”不会使用索引;
●在where子句中,如果有多个过滤条件,应将索引列或过滤记录数最多的条件放在前面;
●尽量使用exists代替selectcount
(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用。
3.2.2.设计约束
●禁止在where子句中的“=”左边进行函数、算术运算或其他表达式运算,此举动会导致系统将可能无法正确使用索引,如price*10=sum;
●做关联查询时,若两个表关联的字段为重复性极低的字段(如id),则两个表关联的字段必须加上索引;
●禁止可以枚举出来的数据的列建立索引。
如布尔型只有T和F,由于这种索引的区分度太低,数据库选择索引时几乎不会选用这类型索引执行,同时也存在索引维护成本,因此不宜建此类型的索引;
●当复合索引为多列时应将变化显著的列放到复合索引的首位,且复合索引不宜超过16列;
●禁止使用【insertintotable_namevalues(?
?
……)】语法,必须使用【insertintotable_name(col1,col2,……)values(?
…...)】,一旦数据列发生顺序变动(如人为变动、数据库迁移)时,此语句无法使用;
●如无必要情况,禁止使用数据库特性化语句(如Oracle的深度递归等),可降低数据库迁移时的成本。
4.EXOA二次开发原则
4.1.二次开发方法
4.1.1.二次开发规模评估
●修改原有模块:
原有模块功能不满足需求的情况。
●新增模块:
需求与系统现有模块差异较大,且新增功能要依赖OA环境运行的情况。
●新增应用系统:
需求规模较大,与OA系统现有功能基本无交集,且新增功能可不依赖OA环境运行的情况。
4.1.2.修改原有模块
●评估原模块功能与需求的差异,差异过大要比较扩展与做新模块之间的长短。
●理解原模块的工作机制和设计原意,检查原模块是否已提供配置手段实现需求,是否提供了扩展方法,若以上皆无,或仍不满足需求,才对原模块代码进行修改。
●分析修改内容是否通用,是否会引入新的依赖,是否对数据库结构作变更,后续能否进行产品升级。
●分析修改对实施的影响。
4.1.3.新增模块
●反复确认系统中无相近功能的模块。
●分析新模块与系统其它模块的关系,明确交互的场景和接口,注意模块间的依赖不要出现循环。
●新模块采用的技术方案不能与OA发生冲突。
原则上不允许引入新的第三方软件依赖。
●通过对业务的分析,预先考虑扩展方案。
●明确模块的实施方法,尽量做到配置可自维护,简化实施过程。
4.1.4.新增应用系统
●分析新系统与其它系统(包括OA)间的关系,与其它系统的交互尽量采用代理模式进行隔离,代理通过调用其它系统的分布式接口完成交互。
●新系统尽量采用与OA相同的技术方案,以方便功能迁移。
●明确系统的实施方法,尽量做到配置可自维护,简化实施过程。
4.2.二次开发规约细则
●数据库编码、页面编码统一使用GBK,禁止使用GB2312。
由于GB2312字符集不全,会导致部分生僻字变成问号;
●原则上不允许引入第三方包。
若必须要引入,在不造成与现有第三方包版本冲突的情况下,通过项目组讨论通过后方可引入;
●相同工作区下,各个核心包的版本号必须一致;
●禁止直接使用JDBC访问数据库。
在不使用第三方ORM框架的情况下,必须使用SQLUtil进行数据库交互;
●除使用事务,其余的所有SQL操作禁止获取SQLUtil的connection方法进行操作;
●项目若需要有使用SaaS模式,整个工作区代码必须遵守SaaS规范,具体规范详见于《4.SAAS模式编码规范与约束.docx》;
●禁止直接对核心表(mv_开头、um_开头的表)进行增删改操作,这种操作必须要调用核心包的对外公布接口,否则会导致核心公文缓存(如公文表单模板缓存等)中产生脏数据。
5.代码管理原则
5.1.代码管理
5.1.1.设计约束
●所有的代码提交必须写readme,且提交时写上commit的注释(comments);
●readme文件需放置在ear工程的根目录下,一个的产品只允许有一个readme;
●readme撰写方式如下:
1.readme提交格式:
提交序号(自编的流水号,数字):
【模块名】日期改动者
改动序号(自编的流水号,可用顺序字母):
project问题ID(若有)修改简述
改动的描述与备注(修改方法、注意事项等)
改动内容类型(+表示增加,-表示删除,*表示修改)改动文件
2.撰写注意事项:
日期统一使用同步CVS的日期,非修改日期,因此可将同步CVS前的所有问题集合在同一个提交序号内;
3.范例:
92:
【协同办公平台】20140404wangp
A:
#18772【工作平台—流程中心—流程审批配置—工作代理】代理开始时间早于系统时间时没有提示信息
增加判断:
代理开始时间:
不能选择早于当前系统时间
*/missiveWeb/WebContent/processing/delegate/delegateEdit.jsp
B:
#18664【工作平台—流程中心—流程发起—流程起草—参考资料】jpg格式图片打开是空白页
修改openFileWith(fileId,workItemId,ext)方法,对图片文件直接显示
*/missiveWeb/WebContent/processing/workitem/docInstReference.jsp
●需要打基线时,必须把基线更变情况列入readme中,如:
-包名(每次打包前必填):
exoa(20140721)_V00_01_009-V01_03_012.ear
--------------------------------------------------------------------------------------------
-打包基线(每次打包前必填):
exoa(20140721)_V00_01_009-V01_03_012
5.2.版本控制管理
5.2.1.设计约束
●对外出包(发布测试版本、发布正式版本)的出口应该控制在一个人手上,该角色需要控制出包频率与基线定制。
详细请参考《5.出包的流程与规范.docx》;
●不允许修改已成为基线版本文件的任何代码。