架构师技能1:Java工程规范浅析领域模型VODTODOPO优秀命名

Posted hguisu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了架构师技能1:Java工程规范浅析领域模型VODTODOPO优秀命名相关的知识,希望对你有一定的参考价值。

把我们之前项目的相关规范做了个总结记录下来,仅供参考,望能有点帮助。

每个人的代码风格迥异,通过统一的编码风格使得代码可读性大大提高。

编程规约或者编码规范的的本质是提高了代码的可读性,最终目的是提高团队协作效率,降低工程维护成本。

一、项目的应用分层:


代码分层,让不同层次的代码做不同的动作。层次清晰的代码,提高可读性,从代码结构就大概能了解到代码是如何分层,每层大概功能是什么。例如常用的Controller、Service、Mapper/Dao三层代码结构,其各层的代码逻辑范围。

默认上层依赖于下层,箭头关系表示可直接依赖,如:开放接口层可以依赖于Web 层,也可以直接依赖于 Service 层,依此类推:

1、开放接口api层/controller: 可直接封装 Service 接口暴露成 RPC 接口; 通过 Web 封装成 http 接口; 网关控 制层等。

2、Web 层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。

3、Service 层:相对具体的业务逻辑服务层。

4、Manager 层:通用业务处理层,它有如下特征

  • 1)封装下沉通用能力 对 Service 层通用能力的下沉,如缓存方案、 中间件通用处理;如mqMannager。
  • 2)封装第三方接口:对第三方平台封装的层,预处理返回结果及转化异常信息,如rpcMannager。
  • 3) 与 DAO 层交互,对 DAO 的业务通用能力的封装。

5、DAO 层:持久层,数据访问层,与底层 mysql、 Oracle、 Hbase 进行数据交互,用来封装对数据库的访问(CRUD)

6、Model, 领域模型对象:   (第二节专门讨论) 

7、外部接口或第三方平台: 包括其它部门 RPC 开放接口,基础平台,其它公司的 HTTP 接口。

分层对于代码规范是比较重要,决定着以后的代码是否可复用,是否职责清晰,边界清晰。分层其实见仁见智,只要符合团队规范就可以。比如我们之前的团队工程规范:

api层/controller:轻业务逻辑,参数校验,异常兜底。通常这种接口可以轻易更换接口类型,所以业务逻辑必须要轻,甚至不做具体逻辑。该层的领域模型不允许传入DAO层。

Service:业务层,复用性较低,推荐每一个controller方法都得对应一个service,不要把业务编排放在controller中去做。允许操作DO数据领域模型Model

Mannager:高可复用逻辑层。主要是做的是业务逻辑处理和数据组装。允许操作DO数据领域模型Model。

service层之间是否可以相互调用?

这个需要看项目规范,适合业务即可,软件最重要的还是是解决复杂度问题,如果service之间是通过接口依赖、IoC注入和自动事物机制,Service层可以互相调用。

二、领域模型


1、Model, 领域模型对象

  领域模型POJO 一般是 DO/DTO/BO/VO 的统称,即POJO 专指只有 setter / getter / toString 的简单类,一般无业务逻辑代码,包括 DO/DTO/VO/PO 等。

  • DO (Domain Object):主要用于定义与数据库对象应的属性(ORM对象关系映射),实体bean的DO映射成一张表,通过 DAO 层向上传输数据源对象。看项目的编码规约,有的习惯使用命名为XxxEntity, 有的习惯命名为XxxDo, 比如UserEntity或者UserDO           
  • DTO数据传输对象(Data Transfer Object):系统、服务之间交互传输用或者是传输类间数据, Service 或 Manager 向外传输的对象。  看项目的编码规约,比如我们习惯使用DTO来做rest 接口参数或者rpc参数。

  • VO View Object:  视图对象,用于展示层,  前台(APP\\WAP\\PC)展示用;即返回给前端的对象,VO可以仅向前端传输,页面需展示字段,如pageList等。
  • PO(Persistent Object):  持久化对象,就是对象是不是需要通过系列化持久化存储到数据库。 其作用就是项目的编码规约,比如我们把需要持久化保存的对象命名为PO.
  • Entity实体: 也可以用作DO,看项目的编码规约,比如我们使用Entity来做service直接的对象传递。

