HugeBoss开发规范

目录

概述

项目依赖关系

开发模式

1 查询模式

2 提交模式_二次业务

3 提交模式_维护

编码细节及案例说明

1 命名问题

2 设计问题

数据库规范

Sql提交规范

版本控制规范(For 版本管理员)




概述

HugeBoss开发编码基础是Java编码规范,加上Huge自己的规范组成。

本文着重介绍的是Huge自己的开发规范。
要想清楚的了解HugeBoss的开发规范,首先要对HugeBoss项目的整体有个把握,因此我们会先介绍项目之间的依赖关系,再说一下从编码角度看到的三种比较典型的开发模式,最后是一些编码要注意的细节及案例。


项目依赖关系

!worddav2ca459935363688ec396a7044b48656f.jpg|height=309,width=553!如上图所示

UI包括所有以ui开头的项目,界面层

Model包括所有以presentationmodel开头的项目,处理界面交互逻辑

Dto包括所有以dto开头的项目,前后台交互的数据

Service包括所有以service(不带.internal)开头的项目,后台服务公布给前台调用的接口

Service.internal包括所有以service.internal开头的项目,后台服务公布的接口实现

Assembler包括所有以assembler开头的项目,组装器,负责将Domain组装成Dto或反之

Domain包括所有以domain开头的项目,领域对象

Data包括所有以data开头的项目,处理数据层的查询更新等

Dtv.service包括所有以dtv.service(不带.internal)开头的项目,第三方系统对我们的接口

Dtv.service.internal包括所有以dtv.service.internal开头的项目,第三方系统对我们的实现

Sysway包括所有以sysway开头的项目,放一些基础类和工具类,任何项目都可以依赖于他
UI,Model,Service,Dto,Sysway 发布成前台客户端程序

Service,Dto,Sysway,Service.internal,Assembler,Domain,Date,Dtv发布成后台服务程序
另外还有一些规则:

包名以"com.sysway"开头且不含有"boss"的项目,都是放与boss无关的公共的类接口。
编码时要注意

1 不要有直接或间接的循环依赖(例如ui依赖于model,model如果再依赖ui就是错误的)。

2 不要有跳过某一层建立依赖的情况(例如model依赖domain层就是错误的),因为我们的系统是分层设计的(参考《HugeBoss架构》)。


开发模式

所有的命名,统一按先动词后名词的顺序,符合自然语言逻辑。

所有的类该放到哪个包里,以Domain为参照。

1 查询模式

命名规则:

接口名称定义规则是:"I"+ Domain类名 + "Service"

接口实现类名称定义规则是:接口名去掉I

接口查询方法定义规则是:"find"+ Domain类名 + 特性标识+ "Info"

查询条件的DTO定义规则是:Domain类名 + 特性标识 + "Info"

如果查询条件特别简单如只有一个code可以不必定义DTO

查询结果的DTO定义规则是:Domain类名 + 特性标识 + "Info"

如果返回结果特别简,如只是个数字,可以不必定义DTO

其中"特性标识"是根据具体应用场景对Domain的修饰,用于说明被命名对象的含义。

Finder接口命名规则:"I"+ Domain类名 + "Finder"

Finder实现命名规则:Finder接口名去掉I

Assembler命名规则:返回的DTO类名 + "Assembler"实现Domain对DTO的转换
查询接口实现方法:

1 前置条件检查

2 调用要查询Domain对象的finder中符合条件的方法(如果没有自己加)

3 查出的Domain通过Assembler组装出需要返回的DTO或列表
举例说明:

以客户(Customer)为例子,按客户编码查询客户摘要信息

接口名定义为:ICustomerService

接口实现类名称为:CustomerService

查询条件DTO定义为:不定义DTO,直接用参数customerCode

查询结果DTO定义为:CustomerSummaryInfo

接口方法定义为:

CustomerSummaryInfo findCustomerSummaryInfo(String customerCode);

实现:

public CustomerSummaryInfo findCustomerSummaryInfo(String customerCode) {

assert customerCode != null : "传入的customerCode不能为null";

Customer customer = Customer.getCustomerFinder().findByCode(customerCode);

return CustomerSummaryInfoAssembler.create(customer);

}




