版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
文档版本:DOCPROPERTY文档版本2018-09-25DOCPROPERTY商标XXXXXX局社会共治服务平台建设项目详细设计说明书XXXXXX有限公司XXXXXXXXXXXX局社会共治服务平台建设项目-详细设计说明书文档基本信息文件状态:[]草稿[√]正式发布[]正在修改文件标识:XXXXXXXXXXXX局社会共治服务平台建设项目-详细设计说明书当前版本:V1.0作者:张三完成日期:2022年11月修订记录版本号作者参与者日期修改说明V0.5张三/2022年11月创建文档V0.6张三/2022年11月补充接口设计V0.7张三/2022年11月调整文档目录结构,统一图片备注。V0.8张三/2022年11月补充输入输出、用户界面设计V1.0张三/2022年11月统一调整文档格式目录TOC\o"1-4"\f\u1.引言 社会共治服务平台建设项目详细设计说明书名称缩写:详细设计说明书文档概述本文档是以项目建设目标和内容以及需求规格说明书、概要设计说明书为依据,以文档的方式阐述本项目各系统模块的详细设计内容,拟达到如下2个主要目的:确保本文档的设计内容符合项目建设目标与内容,以及满足用户的真实需求。确保本文档能作为开发人员进行系统编码的依据。本文档的读者主要分为两个主要类别:一类是项目相关参与人,作为系统的使用者、需求的提出者,通过本文档能够明确产品开发的目标以及能够达到的程度;另一类是项目技术实施的相关人员,通过本文档能够指导编码人员进行系统编码,指导测试人员进行单元测试。修改约束该文档在正式发布后,其更新需要甲乙双方共同确认。参考资料《XXXXXXXXXXXX局社会共治服务平台建设项目需求规格说明书》《XXXXXXXXXXXX局社会共治服务平台建设项目概要设计说明书》设计概述背景介绍党的十九大报告指出,打造共建共治共享的社会治理格局,是中国特色社会主义进入新时代的客观要求。市场监管是社会治理的重要组成部分。商事制度改革后,市场主体保持高增长态势,新技术、新业态、新模式持续涌现,市场监管的难度和复杂性不断提升,传统政府大包大揽模式已无法适应监管的现实需求。以科技赋能市场监管现代化成为为发展主线,营造良好科技创新生态,加快构建市场监管科技创新体系,推动社会共治是共治理念的新发展。项目背景进入新时代,应对机构改革后“一支队伍管市场”的新挑战,从单一的部门监管走向多元参与的社会共治,回应人民群众对美好生活的新期待,是新形势下市场监管的大方向。为应对这一变化,XXXXXX市场监管局提出建设社会共治服务平台,推进XXXXXX市场监管共治体系建设。项目目标转变市场秩序及市场安全监管治理理念,从政府“单打独斗”向“社会共治”转变,从“事后救火”向“事前预警”转变,通过市场监管社会共治平台建设,为通用市场监管领域共治场景提供统一共治监管应用,为个性共治场景提供统一规范能力支撑,压实市场主体责任,引导行业自律,提升主体自治水平,充分发挥公众监督作用,优先实现食品生产、流通、餐饮、电梯场景社会共治模式。推动构建“政府主导、市场主体自治、行业自律、社会监督”的社会共治格局。1、鼓励企业自证合规,推动构建自治自律的社会共治格局压实市场主体责任,引导行业自律,提升主体自治水平,推动构建“政府主导、市场主体自治、行业自律、社会监督”的社会共治格局。2、提升社会监督能力,促进企业良性发展创建消费者、社会公众的监督渠道,通过“他证合规,投诉评价”促进社会监督,树立好企业的口碑。3、建立自治、共治体系,推动市场监管理念转变转变市场秩序及市场安全监管治理理念,从政府“单打独斗”向“社会共治”转变,从“事后救火”向“事前预警”转变,通过市场监管社会共治平台建设,为通用共治场景提供统一共治监管应用,为个性共治场景提供统一能力支撑。通过构建监管线索反哺日常监管和各类专项监管。4、形成一套符合云南市场监管工作实际的共治模式机制保障。建立一套标准规范,形成共治监管机制。系统架构使用图系统架构图技术架构使用图技术架构图部署架构使用图部署架构图系统环境序号系统名称用途数量硬件环境软件环境网络环境1自证合规应用前端应用服务器1云主机:CPU:8核;内存:16G;系统盘:100G;数据盘:200G;系统版本:CentOS7.564位Nginx1.24.0互联网区2后台应用服务器1云主机:CPU:8核;内存:16G;系统盘:100G;数据盘:200G;系统版本:CentOS7.564位;Jdk1.8政务外网区3数据库服务器1云主机:CPU:8核;内存:16G;存储空间:500G系统版本:CentOS7.564位MySQL5.7互联网区出错处理设计出错输出信息错误码错误类型错误字符描述Err_cfg_info事先没有配置系统系统提示用户让管理员创建配置文档Err_debug_info调用外部模型系统出错系统提示用户检查调用地址和参数Err_doc_info引用的配置文档改变或者删除系统提示用户配置文档已改变或删除Err_performent_info系统运行出错系统提示出错,并给出错误编号和说明Err_submit_info没有填写要求的必要信息而提交对于保存操作,使用域校验公式,或者检查是否填写完整;400业务异常业务异常,消息不能读取,缺少必要的请求参数,请求参数类型错误,请求参数绑定错误,参数校验失败401请求未授权客户端请求未授权404请求地址错误404没找到请求405请求方法错误不支持当前请求方法415媒体类型错误不支持当前媒体类型500服务器异常服务器异常出错处理策略故障出现后可能采取的变通措施,包括:1)后备技术说明准备采用的后备技术,当原始系统数据万一丢失时启用的副本的建立和启动的技术,例如周期性地把磁盘信息记录到磁带上去就是对于磁盘媒体的一种后备技术。2)降效技术说明准备采用的后备技术,使用另一个效率稍低的系统或方法来求得所需结果的某些部分,例如一个自动系统的降效技术可以是手工操作和数据的人工记录。3)恢复及再启动技术说明将使用的恢复再启动技术,使软件从故障点恢复执行或使软件从头开始重新运行的方法。出错处理过程系统关键事务将由系统进行事务管理,关键事务如果出错将返回到系统最近完好状态,保证数据安全,不被污染。系统某个实例出现故障,此实例将被锁定,以利于排查问题;但系统其他应用实例将不受影响可以继续工作。质量属性设计高可用性要求系统提供7×24小时的连续运行能力,数据存取服务准确,不能丢失数据。系统具备冗余和容错能力,避免出现系统死锁、资源耗尽、程序崩溃等故障,具备自动纠错和异常报警功能。可扩展性要求系统设计采用分布式数据库技术,支持自动化水平拆分、平滑扩容、弹性扩展、透明读写分离、分布式事务、具备分布式数据库全生命周期的运维管控能力,确保数据层的可扩展性。系统设计采用分布式服务框架和松耦合设计,支持微应用、服务治理和容量线性扩展,在业务持续增长的情况下保障业务平稳运行。系统设计采用组件化、迭代化的开发模式,基于微应用构建通用服务中心,支持快速搭建应用。性能要求社会共治门户提供良好的页面设计与功能交互,在网络稳定的环境下,业务专网业务应用操作界面简单操作的响应时间小于5秒,互联网业务应用操作界面简单操作的响应时间小于5秒;可恢复性要求具备事务回滚功能,可将错误数据恢复到正确节点,而不影响其他数据。接口支持断点续传,与周边系统数据交互出现异常时自动补传和数据校验,确保数据完整性和一致性。具备成熟的灾难恢复功能,提供多种级别的数据及应用备份能力。兼容性要求系统兼容各种版本的主流浏览器,包括IE10+、FireFox、Chrome等常见浏览器,客户端支持常用终端设备PC(Windows)、手机和平板(Android)等。整体需求功能列表编号建设版块一级功能二级功能功能说明1社会共治服务门户企业端门户注册登录提供企业主体用户注册及登录功能,支持用户注册、登录、绑定操作。提供统一的用户登陆界面,支持电子营业执照认证、法人实名认证,事业单位,外资企业认证、连锁企业认证。2主体查询提供企业相关信息检索查询功能,具体包含企业主体信息、行政信息、阳光公示信息。支持查看企业画像信息。3通知公告提供通知公告、风险预警、政策法规等公告信息的查阅。4共治专区对市场监管社会共治应用专区介绍,如食品安全、特种设备、药品安全、重要工业产品、质量安全、知识产权,提供相关的功能介绍。5信息填报意见征集、问卷调查、企业表单等不同类型表单的填报。6企业中心提供共治消息查看、信息反馈、企业基本信息自主维护管理,作为企业自证合规应用入口,可以进入到人员管理、主体责任落实、服务能力管理、客体管理等功能。关键技术基于分布式计算技术(1)分布式文件系统提供一个海量的、可靠的、可扩展的数据存储服务,将集群中各个节点的存储能力聚集起来,并能够自动屏蔽软硬件故障,为用户提供不间断的数据访问服务。支持增量扩容和数据的自动平衡,支持随机读写和追加写的操作。(2)任务调度为集群系统中的任务提供调度服务,同时支持强调响应速度的在线服务和强调处理数据吞吐量的离线任务。自动检测系统中故障和热点,通过错误重试、针对长尾作业并发备份作业等方式,保证作业稳定可靠地完成。(3)集群监控和部署对集群的状态和上层应用服务的运行状态和性能指标进行监控,对异常事件产生警报和记录;为运维人员提供整个基础计算平台以及上层应用的部署和配置管理,支持在线集群扩容、缩容和应用服务的在线升级。(4)分布式系统底层服务提供分布式环境下所需要的协调服务、远程过程调用、安全管理和资源管理的服务。这些底层服务为上层的分布式文件系统、任务调度等模块提供支持。基于云技术的计算和存储狭义云计算是指IT基础设施的交付和使用模式,指通过网络以按需、易扩展的方式获得所需的资源;广义云计算是指服务的交付和使用模式,指通过网络以按需、易扩展的方式获得所需的服务。这种服务可以是IT和软件、互联网相关的,也可以是任意其他的服务,它具有超大规模、虚拟化、可靠安全等独特功效。云技术具有以下特点:(1)数据安全可靠云计算提供了最可靠、最安全的数据存储中心,用户不用再担心数据丢失、病毒入侵等麻烦。严格的权限管理策略可以帮助你放心地与你指定的人共享数据。(2)客户端需求低其次,云计算对用户端的设备要求最低,使用起来也最方便。(3)轻松共享数据云计算可以轻松实现不同设备间的数据与应用共享。(4)可能无限多云计算为使用网络提供了几乎无限多的可能。为存储和管理数据提供了几乎无限多的空间,也为完成各类应用提供了几乎无限强大的计算能力。微服务架构服务架构采用一组服务的方式来构建一个应用,服务独立部署在不同的进程中,不同服务通过一些轻量级交互机制来通信,例如RPC、HTTP等,服务可独立扩展伸缩,每个服务定义了明确的边界,不同的服务甚至可以采用不同的编程语言来实现,由独立的团队来维护,具备如下几个特征:(1)通过服务实现组件化传统实现组件的方式是通过库(library),传统组件是和应用一起运行在进程中,组件的局部变化意味着整个应用的重新部署。通过服务来实现组件,意味着将应用拆散为一系列的服务运行在不同的进程中,那么单一服务的局部变化只需重新部署对应的服务进程。另外将服务作为组件可以更明确的定义出组件的边界,因为服务之间的调用是跨进程的,清晰的边界和职责定义是设计时必须考虑的。(2)按业务能力来划分服务与组织团队传统开发方式中,我们将工程师按技能专长分层为前端层、中间层、数据层,前端对应的角色为UI、页面构建师等,中间层对应的角色为服务端业务开发工程师,数据层对应着DBA等角色。事实上传统应用设计架构的分层结构正反应了不同角色的沟通结构。而微服务架构的开发模式不同于传统方式,它将应用按业务能力来划分为不同的服务,每个服务都要求在对应业务领域的全栈(从前端到后端)软件实现,从界面到数据存储到外部沟通协作等等。因此团队的组织是跨功能的,包含实现业务所需的全面的技能。近年兴起的全栈工程师正是因为架构和开发模式的转变而出现,当然具备全栈的工程师其实很少,但将不同领域的工程师组织为一个全栈的团队就容易的多。(3)服务即产品传统的应用开发都是基于项目模式的,开发团队根据一堆功能列表开发出一个软件应用并交付给客户后,该软件应用就进入维护模式,由另一个维护团队负责,开发团队的职责结束。而微服务架构的倡导者提议避免采用这种项目模式,更倾向于让开发团队负责整个产品的全部生命周期。(4)智能终端与哑管道微服务架构抛弃了ESB过度复杂的业务规则编排、消息路由等。服务作为智能终端,所有的业务智能逻辑在服务内部处理,而服务间的通信尽可能的轻量化,不添加任何额外的业务规则。(5)去中心统一化传统应用中倾向采用统一的技术平台或产品来解决所有问题。不是每个问题都是钉子,也不是每个解决方案都是一个锤子。问题有其具体性,解决方案也应有其针对性。用最适合的技术方案去解决具体的问题,在大一统的传统应用中其实很难做到,而微服务的架构意味着,你可以针对不同的业务服务特征选择不同的技术平台或产品,有针对性的解决具体的业务问题。(6)基础设施自动化单一进程的传统应用被拆分为一系列的多进程服务后,意味着开发、调试、测试、集成、监控和发布的复杂度都会相应增大。必须要有合适的自动化基础设施来支持微服务架构模式,否则开发、运维成本将大大增加。(7)Designforfailure正因为将服务独立在不同的进程中后,引入了额外的失败因素。任何时刻对服务的调用都可能因为服务方不可用导致失败,这就要求服务的消费方需要优雅的处理此类错误。这其实是相对传统应用开发方式的一个缺点,不过随着一些开源服务化框架的出现,对业务开发人员而言适当的屏蔽了类似的错误处理,不过开发人员依然需要知道对服务的调用是完全不同于进程内的方法或函数调用的。(8)进化设计一旦采用了微服务架构模式,那么在服务需要变更时我们要特别小心,服务提供者的变更可能引发服务消费者的兼容性破坏,时刻谨记保持服务契约(接口)的兼容性。业界流行的阿里的框架dubbo以及淘宝内部的HSF,Navi-rpc都可以看做微服务化框架的雏形,加上服务治理中心的管理、基础交付设施的保障就可以构成完整的一套微服务框架。整体架构如下图,他由服务发布者、调用者和治理中心三者组成,属于标准的协调者模式。微服务整体框架生产者中服务逻辑在Spring或者Guice等IoC框架的bean中,由IoC容器托管,为了符合模块即服务的思想,在框架层级实现了一套可插拔组件的引擎,去实现组件的扫描,需要暴露服务的发布出来,依赖别的服务的,通过字节码技术生成Rpc调用代理Stub,形成了一个基于组件的容器,通过JSR315这个规范的SPI实现对接到J2EE容器,下面的消费者结构相同。在服务启动后,首先会第一步注册自己到服务治理中心,上传自己的契约、版本上去,治理中心如果通过检查就发布出去,之后和治理中心通过长连接协议(我们采用websocket,因为现成、简单)做一个订阅发布的通道,可以供收集状态,推送服务Endpint的变更;服务消费者可以去治理中心或者Maven仓库获取契约、SDK,治理中心推送Endpoint下来,供路由进行Rpc调用,通过消费者也通过长连接协议来进行状态和统计信息的上报,供治理中心进行分析决策和反馈。服务治理中心为了保证高可用性,通常使用Zookeeper这个流行的开源的基于Paxos的方案,当然最近渐渐流行起来的kebernetes的etcd是基于Raft的集群共享数据、也可以做服务的发现的解决方案。随着这种分布式调用越来越频繁,就需要服务治理能力越来越强,否则就是一张混乱的、无序的Rpc调用的网,无法管理复杂度。这里建立了服务治理的模型,在下图中的服务治理中心来实现,模型从这样几个角度来考虑如何治理服务,包括通信、契约、版本、监控、安全、交付等角度,依托服务治理中心,有了这套基础设施保驾护航,服务化就可以真正做到提高研发效率、提供优雅的开发体验。服务治理模型DOA面向数据的体系结构面向数据的体系结构(DOA,DataOrientedArchitecture),建立在云计算的硬件架构之上,采用“面向数据和以数据为核心”的思想,通过数据注册中心(DRC,DataRegisterCenter),数据权限中心(DAC,DataAuthorityCenter),数据异常控制中心(DEC,DataExceptionControlCenter)来统一定义数据、管理数据和提供数据服务,通过数据应用单元(DAUs,DataApplicationUnits)对各种应用进行管理和服务,建立一种数据大平台与碎片化应用的数据生态系统,构建起从数据保护到授权应用的整套机制,为有效解决大数据时代所面临软件体系结构的问题提供基础理论和方法技术支撑。大数据时代下的广义数据,是真实世界映射成虚拟世界的各种类型的数据,应用则是由政府、企业和个人在互联网和移动互联网中随时随地、随心随意的各种需求产生出的碎片化和个性化的应用。数据生态系统可以简单形象地比喻为“肥沃的数据土壤上生长着茂盛的应用森林”。理解为:将不断积累和丰富的各种数据定义为数据土壤,那么建立在数据之上的各种碎片化、个性化和不断增长的应用则是应用森林。应用森林中的某一棵应用之树是具有生命周期的,可能会被淘汰或死亡,但整个森林是生态的、枝繁叶茂的和可持续发展的。一个生态系统的好坏取决于这个生态系统的构成和运行机制,而面向数据的软件体系结构(DOA)就是探索一种解决数据与应用之间自生长、自适应、自管理和可持续发展的机制,也包括数据的安全机制和应用中数据的授权使用机制。数据注册中心(DRC),是DOA的核心部件,通过它来构建逻辑的数据资源池,并管理数据和提供数据服务。DRC按照统一标准进行设计,可以将各个行业或不同规模的DRC进行互联和关联,从而可以构成更大规模的DOA系统。数据权限中心(DAC),是DOA的关键部件,对数据的安全存储、传输及应用授权进行管理。对数据实行“天生加密、授权使用”的机制,将数据分成存储和传输时保持加密的“数据态”和在应用中授权使用时解密的“应用态”,充分保证数据的安全及使用的授权。数据异常控制中心(DEC),是DOA的重要部件,对数据资源池进行自适应管理,也是数据生态系统的主要构成。数据应用单元(DAUs),是DOA的关键部件,关联应用对数据的访问,对各种应用提供支持。类似于构件系统,在数据资源池之上,以模块和积木方式提供应用程序接口(API,ApplicationProgrammingInterface),供应用系统直接调用,可以由易到难,由简到繁地构建生态的应用系统。大数据分析技术大数据分析技术是改进已有数据挖掘和机器学习技术,开发数据网络挖掘、特异群组挖掘、图挖掘等新型数据挖掘技术;突破基于对象的数据连接、相似性连接等大数据融合技术,突破用户兴趣分析、网络行为分析、情感语义分析等面向领域的大数据挖掘技术。大数据挖掘就是从大量的、不完全的、有噪声的、模糊的、随机的实际应用数据中,提取隐含在其中的、人们事先不知道的、但又是潜在有用的信息和知识的过程。与传统数据分析相比,用于大数据分析的数据集合主要有三点区别:首先,传统模式多通过采样方式获得部分数据用于分析,大数据可以对收集到的所有海量数据进行分析,分析用的数据源由采样数据扩展至全部数据;其次,分析用的数据源从传统单一领域的数据扩展到跨领域数据,大数据可以将不同领域的数据组合后进行分析;再次,传统数据分析更关注数据源与分析结果间的因果关系,大数据分析时数据源与分析结果间不再只是因果关系,基于有相关关系的数据源同样可以分析预测出正确的结果。大数据分析给传统数据分析和处理技术带来了很多挑战。云计算和开源技术的发展推动大数据落地,分布式存储、非关系数据库和并行处理技术逐渐成为大数据应用实施过程中的关键技术。数据可视化技术(1)支持多种场景的复杂设计模板数据可视化的设计难点不在于图表类型的多,而在于如何能在简单的一页之内让人读懂数据之间的层次与关联,这就关系到色彩、布局、图表的综合运用。通过提供指挥中心、地理分析、实时监控、汇报展示等多种场景模版,即便没有设计师的可视化作品也有高设计水准。(2)多种图表组件,支撑多种数据类型的分析展示除针对业务展示优化过的常规图表外,还能够绘制包括海量数据的地理轨迹、地理飞线、热力分布、地域区块、3D地图、3D地球,地理数据的多层叠加。此外还有拓扑关系、树图等异形图表供自由搭配。(3)多种数据源接入,充分发挥云大数据计算的能力能够接入包括云分析型数据库,关系型数据库,本地上传和在线API的接入,且支持动态请求。满足各类大数据实时计算、监控的需求,充分发挥大数据计算的能力。(4)图形化的搭建工具,无需专业编程人员也可快速实现提供多种的业务模块级而非图表组件的Wiget,所见即所得式的配置方式,只需要通过拖拖拽拽,无需编程能力,即可创造出专业的可视化应用。(5)多分辨率适配与发布方式,满足不同场合下的使用特别针对拼接大屏端的展示做了分辨率优化,能够适配非常规拼接分辨率做适配优化。创建的可视化应用能够发布分享,用户也可以访问到应用,作为对外数据业务展示的窗口。编码规范命名风格(1)【强制】代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。反例:_name/__name/$Object/name_/name$/Object$(2)【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用。正例:alibaba/taobao/youku/hangzhou等国际通用的名称,可视同英文。反例:DaZhePromotion[打折]/getPingfenByName()[评分]/int某变量=3(3)【强制】类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:DO/BO/DTO/VO/AO正例:MarcoPolo/UserDO/XmlService/TcpUdpDeal/TaPromotion反例:macroPolo/UserDo/XMLService/TCPUDPDeal/TAPromotion(4)【强制】方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式。正例:localValue/getHttpMessage()/inputUserId(5)【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。正例:MAX_STOCK_COUNT反例:MAX_COUNT(6)【强制】抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类的名称开始,以Test结尾。(7)【强制】中括号是数组类型的一部分,数组定义如下:String[]args;反例:使用Stringargs[]的方式来定义。(8)【强制】POJO类中布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误。反例:定义为基本数据类型BooleanisDeleted;的属性,它的方法也是isDeleted(),RPC框架在反向解析的时候,“以为”对应的属性名称是deleted,导致属性获取不到,进而抛出异常。(9)【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。正例:应用工具类包名为com.alibaba.open.util、类名为MessageUtils(此规则参考spring的框架结构)。(10)【强制】杜绝完全不规范的缩写,避免望文不知义。反例:AbstractClass“缩写”命名成AbsClass;condition“缩写”命名成condi,此类随意缩写严重降低了代码的可阅读性。(11)【推荐】为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达其意。正例:从远程仓库拉取代码的类命名为PullCodeFromRemoteRepository反例:变量inta;的随意命名方式。(12)【推荐】如果模块、接口、类、方法使用了设计模式,在命名时体现出具体模式。说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计理念。正例:publicclassOrderFactory;publicclassLoginProxy;publicclassResourceObserver;(13)【推荐】接口类中的方法和属性不要加任何修饰符号(public也不要加),保持代码的简洁性,并加上有效的Javadoc注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量。正例:接口方法签名:voidf();接口基础常量表示:StringCOMPANY="alibaba";反例:接口方法定义:publicabstractvoidf();说明:JDK8中接口允许有默认实现,那么这个default方法,是对所有实现类都有价值的默认实现。(14)接口和实现类的命名有两套规则:1)【强制】对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别。正例:CacheServiceImpl实现CacheService接口。2)【推荐】如果是形容能力的接口名称,取对应的形容词做接口名(通常是–able的形式)。正例:AbstractTranslator实现Translatable。(15)【参考】枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。正例:枚举名字为ProcessStatusEnum的成员名称:SUCCESS/UNKOWN_REASON(16)【参考】各层命名规约:1)Service/DAO层方法命名规约a)获取单个对象的方法用get做前缀。b)获取多个对象的方法用list做前缀。c)获取统计值的方法用count做前缀。d)插入的方法用save/insert做前缀。e)删除的方法用remove/delete做前缀。f)修改的方法用update做前缀。2)领域模型命名规约a)数据对象:xxxDO,xxx即为数据表名。b)数据传输对象:xxxDTO,xxx为业务领域相关的名称。c)展示对象:xxxVO,xxx一般为网页名称。d)POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。常量定义(1)【强制】不允许任何魔法值(即未经定义的常量)直接出现在代码中。反例:Stringkey="Id#taobao_"+tradeId;cache.put(key,value);(2)【强制】long或者Long初始赋值时,使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。说明:Longa=2l;写的是数字的21,还是Long型的2?(3)【推荐】不要使用一个常量类维护所有常量,按常量功能进行归类,分开维护。说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。正例:缓存相关常量放在类CacheConsts下;系统配置相关常量放在类ConfigConsts下。(4)【推荐】常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。1)跨应用共享常量:放置在二方库中,通常是client.jar中的constant目录下。2)应用内共享常量:放置在一方库中,通常是modules中的constant目录下。反例:易懂变量也要统一定义成应用内共享常量,两位攻城师在两个类中分别定义了表示“是”的变量:类A中:publicstaticfinalStringYES="yes";类B中:publicstaticfinalStringYES="y";A.YES.equals(B.YES),预期是true,但实际返回为false,导致线上问题。3)子工程内部共享常量:即在当前子工程的constant目录下。4)包内共享常量:即在当前包下单独的constant目录下。5)类内共享常量:直接在类内部privatestaticfinal定义。(5)【推荐】如果变量值仅在一个范围内变化,且带有名称之外的延伸属性,定义为枚举类。下面正例中的数字就是延伸信息,表示星期几。正例:publicEnum{MONDAY(1),TUESDAY(2),WEDNESDAY(3),THURSDAY(4),FRIDAY(5),SATURDAY(6),SUNDAY(7);}代码格式(1)【强制】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果是非空代码块则:1)左大括号前不换行。2)左大括号后换行。3)右大括号前换行。4)右大括号后还有else等代码则不换行;表示终止的右大括号后必须换行。(2)【强制】左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。详见第5条下方正例提示。反例:if(空格a==b空格)(3)【强制】if/for/while/switch/do等保留字与括号之间都必须加空格。(4)【强制】任何二目、三目运算符的左右两边都需要加一个空格。说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。(5)【强制】采用4个空格缩进,禁止使用tab字符。说明:如果使用tab缩进,必须设置1个tab为4个空格。IDEA设置tab为4个空格时,请勿勾选Usetabcharacter;而在eclipse中,必须勾选insertspacesfortabs。正例:(涉及1-5点)publicstaticvoidmain(String[]args){//缩进4个空格Stringsay="hello";//运算符的左右必须有一个空格intflag=0;//关键词if与括号之间必须有一个空格,括号内的f与左括号,0与右括号不需要空格if(flag==0){System.out.println(say);}//左大括号前加空格且不换行;左大括号后换行if(flag==1){System.out.println("world");//右大括号前换行,右大括号后有else,不用换行}else{System.out.println("ok");//在右大括号后直接结束,则必须换行}}(6)【强制】注释的双斜线与注释内容之间有且仅有一个空格。正例://注释内容,注意在//和注释内容之间有一个空格。(7)【强制】单行字符数限制不超过120个,超出需要换行,换行时遵循如下原则:1)第二行相对第一行缩进4个空格,从第三行开始,不再继续缩进,参考示例。2)运算符与下文一起换行。3)方法调用的点符号与下文一起换行。4)方法调用时,多个参数,需要换行时,在逗号后进行。5)在括号前不要换行,见反例。正例:StringBuffersb=newStringBuffer();//超过120个字符的情况下,换行缩进4个空格,点号和方法名称一起换行sb.append("zi").append("xin")....append("huang")....append("huang")....append("huang");反例:StringBuffersb=newStringBuffer();//超过120个字符的情况下,不要在括号前换行sb.append("zi").append("xin")...append("huang");//参数很多的方法调用可能超过120个字符,不要在逗号前换行method(args1,args2,args3,...,argsX);(8)【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。正例:下例中实参的"a",后边必须要有一个空格。method("a","b","c");(9)【强制】IDE的textfileencoding设置为UTF-8;IDE中文件的换行符使用Unix格式,不要使用Windows格式。(10)【推荐】没有必要增加若干空格来使某一行的字符与上一行对应位置的字符对齐。正例:inta=3;longb=4L;floatc=5F;StringBuffersb=newStringBuffer();说明:增加sb这个变量,如果需要对齐,则给a、b、c都要增加几个空格,在变量比较多的情况下,是一种累赘的事情。(11)【推荐】方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。说明:没有必要插入多个空行进行隔开。OOP规约(1)【强制】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。(2)【强制】所有的覆写方法,必须加@Override注解。说明:getObject()与get0bject()的问题。一个是字母的O,一个是数字的0,加@Override可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。(3)【强制】相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。说明:可变参数必须放置在参数列表的最后。(提倡同学们尽量不用可变参数编程)正例:publicUsergetUsers(Stringtype,Integer...ids){...}(4)【强制】外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。(5)【强制】不能使用过时的类或方法。说明:.URLDecoder中的方法decode(StringencodeStr)这个方法已经过时,应该使用双参数decode(Stringsource,Stringencode)。接口提供方既然明确是过时接口,那么有义务同时提供新的接口;作为调用方来说,有义务去考证过时方法的新实现是什么。(6)【强制】Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。正例:"test".equals(object);反例:object.equals("test");说明:推荐使用java.util.Objects#equals(JDK7引入的工具类)(7)【强制】所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较。说明:对于Integervar=?在-128至127范围内的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。(8)关于基本数据类型与包装数据类型的使用标准如下:1)【强制】所有的POJO类属性必须使用包装数据类型。2)【强制】RPC方法的返回值和参数必须使用包装数据类型。3)【推荐】所有的局部变量使用基本数据类型。说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。反例:比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示为0%,这是不合理的,应该显示成中划线。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。(9)【强制】定义DO/DTO/VO等POJO类时,不要设定任何属性默认值。反例:POJO类的gmtCreate默认值为newDate();但是这个属性在数据提取时并没有置入具体值,在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。(10)【强制】序列化类新增属性时,请不要修改serialVersionUID字段,避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改serialVersionUID值。说明:注意serialVersionUID不一致会抛出序列化运行时异常。(11)【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。(12)【强制】POJO类必须写toString方法。使用IDE的中工具:source>generatetoString时,如果继承了另一个POJO类,注意在前面加一下super.toString。说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。(13)【推荐】使用索引访问用String的split方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有抛IndexOutOfBoundsException的风险。说明:Stringstr="a,b,c,,";String[]ary=str.split(",");//预期大于3,结果是3System.out.println(ary.length);(14)【推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读,此条规则优先于第15条规则。(15)【推荐】类内方法定义顺序依次是:公有方法或保护方法>私有方法>getter/setter方法。说明:公有方法是类的调用者和维护者最关心的方法,首屏展示最好;保护方法虽然只是子类关心,也可能是“模板设计模式”下的核心方法;而私有方法外部一般不需要特别关心,是一个黑盒实现;因为承载的信息价值较低,所有Service和DAO的getter/setter方法放在类体最后。(16)【推荐】setter方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在getter/setter方法中,不要增加业务逻辑,增加排查问题的难度。反例:publicIntegergetData(){if(true){returnthis.data+100;}else{returnthis.data-100;}}(17)【推荐】循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展。说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。反例:Stringstr="start";for(inti=0;i<100;i++){str=str+"hello";}(18)【推荐】final可以声明类、成员变量、方法、以及本地变量,下列情况使用final关键字:1)不允许被继承的类,如:String类。2)不允许修改引用的域对象,如:POJO类的域变量。3)不允许被重写的方法,如:POJO类的setter方法。4)不允许运行过程中重新赋值的局部变量。5)避免上下文重复使用一个变量,使用final描述可以强制重新定义一个变量,方便更好地进行重构。(19)【推荐】慎用Object的clone方法来拷贝对象。说明:对象的clone方法默认是浅拷贝,若想实现深拷贝需要重写clone方法实现属性对象的拷贝。(20)【推荐】类成员与方法访问控制从严:1)如果不允许外部直接通过new来创建对象,那么构造方法必须是private。2)工具类不允许有public或default构造方法。3)类非static成员变量并且与子类共享,必须是protected。4)类非static成员变量并且仅在本类使用,必须是private。5)类static成员变量如果仅在本类使用,必须是private。6)若是static成员变量,必须考虑是否为final。7)类成员方法只供类内部调用,必须是private。8)类成员方法只对继承类公开,那么限制为protected。说明:任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。思考:如果是一个private的方法,想删除就删除,可是一个public的service方法,或者一个public的成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作用域太大,无限制的到处跑,那么你会担心的。集合处理(1)【强制】关于hashCode和equals的处理,遵循如下规则:1)只要重写equals,就必须重写hashCode。2)因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。3)如果自定义对象做为Map的键,那么必须重写hashCode和equals。说明:String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用。(2)【强制】ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常,即java.util.RandomAccessSubListcannotbecasttojava.util.ArrayList说明:subList返回的是ArrayList的内部类SubList,并不是ArrayList,而是ArrayList的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。(3)【强制】在subList场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均会产生ConcurrentModificationException异常。(4)【强制】使用集合转数组的方法,必须使用集合的toArray(T[]array),传入的是类型完全一样的数组,大小就是list.size()。说明:使用toArray带参方法,入参分配的数组空间不够大时,toArray方法内部将重新分配内存空间,并返回新数组地址;如果数组元素大于实际所需,下标为[list.size()]的数组元素将被置为null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致。正例:List<String>list=newArrayList<String>(2);list.add("guan");list.add("bao");String[]array=newString[list.size()];array=list.toArray(array);反例:直接使用toArray无参方法存在问题,此方法返回值只能是Object[]类,若强转其它类型数组将出现ClassCastException错误。(5)【强制】使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。说明:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。String[]str=newString[]{"you","wu"};Listlist=Arrays.asList(str);第一种情况:list.add("yangguanbao");运行时异常。第二种情况:str[0]="gujin";那么list.get(0)也会随之修改。(6)【强制】泛型通配符<?extendsT>来接收返回的数据,此写法的泛型集合不能使用add方法,而<?superT>不能使用get方法,做为接口调用赋值时易出错。说明:扩展说一下PECS(ProducerExtendsConsumerSuper)原则:第一、频繁往外读取内容的,适合用<?extendsT>。第二、经常往里插入的,适合用<?superT>。(7)【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。正例:Iterator<String>iterator=list.iterator();while(iterator.hasNext()){Stringitem=iterator.next();if(删除元素的条件){iterator.remove();}}反例:List<String>list=newArrayList<String>();list.add("1");list.add("2");for(Stringitem:list){if("1".equals(item)){list.remove(item);}}说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结果吗?(8)【强制】在JDK7版本及以上,Comparator要满足如下三个条件,不然Arrays.sort,Collections.sort会报IllegalArgumentException异常。说明:三个条件如下1)x,y的比较结果和y,x的比较结果相反。2)x>y,y>z,则x>z。3)x=y,则x,z比较结果和y,z比较结果相同。反例:下例中没有处理相等的情况,实际使用中可能会出现异常:newComparator<Student>(){@Overridepublicintcompare(Studento1,Studento2){returno1.getId()>o2.getId()?1:-1;}};(9)【推荐】集合初始化时,指定集合初始值大小。说明:HashMap使用HashMap(intinitialCapacity)初始化。正例:initialCapacity=(需要存储的元素个数/负载因子)+1。注意负载因子(即loaderfactor)默认为0.75,如果暂时无法确定初始值大小,请设置为16(即默认值)。反例:HashMap需要放置1024个元素,由于没有设置容量初始大小,随着元素不断增加,容量7次被迫扩大,resize需要重建hash表,严重影响性能。(10)【推荐】使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。正例:values()返回的是V值集合,是一个list集合对象;keySet()返回的是K值集合,是一个Set集合对象;entrySet()返回的是K-V值组合集合。(11)【推荐】高度注意Map类集合K/V能不能存储null值的情况,如下表格:集合类KeyValueSuper说明Hashtable不允许为null不允许为nullDictionary线程安全ConcurrentHashMap不允许为null不允许为nullAbstractMap锁分段技术(JDK8:CAS)TreeMap不允许为null允许为nullAbstractMap线程不安全HashMap允许为null允许为nullAbstractMap线程不安全反例:由于HashMap的干扰,很多人认为ConcurrentHashMap是可以置入null值,而事实上,存储null值时会抛出NPE异常。(12)【参考】合理利用好集合的有序性(sort)和稳定性(order),避免集合的无序性(unsort)和不稳定性(unorder)带来的负面影响。说明:有序性是指遍历的结果是按某种比较规则依次排列的。稳定性指集合每次遍历的元素次序是一定的。如:ArrayList是order/unsort;HashMap是unorder/unsort;TreeSet是order/sort。(13)【参考】利用Set元素唯一的特性,可以快速对一个集合进行去重操作,避免使用List的contains方法进行遍历、对比、去重操作。并发处理(1)【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。说明:资源驱动类、工具类、单例工厂类都需要注意。(2)【强制】创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。正例:publicclassTimerTaskThreadextendsThread{publicTimerTaskThread(){super.setName("TimerTaskThread");...}(3)【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。(4)【强制】线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。说明:Executors返回的线程池对象的弊端如下:1)FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。2)CachedThreadPool和ScheduledThreadPool:允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。(5)【强制】SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。正例:注意线程安全,使用DateUtils。亦推荐如下处理:privatestaticfinalThreadLocal<DateFormat>df=newThreadLocal<DateFormat>(){@OverrideprotectedDateFormatinitialValue(){returnnewSimpleDateFormat("yyyy-MM-dd");}};说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释:simplebeautifulstrongimmutablethread-safe。(6)【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。说明:尽可能使加锁的代码块工作量尽可能的小,避免在锁代码块中调用RPC方法。(7)【强制】对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。说明:线程一需要对表A、B、C依次全部加锁后才可以进行更新操作,那么线程二的加锁顺序也必须是A、B、C,否则可能出现死锁。(8)【强制】并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用version作为更新依据。说明:如果每次访问冲突概率小于20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于3次。(9)【强制】多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。(10)【推荐】使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法被执行到,避免主线程无法执行至await方法,直到超时才返回结果。说明:注意,子线程抛出异常堆栈,不能在主线程try-catch到。(11)【推荐】避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed导致的性能下降。说明:Random实例包括java.util.Random的实例或者Math.random()的方式。正例:在JDK7之后,可以直接使用APIThreadLocalRandom,而在JDK7之前,需要编码保证每个线程持有一个实例。(12)【推荐】在并发场景下,通过双重检查锁(double-checkedlocking)实现延迟初始化的优化问题隐患(可参考The"Double-CheckedLockingisBroken"Declaration),推荐解决方案中较为简单一种(适用于JDK5及以上版本),将目标属性声明为volatile型。反例:classSingleton{privateHelperhelper=null;publicHelpergetHelper(){if(helper==null)synchronized(this){if(helper==null)helper=newHelper();}returnhelper;}//othermethodsandfields...}(13)【参考】volatile解决多线程内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。如果是count++操作,使用如下类实现:AtomicIntegercount=newAtomicInteger();count.addAndGet(1);如果是JDK8,推荐使用LongAdder对象,比AtomicLong性能更好(减少乐观锁的重试次数)。(14)【参考】HashMap在容量不够进行resize时由于高并发可能出现死链,导致CPU飙升,在开发过程中可以使用其它数据结构或加锁来规避此风险。(15)【参考】ThreadLocal无法解决共享对象的更新问题,ThreadLocal对象建议使用static修饰。这个变量是针对一个线程内所有操作共享的,所以设置为静态变量,所有此类实例共享此静态变量,也就是说在类第一次被使用时装载,只分配一块存储空间,所有此类的对象(只要是这个线程内定义的)都可以操控这个变量。控制语句(1)【强制】在一个switch块内,每个case要么通过break/return等来终止,要么注释说明程序将继续执行到哪一个case为止;在一个switch块内,都必须包含一个default语句并且放在最后,即使它什么代码也没有。(2)【强制】在if/else/for/while/do语句中必须使用大括号。即使只有一行代码,避免采用单行的编码方式:if(condition)statements;(3)【推荐】表达异常的分支时,少用if-else方式,这种方式可以改写成:if(condition){...returnobj;}//接着写else的业务逻辑代码;说明:如果非得使用if()...elseif()...else...方式表达逻辑,【强制】避免后续代码维护困难,请勿超过3层。正例:超过3层的if-else的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现,其中卫语句示例如下:publicvoidtoday(){if(isBusy()){System.out.println(“changetime.”);return;}if(isFree()){System.out.println(“gototravel.”);return;}System.out.println(“stayathometolearnAlibabaJavaCodingGuidelines.”);return;}(4)【推荐】除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行其它复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量名,以提高可读性。说明:很多if语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?正例://伪代码如下finalbooleanexisted=(file.open(fileName,"w")!=null)&&(...)||(...);if(existed){...}反例:if((file.open(fileName,"w")!=null)&&(...)||(...)){...}(5)【推荐】循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的try-catch操作(这个try-catch是否可以移至循环体外)。(6)【推荐】接口入参保护,这种场景常见的是用于做批量操作的接口。(7)【参考】下列情形,需要进行参数校验:1)调用频次低的方法。2)执行时间开销很大的方法。此情形中,参数校验时间几乎可以忽略不计,但如果因为参数错误导致中间执行回退,或者错误,那得不偿失。3)需要极高稳定性和可用性的方法。4)对外提供的开放接口,不管是RPC/API/HTTP接口。5)敏感权限入口。(8)【参考】下列情形,不需要进行参数校验:1)极有可能被循环调用的方法。但在方法说明里必须注明外部参数检查要求。2)底层调用频度比较高的方法。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底层才会暴露问题。一般DAO层与Service层都在同一个应用中,部署在同一台服务器中,所以DAO的参数校验,可以省略。3)被声明成private只会被自己代码所调用的方法,如果能够确定调用方法的代码传入参数已经做过检查或者肯定不会有问题,此时可以不校验参数。注释规约(1)【强制】类、类属性、类方法的注释必须使用Javadoc规范,使用/**内容*/格式,不得使用//xxx方式。说明:在IDE编辑窗口中,Javadoc方式会提示相关注释,生成Javadoc可以正确输出相应注释;在IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。(2)【强制】所有的抽象方法(包括接口中的方法)必须要用Javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。说明:对子类的实现要求,或者调用注意事项,请一并说明。(3)【强制】所有的类都必须添加创建者和创建日期。(4)【强制】方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/**/注释,注意与代码对齐。(5)【强制】所有的枚举类型字段必须要有注释,说明每个数据项的用途。(6)【推荐】与其“半吊子”英文来注释,不如用中文注释把问题说清楚。专有名词与关键字保持英文原文即可。反例:“TCP连接超时”解释成“传输控制协议连接超时”,理解反而费脑筋。(7)【推荐】代码修改的同时,注释也要进行相应的修改,尤其是参数、返回值、异常、核心逻辑等的修改。说明:代码与注释更新不同步,就像路网与导航软件更新不同步一样,如果导航软件严重滞后,就失去了导航的意义。(8)【参考】谨慎注释掉代码。在上方详细说明,而不是简单地注释掉。如果无用,则删除。说明:代码被注释掉有两种可能性:1)后续会恢复此段代码逻辑。2)永久不用。前者如果没有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。(9)【参考】对于注释的要求:第一、能够准确反应设计思想和代码逻辑;第二、能够描述业务含义,使别的程序员能够迅速了解到代码背后的信息。完全没有注释的大段代码对于阅读者形同天书,注释是给自己看的,即使隔很长时间,也能清晰理解当时的思路;注释也是给继任者看的,使其能够快速接替自己的工作。(10)【参考】好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的一个极端:过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担。反例://putelephantintofridgeput(elephant,fridge);方法名put,加上两个有意义的变量名elephant和fridge,已经说明了这是在干什么,语义清晰的代码不需要额外的注释。(11)【参考】特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫描,经常清理此类标记。线上故障有时候就是来源于这些标记处的代码。1)待办事宜(TODO):(标记人,标记时间,[预计处理时间])表示需要实现,但目前还未实现的功能。这实际上是一个Javadoc的标签,目前的Javad
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 医药电商发展动态-洞察分析
- 药酒与传统疗法比较-洞察分析
- 油田绿色开采技术-洞察分析
- 2024-2025学年陕西省部分学校高三上学期11月期中统测物理试题(解析版)
- 水资源节约型灌溉技术-洞察分析
- 2024年员工三级安全培训考试题附完整答案(有一套)
- 2023年-2024年新入职员工安全教育培训试题(原创题)
- 2024年企业主要负责人安全培训考试题含答案【培优B卷】
- 素数计算性能提升-洞察分析
- 2024企业主要负责人安全培训考试题附答案【培优A卷】
- 2024亲戚借名买房协议书
- 小学二年级上册数学-数角的个数专项练习
- 期末核心素养测评卷2023-2024学年语文五年级上册+统编版
- 医疗器械质量安全风险会商管理制度
- 《我爱上班》朗诵稿
- 2024年石油石化技能考试-石油钻井工笔试参考题库含答案
- 2024年度带状疱疹课件
- 电桩采购安装充电桩调试验收方案
- 消防设施安全检查表
- 钻孔灌注桩施工方案 (详细)
- 新建南通至宁波高速铁路站前Ⅲ标二分部出海栈桥及综合码头(自用)工程海域使用论证报告表
评论
0/150
提交评论