领域模型的后缀命名也是要结合团队工程规范:比如还有

BO(Business Object)后缀:业务对象。由Service层输出的封装业务逻辑的对象。

Query/Filter/Param后缀:数据查询对象,各层接收上层的查询请求。

Form后缀:表单提交对象

领域模型类里面到底要不要写逻辑,还是只能用最普通的get/set方法。这就是讨论失血模型、贫血模型、充血模型的问题。

2、失血模型

失血模型:domain object只有属性的get set方法的纯数据类,所有的业务逻辑完全由Service层来完成的,由于没有dao,Service直接操作数据库,进行数据持久化。

service:  肿胀的服务逻辑

model:只包含get set方法

显然失血模型service层负担太重,一般不会有这种设计。
 

3、贫血模型

领域模型是指领域对象domain ojbect里只有get和set方法(POJO),所有的业务逻辑都不包含在内而是放在Service层。

service :组合服务,也叫事务服务

model:除包含get set方法,还包含原子服务(如获得关联model的id)

dao:数据持久化

贫血模型比较常见,其问题在于原子服务往往不能直接拿到关联model,因此可以把这个原子服务变成直接用关联modelRepo拿到关联model,这就是充血模型。
 

贫血模型最早广泛应用源于EJB2,最强盛时期则是由Spring创造,将:

  • “行为”(逻辑、过程);

  • “状态”(数据,对应到语言就是对象成员变量)。

分离到不同的对象中:

  • 只有状态的对象就是所谓的“贫血对象”;

  • 只有行为的对象就是,我们常见的N层结构中的Logic/Service/Manager层(对应到EJB2中的Stateless Session Bean)。

——曾经Spring的作者Rod Johnson也承认,Spring不过是在沿袭EJB2时代的“事务脚本”,也就是面向过程编程。

贫血模型和面向对象设计背道而驰。但优点在于简单:

  • 对于只有少量业务逻辑的应用来说,使用起来非常自然;

  • 开发迅速,易于理解;

  • 注意:也不能完全排斥这种方式。

缺点无法良好的应对复杂逻辑。《重构-改善既有代码的设计》提到的坏代码味道之一就是纯数据类的问题,要求数据和行为是在一起,而贫血模型恰恰就是纯数据类的问题呢。

4、充血模型

面向对象设计的本质是:“一个对象是拥有状态和行为的”。

充血模型:绝大多业务逻辑都应该被放在domain object里面,包括持久化逻辑,而Service层是很薄的一层,仅仅封装事务和少量逻辑,不和DAO层打交道。

service :组合服务 也叫事务服务

model:除包含get set方法,还包含原子服务和数据持久化的逻辑

它的优点是面向对象,Business Logic符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑service太过沉重。

充血模型的问题也很明显,当model中包含了数据持久化的逻辑,实例化的时候可能会有很大麻烦,拿到了太多不一定需要的关联model。

如果是数据库表的映射类DO,最好是越简单越好
如果是封装查询条件、查询结果(如dto之类)是可以加一些简单逻辑在里面的。

三、项目顶层代码结构和调用链


1、 项目顶层代码结构

com  
 +- xxxCompany  
     +- myprojectApplication.java (应用启动主类)
     |
     +- myproject  
         |  
         +-common/base //公共/基础相关相关
         |  +-  AppConst.java  
         |  +-  AppContext.java  
         |   
         +-module1
         |  +---controller 控制层
         |  |   +- Userontroller.java
         |  |   
         |  +---model //模型
         |  |   +- domain 实体对象
         |  |   |  +-UserDO.java        
         |  |   |  
         |  |   +- dto 传输对象
         |  |   |  +-UserQueryDTO.java
         |  |   |  
         |  |   +- vo 前端对象
         |  |   |  +-UserProfileVO.java
         |  |   
         |  |   
         |  +---service//业务逻辑层,处理数据逻辑,验证数据
         |  |   +- impl
         |  |   |   +- UserServiceImpl.java          
         |  |   +- UserService.java
         |  |
         |  |
         |  +---dao //数据访问层,与底层 MySQL、 Oracle、 Hbase 等进行数据交互。
         |  |    +- UserDao.java
         |
         +- util//工具包
         |   +- DateUtils.java //Utils后缀 