2 提交模式_二次业务

命名规则:与上面相同的不再重复说明

接口查询方法定义规则是:"业务动词"[ + Domain类名]

前台提交的数据以DTO的形式传到接口参数中,特别简单的情况可以不定义DTO

Act命名规则:"业务动词"[ + Domain类名] + "Act"

Order命名规则:"业务动词"[ + Domain类名] + "Order"

二次业务的接口一般定义在ICustomerOrderServcie中

二次业务的接口参数,一定要带个CommitType类型的commitType,这个参数说明本次是预提交还是真正的提交(预提交是为验证整个提交过程用,不会真正提交到数据库)

在实现中不需要对commitType参数做出处理,因为有方面统一处理预提交/提交。
前台实现方法:

界面必须继承BaseCustomerSection,model必须继承BaseCustomerSectionModel
查询接口实现方法:

1 前置条件检查

2 组织新建Act需要的数据

3 调用Act.run()方法,下受理单。

注:一般来说二次业务接口实现无返回值,出错信息(如前置条件不符)通过抛异常或断言实现(有方面把断言转换为异常)。
举例说明:

以新客户订购为例子

前台提交的DTO为:CustomerPurchaseOrderInfo

接口定义如下:

void purchase(

CustomerPurchaseOrderInfo customerPurchaseOrderInfo,

CommitType commitType);

接口实现请参考代码。


3 提交模式_维护

命名规则:与上面相同的不再重复说明

Page命名:"Maintain"+ Domain类名 + "Page"

Section命名:"Maintain"+ Domain类名 + "Section"

Model命名:"Maintain"+ Domain类名 + "Model"

接口方法命名:"Maintain"+ Domain类名

Act命名:"Maintain"+ Domain类名 + "Act"

Assembler命名规则:Domain类名 + "Assembler"

这里的Assembler与查询功能的Assembler相反,是把DTO转换成Domain,并提供增加、更改的方法。
接口定义参数统一有三个列表:

addInfos(增加的信息)、updatedInfos(修改的信息)、deletedInfos(删除的信息)

可以根据情况增加其它参数
查询接口实现方法:

1 前置条件检查

2 组织新建Act需要的Assembler

3 调用Act.run()方法,循环三个列表,分别进行增加、修改、删除操作。

注:一般来说维护功能的接口实现也无返回值,出错信息(如前置条件不符)通过抛异常或断言实现(有方面把断言转换为异常)。
举例说明:

维护设备为例子

DTO定义为:MaintainDeviceInfo

接口名称为:maintainDevice

Act名称为:MaintainPhysicalDeviceAct

Assembler名称为:PhysicalDeviceAssembler

接口定义如下:

public void maintainDevice(List<MaintainDeviceInfo> addedDeviceInfos,

List<MaintainDeviceInfo> deletedDeviceInfos,

List<MaintainDeviceInfo> updatedDeviceInfos);

接口实现

public void maintainDevice(List<MaintainDeviceInfo> addedDeviceInfos,

List<MaintainDeviceInfo> deletedDeviceInfos,

List<MaintainDeviceInfo> updatedDeviceInfos) {

Act act = new MaintainPhysicalDeviceAct(

PhysicalDeviceAssembler.create(addedDeviceInfos),

PhysicalDeviceAssembler.create(updatedDeviceInfos),

PhysicalDeviceAssembler.create(deletedDeviceInfos)

);

act.run();

}

编码细节及案例说明

1 命名问题


所有的命名都以动词在前名词在后的形式,符合自然语言的逻辑
常量定义要大写,不同单词之间以下划线分隔


维护xxx的功能,都以"Maintain"开头。

例如:维护物理资源规格的页面

正确的命名是:MaintainPhysicalResourceSpecificationPage

错误的命名1:PhysicalResourceSpecificationPage(缺少动词)

错误的命名2:PhysicalResourceSpecificationMaintainPage(违反先动词后名词的原则)错误的命名3:ModifyPhysicalResourceSpecificationPage(修改不能够反应所有维护的意 思,维护是指新增,修改,删除的动作集合,并非仅仅把已存在的东西做更改,这是有区别的。)