2、调用链规约

我们项目编程规约,结合swaggger看:

1)controller层接收DTO请求参数 ,并进行简单参数校验。

2)controller层调用了Service层的接口方法。

3)Service层调用Dao层的方法,返回DO的entity对象。

4)Service层封装了前端需要VO对象,返回给controller层

5)controller层返回VO给前端。

四、常用命名原则和规约


规范命名约定目的是为了保持统一,减少沟通成本,提升团队研发效能。通过命名就能体现出代码的特征,含义或者是用途,让阅读者可以根据名称的含义快速厘清程序的脉络。做到见名知意,名副其实。

《Clean Code》这本书明确指出:

    好的代码本身就是注释,我们要尽量规范和美化自己的代码来减少不必要的注释。

    若编程语言足够有表达力,就不需要注释,尽量通过代码来阐述。

举个例子:

去掉下面复杂的注释,只需要创建一个与注释所言同一事物的函数即可

// check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))

应替换为

if (employee.isEligibleForFullBenefits())
 

1、首先遵循一定的原则:

好的命名风格应该是看到变量或者函数名字就能“望文生义”,做到名副其实。毕竟我们不能把自己写的所有代码都做注释。好的命名是不需要注释来补充的,达到代码自解释。

1)、编码规范统一:

在编写一个子模块或派生类的时候,要遵循其基类或整体模块的命名风格,保持命名风格在整个模块中的同一性。如骆驼命名法,大括号位置等。

2)、命名一致性原则:

    命名一致性:如booleam变量,前缀最好是is、can,need。

函数取名最忌讳"名不副实"

    比如一个 getXXX 的函数,结果里面还做了 add, update 的操作。对问题排查造成很大的困扰。因此命名一定要用实质内容相符。不论是类名,变量名,方法名都要有实际的意。   建议方法:先查查字典,找个通俗易懂而且比较贴近的名字。可以参考 jdk 的命名、通用词汇和行业词汇; 作用域小的采用短命名,作用域大的采用长命名。

  再比如有个Cache类,里面有个函数判断key是否过期:

public boolean isExpired(String key)

        // 当前时间戳

        long curTimestamp = DateUtils.nowUnixTime();

        // 获取key的存入时间戳

        long storeTimestamp = getStoreTimestamp(key);

        

        if (curTimestamp - storeTimestamp > MAX_EXPIRE_SECONDS)

            // 注意这个地方的delete是个隐藏逻辑

            delete(key);

            return true;

        

        return false;

 

  上面这个函数从函数字面意思看是判断key是否过期,但是!!它居然在函数里面隐藏了一段特殊逻辑:如果过期则删除掉key。这个就是典型的"名不副实",这个是最忌讳的,会给后续的开发人员留下"巨坑"。

  有两种方式去优化这段代码:

  • 方式一:将隐藏逻辑去掉

public boolean isExpired(String key)

        // 当前时间戳

        long curTimestamp = DateUtils.nowUnixTime();

        // 获取key的存入时间戳

        long storeTimestamp = getStoreTimestamp(key);

        

        if (curTimestamp - storeTimestamp > MAX_EXPIRE_SECONDS)

            return true;

        

        return false;

 

  • 方式二:改变函数名字

public int deleteIfExpired(String key)

        // 当前时间戳

        long curTimestamp = DateUtils.nowUnixTime();

        // 获取key的存入时间戳

        long storeTimestamp = getStoreTimestamp(key);

        

        if (curTimestamp - storeTimestamp > MAX_EXPIRE_SECONDS)

            return delete(key);

        

        return 0;

 

3)、名字标识符组成:动词+名词

1、名字标识符采用英文单词,应当直观且可以拼读,可望文知意,用词应当准确。正确的英文拼写和语法可以让阅读者易于理解,避免歧义。

2、杜绝完全不规范的英文缩写,避免望文不知义。如Function“缩写”成 Fu,此类随意缩写严重降低了代码的可阅读性。

4、为了达到代码自解释的目标,任何自定义编程元素在命名时,使用完整的单词组合来表达。
正例:在 JDK 中,对某个对象引用的 volatile 字段进行原子更新的类名为:AtomicReferenceFieldUpdater。

4、只要命名合理,不要担心方法名称太长

首先需要保证命名有意义,只要命名合理,不要担心方法名称太长,但方法名称过长常常又意味着该方法干的事太多了,则需要思考是否可以拆分方法,这也反映了"职责单一"设计原则。

保证命名有意义的前提之下,尽量保证命名的简短,删除一些不影响表达的单词,或者采用缩写。举几个例子:

  1. ActivityRuleRepository.findActivityRuleById() 可以简写成ActivityRuleRepository.findById(),因为上下文已经说明白了这个一个查询活动规则的Repository接口。
  2. void updateRuleForRevision(String ruleString) 简写成void updateRule4Revision(String ruleStr)
  3. ActivityRule convert2ActivityRule(String ruleStr) 借鉴toString的简写方式,简写成ActivityRule toActivityRule(String ruleStr)

3)最小化长度 && 最大化信息量原则

在足够描述用途的前提下,尽量以最小词汇量去描述事物,如staff就company_person_collection要简捷易记。

也可采用有广泛共识的缩写后缀,如msg,idx,cnt,btn,id ,flg等,如果缩写共识度不高,请在取得同事们共识后用注释说明其含义。

变量/函数长度控制在4~18个字符内,有助于对代码的理解。

过长的变量:howLongDoesItTakeToOpenTheDoor, howBigIsTheMaterial…

简捷的变量:timeToOpenTheDoor, materialSize.

4)避免过于相似,也不要用双关语,避免歧义,比如add和append:

不要出现仅靠大小写区分的相似的标识符,例如“i”与“I”,“function”与“Function”等等。

正确命名具有互斥意义的标识符

用正确的反义词组命名具有互斥意义的标识符 ,如

add / remove       begin / end        create / destroy

insert / delete       first / last         get / set

increment / decrement                 put / get

add / delete         lock / unlock      open / close

min / max          old / new         start / stop

next / previous      source / target     show / hide

send / receive       source / destination

cut / paste          up / down

这些有助于理解成对的变量/函数的意义.

尽量避免名字中出现数字编号

尽量避免名字中出现数字编号,如value1,value2等,除非逻辑上的确需要编号。

5)少使用类型前缀

最好从名字上就能揣测出其类型。加后缀说明是可以的。

少单独使用含义广泛的词。如data,info,value等。

6)避免过度使用get作为方法前缀

应该用更精确的动词描述动作,如“请求”request,“获取”acquire,“查找”search/lookfor/find,“查询”inquire,“构建”build 或“创建”create, 执行某个动作如执行查询doGet

get和set和成对出现,是轻量的实现。

get这种方法命名一定是明确index,性能比较好,

query选择选择符合的。

  1. 找到数据:find/lookfor,肯定有数据。
  2. 搜索数据:search、搜索数据可能不存在。
  3. 查询数据:query 强调查询这个动作,返回的数据是比较原始。query返回的是List<object>,find返回的才是List<Record>。

2.常见类名命名规范:

1、类名通常以名词结尾。而且在类名中要体现它是以保存数据为主还是提供功能为主。例如 ObjectBuilder 这个类我们都可以猜到它的主要功能是创建Object对象,

2、以动词-er/or 结尾的类名,至少应该包含一个以该动词开头的方法。例如 ObjectBuilder 这个类,它至少应该包含一个以 build- 开头的方法。有了这种规约,阅读者就能更方便地理解这个类。

前缀名

意义

举例

Abstract 或者 Base 开头抽象类BaseUserService

后缀名

意义

举例

Controller

对外接口类

UserController

Service

服务类,里面包含了给其他类提同业务服务的方法

UserService

Impl

实现类,而不是接口

UserServiceImpl

Manager

通用业务处理层

UserManager

Ixxx

接口

IUserDao

Dao

数据访问方法

OrderDao

Listener