ActTypeCode的取名以Act结束,不要命名为xxxPage等非Act结尾的,因为Page是实现方式,Act是与业务相关的,与实现无关。

正确的例子:

pageHash.put("MaintainSimpleTypeAct", "com.sysway.boss.ui.businessconfiguration.MaintainSimpleTypePage");//维护简单类型
错误的例子1:

pageHash.put("NewBizMonthReportPage", "com.sysway.boss.ui.syntheticalstatistics.NewBizMonthReportPage");//新宽带业务月报表

不该以"Page"结尾,应该是"Act"。
错误的例子2:

pageHash.put("PhysicalResourceStorageActIn", "com.sysway.boss.ui.resourcemanagement.physical.storage.PhysicalResourceInStoragePage");//物理资源入库

pageHash.put("PhysicalResourceStorageActOut", "com.sysway.boss.ui.resourcemanagement.physical.storage.PhysicalResourceOutStoragePage");//物理资源出库

不是以"Act"结尾。


变量名要写全称,不要缩写,为了易读。

我们的代码命名提倡完整的命名,不提倡缩写,缩写只用在两种情况,

1.该缩写已约定俗称比如:MAC、I、j、k等。

2.由于客观的限制不得不缩写:比如有长度限制的数据库字段名、表名

正确的定义:ChangeBaseProductOrderInfo changeBaseProductOrderInfo;

错误的定义1:ChangeBaseProductOrderInfo info;(引用时从名称看不出含意)

错误的定义2:ChangeBaseProductOrderInfo cbpoi;(引用时从名称看不出含意)


变更名与值,函数名与函数实现要保持一致。

错误例子1:final String IS_PRINT_BEFORE_COMMIT="isCommitBeforePrint";(名称与含义相反)

错误例子2:public List<Product> findRecurringProductByCustomerAndProductStatus(String customerCode, String... productStatuses) {

return findByCustomerAndProductStatus(customerCode, productStatuses);

}

最先是取得有周期性价格的产品,但由于某些地方的需要改为取得所有产品

改了实现后没改函数名称


不要有类似xxx2的命名(类,变更,存储过程等)。

为了程序的易读性,如果在同一作用域里有两个同类的变量,命名时考虑将这两个变量的用途和角色,加入变量名中。不要取为xxx2名称,如果一定不可避免(例如是临时方案),则一定要写明注释。

另外一种类名有XXX2的情况,这个多半是对第一个类的替换和优化,但是又不想影响原来的实现,这种允许存在,但最终要把废弃掉的那个删除,把2改成正常名称。
错误的例子1:

NoteDetailInfo.itemName2

发 票明细项NoteDetailInfo的显示各地不同导致加了多个itemName2的属性


变更字段的取名要精准

如果字段的作用是id请不要命名为code,如果字段的作用是code也不要取成id。


2 设计问题


有时类中需要增加一些静态的方法取得常用值的实例,这时要用方法,不要用静态值。

例如:Money类,外面可以通过Money.ZERO来取得Money为0的实例。

public static final Money ZERO = new Money();

public void setAmount(BigDecimal amount) {

super.setAmount(amount.setScale(DEFAULT_SCALE, RoundingMode.HALF_UP));

}

由于ZERO是静态的,Money又有setAmount()方法会改写amount的值,那么当一个变量采用Money.ZERO的方法做了初始化后,又直接通过setAmount()方法更改Money中amount的值(假设新的值是x),则所有引用ZERO的值都改为了x,这是很危险的做法。
所以在这种情况下,需要把ZERO的值改为通过方法取得一个新的实例。

public static Money getZero(){

return new Money();

}


修改了函数实现后,要遍历所有调过该方法的地方,看是否会受到影响。

错误的例子:

public List<Product> findRecurringProductByCustomerAndProductStatus(String customerCode, String... productStatuses) {

return findByCustomerAndProductStatus(customerCode, productStatuses);

}

最先是取得有周期性价格的产品,但由于某些地方的需要改为取得所有产品

是否看了原来调用该方法的所有地方是否会受到影响?