响应某种事件的类

PaymentSuccessListener

Event

这个类代表了某种事件

PaymentSuccessEvent

Factory

生成某种对象工厂的类

PaymentOrderFactory

Adapter

用来连接某种以前不被支持的对象的类

DatabaseLogAdapter

Job

某种按时间运行的任务

PaymentOrderCancelJob

Wrapper

这是一个包装类,为了给某个类提供没有的能力

SelectableOrderListWrapper

DO

定义与数据库对象应的属性(ORM对象关系映射

UserDO

DTO

DTO数据传输对象

UserDTO

VO

用于展示层,  前台(APP\\WAP\\PC)展示用

UserVO

Entity

实体

属性

约束

举例

设计模式相关类Builder,Factory等当使用到设计模式时,需要使用对应的设计模式作为后缀,如ThreadFactory
Util类一般是无状态的,只包含静态方法。使用时无需创建类的实例。
Helper类可以有状态(类的成员变量),一般需要创建实例才能使用。

POJO 是 DO / DTO / BO / VO 的统称,禁止命名成 xxxPOJO。

接口管理:XXXManager 线程相关:XXXExecutor 初始化相关:XXXInitializer 处理相关:XXXHandler 监听器:XXXListener

3.常见方法命名规范:

1、和类名不同的是,方法命名一般为动词或动词短语,与参数或参数名共同组成动宾短语,即动词 + 名词。一个好的函数名一般能通过名字直接获知该函数实现什么样的功能。

2、用具体的名字代替抽象的名字。比如:ServiceCanStart() 与 CanListenOnPort()

检测服务端口是否可以开始监听,明显后一个要更好一些。

3、首先需要保证命名有意义,只要命名合理,不要担心方法名称太长,但方法名称过长常常又意味着该方法干的事太多了,则需要思考是否可以拆分方法,这也反映了"职责单一"设计原则。

保证命名有意义的前提之下,尽量保证命名的简短,删除一些不影响表达的单词,或者采用缩写。举几个例子:

  1. UserDao.findUserById() 可以简写成UserDao.findById(),因为上下文已经说明白了这个一个查询用户的Dao接口。
  2. void updateUserForName(String name) 简写成void updateForName(String name)
  3. User  convertToUserModel(String uid) 借鉴toString的简写方式,简写成ttoUserModel(String ruleStr)

4、如add、insert、append等词都有类似的意思,在使用时最好准确,而且统一。如字符串连接应该用append,而不是add。

可以借鉴spring的方法命名规则:

1、getBean:轻量实现,调用doGetBean。

2、doGetBean:先判断缓存,缓存没有则调用createBean生成。

      String beanName = this.transformedBeanName(name);

      Object sharedInstance = this.getSingleton(beanName);

      this.createBean(beanName, mbd, args);

3、createBean:校验bean的合法性,然后调用doCreateBean真正创建。

    

4、doCreateBean:真正创建bean。

1) 各层命名规约: Service / DAO 层方法命名规约:
  1. 获取单个对象的方法用 get 做前缀。
  2. 获取多个对象的方法用 list 做前缀,复数结尾,如:listObjects
  3. 获取统计值的方法用 count 做前缀。
  4. 插入的方法用 save / insert 做前缀。
  5. 删除的方法用 remove / delete 做前缀。
  6. 修改的方法用 update 做前缀。
  7. 取出数据:fetch
  8. 找到数据:find,肯定有数据。
  9. 搜索数据:search、搜索数据可能不存在。
  10. 查询数据:query 强调查询这个动作,返回的数据是比较原始。query返回的是List<object>,find返回的才是List<Record>。

1) 返回真伪值的方法

单词位置意义例子
is前缀对象是否符合期待的状态isValid
can前缀 对象能否执行所期待的动作canRemove
has前缀对象是否持有所期待的数据和属性hasObservers
need前缀调用方是否需要执行某个命令或方法needMigrate
should前缀是否应当执行操作shouldCreate

2) 用来检查的方法

单词位置意义例子
ensure前缀检查是否为期待的状态,不是则抛出异常或返回error codeensureCapacity
validate前缀 检查是否为正确的状态,不是则抛出异常或返回error codevalidateInputs

3)、按需求才执行的方法

单词位置意义例子
try前缀尝试执行,失败时抛出异常或是返回errorcode    tryCreatetryCreate
OrDefault后缀 尝试执行,失败时返回默认值getOrDefault
OrElse后缀尝试执行、失败时返回实际参数中指定的值getOrElse

4) 异步相关方法命名

单词位置意义例子
blocking前缀线程阻塞方法blockingGetUser
Async/Sync后缀异步方法sendAsync

异步相关方

单词位置意义例子
schedule前缀Job和Task放入队列schedule, scheduleJob
execute前缀执行异步方法 execute,executeTask
start/stop/cancel前缀启动/停止/取消/异步任务startJob

4.5 回调方法

单词位置意义例子
on前缀事件发生时执行onCompleted
before前缀事件发生前执行beforeUpdate
after前缀事件发生后执行afterUpdate

4.6 操作对象生命周期的方法

单词位置意义例子
initialize前缀初始化。也可作为延迟初始化使用initialize
pause前缀/后缀暂停onPause ,pause
stop前缀/后缀事件发生后执行onStop,stop
destroy前缀销毁destroy

4.6 执行

单词位置意义例子
do前缀强调真正执行某个动作,和其他动词一块使用

doGet,doCreate,doDispatch

doExecute

perform前缀实施执行较复杂逻辑,一般单独使用perform
execute前缀执行某个调用,后面跟着名词executeTask

4.7 与集合操作相关的方法:

集合的容量通常用capacity、集合实际元素个数用size、字符串长度用length,不要用size去形如字符串的长度。

单词位置意义例子
add前缀添加addJob
insert前缀插入到下标ninsertJob
append前缀附加信息到当前对象的末尾appendJob
put前缀添加与key对应的元素putJob
remove前缀移除元素 removeJob
push前缀添加到栈头pushJob
pop前缀从栈头取出并移除popJob
peek前缀从栈头取出但不移除peekJob
find前缀寻找符合条件的某物findById
contains是否持有与指定对象相同的对象contains

   

4.7 助词/介词
 

单词位置意义例子
by中间靠、通过getByName

for中间为某物做了什么setDataForVm
with中间“和”、带有的意思,如with sb.startWithA():A开头的单词
Of使用Of串联多个名词,使用形容词修饰名词
in

4.8 与数据相关的方法

获取/读取/查找/查询:get、fetch、acquire、read、search、find、query
create:新创建    createAccount
from:从既有的某物新建,或是从其他的数据新建    fromConfig
to:转换    toString
update:更新既有某物    updateAccount
load: 读取    loadAccount
fetch:远程读取    fetchAccount
delete: 删除    deleteAccount
remove:删除    removeAccount
save:保存    saveAccount
store:保存    storeAccount
commit:保存    commitChange
apply: 保存或应用    applyChange
clear:清除数据或是恢复到初始状态    clearAll
reset:清除数据或是恢复到初始状态    resetAll

4.9 成对出现的动词
get获取    set 设置
add 增加    remove 删除
create 创建    destory 移除
start 启动    stop 停止
open 打开    close 关闭
read 读取    write 写入
load 载入    save 保存
create 创建    destroy 销毁
begin 开始    end 结束
backup 备份    restore 恢复
import 导入    export 导出
split 分割    merge 合并
inject 注入    extract 提取
attach 附着    detach 脱离
bind 绑定    separate 分离
view 查看    browse 浏览
edit 编辑    modify 修改
select 选取    mark 标记
copy 复制    paste 粘贴
undo 撤销    redo 重做
insert 插入    delete 移除
add 加入    append 添加
clean 清理    clear 清除
index 索引    sort 排序
find 查找    search 搜索
increase 增加    decrease 减少
play 播放    pause 暂停
launch 启动    run 运行
compile 编译    execute 执行
debug 调试    trace 跟踪
observe 观察    listen 监听
build 构建    publish 发布
input 输入    output 输出
encode 编码    decode 解码
encrypt 加密    decrypt 解密
compress 压缩    decompress 解压缩
pack 打包    unpack 解包
parse 解析    emit 生成
connect 连接    disconnect 断开
send 发送    receive 接收
download 下载    upload 上传
refresh 刷新    synchronize 同步
update 更新    revert 复原
lock 锁定    unlock 解锁
check out 签出    check in 签入
submit 提交    commit 交付
push 推    pull 拉
expand 展开    collapse 折叠
begin 起始    end 结束
start 开始    finish 完成
enter 进入    exit 退出
abort 放弃    quit 离开
obsolete 废弃    depreciate 废旧
collect 收集    aggregate 聚集