当前台需要的信息缺少时,应该先找相关人员沟通看有没可用的接口,如果没有,自己重新写一个接口取得相应的数据,不要找个复杂的接口缺只取其中很小一部分数据。

错误的例子:

List list = productSpecificationService.findAll();

// 转换成typeInfo

List<TypeInfo> typeInfoList = this.ConversionTypeInfo(list);


包之间的引用参考下图关系

参考项目依赖关系一节。
错误的例子1:

sysway.presentationmodel引用dto.product

本来是个底层的包,但这样做导致编译sysway.presentationmodel时必须要将所有dto的项目编译通过

sysway.presentationmodel,应该是放与boss无关的类。而dto.product与boss是相关的。


遇到不明白的问题,要先找相关人员或组长进行沟通,了解现有的实现方案,再做决策

是否原来就有现成可用的东西?是否需要小范围的重构?是否需要大面积的重构?
错误的例子1:

ProductOfferingPriceInfo里增加SmartCardCode

SmartCardCode与产品价格信息没关系,是否考虑应该换个方式实现?
错误的例子2:

NoteDetailInfo.itemName2

发 票明细项NoteDetailInfo的显示各地不同导致加了多个itemName2的属性

命名上也看不出来区别,构造函数也没有

一定要加成xxx2吗,发 票的需求越来越杂,原来的结构已很难支持当前的变化,是否应该考虑重构?
错误的例子3:

已经存在的工具方法,在Model又写一遍私有的

private static final SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");

private String format(Calendar date) {

return format.format(date.getTime());

}

实际上DateHelper.toDateString(...)就可以实现


已经没使用的了代码,直接删除掉,不要只注释掉,没人使用,未来也不会有人使用的方法函数也应该删除掉。因为我们有版本控制,需要时可以找到。




所有关于Code的定义,统一通过新建立一个以大写I开头的接口,放在与业务相关的service项目中,包与Domain所在包的位置保持一致。




接口应该与业务相关,放到与当前业务相关的包及接口类中。

错误的例子:

查物理资源信息的放到CommonService中

ICommonService.findPhysicalResources()

应该放到IPhysicalResourceService 中



数据库规范

1 建表时要考虑未来的数据量和性能问题,例如:是否需要建立索引?

2 建表或增加字段时的字段类型不要随便写,请参考自动生成的建表sql中相应的类型。

自动生成sql的脚本是:ant generate-schema-script;

注意:需要ant default;执行完成后才可以执行成功。



Sql提交规范

基本规则:

文件类别有两种,sql,prc

prc文件: 代码块,有begin...end的那种,一个代码块要以~作为结束标识符.

如a.prc文件的内容

Begin

....

End~

Sql文件: 非代码块内容,以;结束。

如 b.sql内容

Insert into ..... ;

Update .....;

Call addmenu....;

注意:每一个完整的sql语句,比如一个存储过程,单个insert语句最后要加一个回车.

文件命名格式.

两位数字[~[两位数字]].prc/sql,前面的数字代表了sql文件执行顺序。

如01.XXX.sql

11.XXX.sql

01~01.XXX.sql

注意 . 号前只能两位数字,不能超过3位.文件命名最好是xx.内容概要[jira号].sql/prc
注意事项:

1有关sql校验的问题,要注意用sql.check工具校验过再提交。

2不同内容的sql不要用同样的文件名。如果是对上一个sql的升级,第2个sql文件名要注明详细点。

例如一个不好的例子:

20090115提交的一个01.proc_staJobs.pdc

和20090316也提交了 01.proc_staJobs.pdc

两个sql内容不一样,在出升级sql时会过滤掉重名的文件。

3.开发只能在全局的s00_current和项目.current下提交或修改当前的sql,已经在history里的sql表明已经

在现场执行过或已经升级到基础库了,修改的话会给其他项目造成影响或造成已执行过该sql的项目的sql版本不一致问题。

4.改变表结构的sql应该放到s00_current下面,修复数据的sql放相应所属项目的current下面,如果需要设置默认值,需要考虑s00_current中的设置不能影响其它项目的执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值