4.10其他常用词汇

application 应用程式 应用、应用程序
application framework 应用程式框架、应用框架 应用程序框架
architecture 架构、系统架构 体系结构
argument 引数(传给函式的值)。叁见 parameter 叁数、实质叁数、实叁、自变量
array 阵列 数组
assign 指派、指定、设值、赋值 赋值
assignment 指派、指定 赋值、分配
attribute 属性 属性、特性
batch 批次(意思是整批作业) 批处理
binding 系结 绑定
build 建造、构筑、建置(MS 用语)
build-in 内建 内置
business 商务,业务 业务
callback 回呼 回调
chain 串链(例 chain of function calls) 链
checked exception 可控式异常(Java)
cleanup 清理、善后 清理、清除
client 客端、客户端、客户 客户
client-server 主从架构 客户/服务器
container 容器 容器 ###### (存放资料的某种结构如 list, vector…)
context 背景关系、周遭环境、上下脉络 环境、上下文
control 控制元件、控件 控件


define 定义 预定义
definition 定义、定义区、定义式 定义
delegate 委派、委托、委任 委托

derived class 衍生类别 派生类
design by contract 契约式设计
design pattern 设计范式、设计样式 设计模式 ※ 最近我比较喜欢「设计范式」一词

driver 驱动程式 驱动(程序)
dynamic binding 动态系结 动态绑定
escape code 转义码 转义码
evaluate 评估、求值、核定 评估
event 事件 事件
event driven 事件驱动的 事件驱动的
exception 异常情况 异常
exception declaration 异常宣告(ref. C++ Primer 3/e, 11.3) 异常声明
exception handling 异常处理、异常处理机制 异常处理、异常处理机制
exception specification 异常规格(ref. C++ Primer 3/e, 11.4) 异常规范
exit 退离(指离开函式时的那一个执行点) 退出
explicit 明白的、明显的、显式 显式
export 汇出 引出、导出
expression 运算式、算式 表达式
facility 设施、设备 设施、设备
feature 特性
field 栏位,资料栏(Java) 字段, 值域(Java)
flush 清理、扫清 刷新
font 字型 字体

formal parameter 形式叁数 形式叁数
framework 框架 框架

generic algorithm 泛型演算法 通用算法
getter (相对於 setter) 取值函式
global 全域的(对应於 local) 全局的
global object 全域物件 全局对象
global scope resolution operator 全域生存空间(范围决议)运算子 :: 全局范围解析操作符
group 群组

handle 识别码、识别号、号码牌、权柄 句柄
handler 处理常式 处理函数
heap 堆积 堆

hook 挂钩 钩子

inheritance 继承、继承机制 继承、继承机制
inline 行内 内联
inline expansion 行内展开 内联展开
initialization 初始化(动作) 初始化
initialization list 初值列 初始值列表
initialize 初始化 初始化

invoke 唤起 调用

call: 比较明确的调用 (方法名,形参,返回值都是确定的)
invoke: 调用的对象,方法名,参数,返回值都不确定,比较上层建筑的代码常用。
e.g jdk生成动态代理,设计动态代理类是上层建筑代码,负责生成 接口的对象,对象中的所有方法都是调用 invoke方法,来让目标对象做工作。
让哪个目标对象?, 执行那个方法(Method类),方法传参(args)都是未知不确定的,所以用invoke 祈求(本身祈求就是很虚的东西呀),更加符合当前代码的抽象场景

iterate 迭代(回圈一个轮回一个轮回地进行) 迭代


load 载入 装载
loader 载入器 装载器、载入器
local 区域的(对应於 global) 局部的
local object 区域物件 局部对象
lock 机锁
loop 回圈 循环
lvalue 左值 左值
macro 巨集 宏
magic number 魔术数字 魔法数

member 成员 成员

message 讯息 消息

multi-tasking 多工 多任务

postfix 后置式、后序式 后置式

prefix 前置式、前序式 前置式
preprocessor 前处理器 预处理器


schedule 排程 调度
scheduler 排程器 调度程序
scheme 结构纲目、组织纲目

4. 常见变量名命名规范:

命名原则1:名词、名字组合或者形容词

变量一般情况下建议使用名词、名字组合或者形容词,因为变量一般形容的是一种事物或者事物的属性,所以用名词或者名词组合更容易让人理解。

命名原则2:变量命名前后用词需统一

  在同一个工程或者一个场景下,变量命名风格需前后统一,比如total和sum都能表示总计的意思,那么所有需要用到"总计"含义的地方要么全部使用total、要么全部使用sum。

1、在常量与变量命名时,表示类型的名词放在词尾,以提升辨识度。

正例: startTime / workQueue / nameList / TERMINATED_THREAD_COUNT 反例: startedAt / QueueOfWork / listName / COUNT_TERMINATED_THREAD
在一个方法中将返回值命名为 result,能够让方法的脉络更清晰:userListResult   2、【强制】 POJO 类中的任何布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误。
说明: 本文 MySQL 规约中的建表约定第 1 条,表达是与否的变量采用 is_xxx 的命名方式,所以需要在<resultMap>设置从 is_xxx 到 xxx 的映射关系。 反例: 义为基本数据类型 Boolean isDeleted 的属性,它的方法也是 isDeleted(),框架在反向解析时,“误以为 ”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。

3、常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。

4、集合变量用类型或者复数s作为后缀

  在java中,有很多集合,比如List、Map、Set等,那么集合变量该怎么命名呢?

  一般可采取两种方式:

  • 使用复数s结尾

List<Student> students = new ArrayList<>();

  • 用集合类型作为后缀

List<Student> studentList = new ArrayList<>();

  上面两种方式均可,没有比较明显的偏好,根据实际场景决定。第一种方式相对更简洁,第二种在局部作用域里面有多种相关的集合变量时区分度更大,比如:

List<Student> studentList = new ArrayList<>();

Map<Long, Student> studentMap = Maps.newHashMap();

for (Student stu : studentList)

  studentMap.put(stu.getId, stu);

  建议是

         如果局部作用域只有一种类型的集合,那么推荐使用复数形式;

        如果局部作用域有多个相关的集合类型,那么推荐用类型结尾。

变量命名约定俗称的缩写:

全称缩写
identificationid
averageavg
maximummax
minimummin
bufferbuf
errorerr
messagemsg
imageimg
lengthlen
librarylib
passwordpwd
positionpos
data transfer objectdto
view objectvo

7)抛弃掉flag变量

5、mybatisplus的Iservice规范命名例子:

/**
 * 顶级 Service
 *
 * @author hubin
 * @since 2018-06-23
 */
public interface IService<T> 

    /**
     * 插入一条记录(选择字段,策略插入)
     *
     * @param entity 实体对象
     */
    boolean save(T entity);

    /**
     * 插入(批量)
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean saveBatch(Collection<T> entityList) 
        return saveBatch(entityList, 1000);
    

    /**
     * 插入(批量)
     *
     * @param entityList 实体对

以上是关于架构师技能1:Java工程规范浅析领域模型VODTODOPO优秀命名的主要内容,如果未能解决你的问题,请参考以下文章

阿里P8架构师谈:java程序员到架构师,需突破的7大必备技能!

十年java架构师分享的一些干货,成为架构师的必备技能

架构设计(15):Java顶层工程结构规范和浅析VODTODOPO

架构设计(15):Java顶层工程结构规范和浅析VODTODOPO

[架构之路-3]:架构师 - 软件架构师也是魔法师,架构师应具备的四大方面的技能

[架构之路-97]:《软件架构设计:程序员向架构师转型必备》-7-需求分析与业务需求领域建模