瑞_Java开发手册_(七)设计规约

news2024/11/21 0:30:49

文章目录

    • 设计规约的意义
    • 设计规约

🙊前言:本文章为瑞_系列专栏之《Java开发手册》的设计规约篇。由于博主是从阿里的《Java开发手册》学习到Java的编程规约,所以本系列专栏主要以这本书进行讲解和拓展,有需要的小伙伴可以点击链接下载。本文仅供大家交流、学习及研究使用,禁止用于商业用途,违者必究!

本系列第一篇链接:(一)编程规约
本系列第二篇链接:(二)异常日志
本系列第三篇链接:(三)单元测试
本系列第四篇链接:(四)安全规约
本系列第五篇链接:(五)MySQL数据库
本系列第六篇链接:(六)工程结构
本系列第七篇链接:(七)设计规约

在这里插入图片描述

设计规约的意义

  在Java开发手册中,《设计规约》是一个非常重要的部分,它为开发者提供了一系列关于系统设计的指导原则和约定。这些规约旨在确保设计的一致性、可维护性和可扩展性,从而提高软件的质量和可靠性

  设计规约的意义主要如下:

  • 确保设计的一致性:通过制定统一的设计规约,可以确保团队成员遵循相同的标准和约定,从而在整个项目中保持设计的一致性。这有助于减少因个人偏好或习惯导致的差异,降低维护成本。
  • 提升代码质量:规约中明确规定了设计的各个方面,如类设计、接口设计、数据结构设计等。通过遵循这些规约,可以减少代码中的缺陷、提高代码的可读性和可维护性,并使代码更加健壮。
  • 降低维护成本:设计规约为开发人员提供了一个清晰的指南,指导如何进行系统设计和实现。当系统变得复杂时,遵循规约可以使维护工作变得更加简单和高效。开发人员可以快速理解代码的结构和设计意图,降低维护成本。
  • 促进团队合作:设计规约可以帮助团队成员更好地协作和沟通。当所有人遵循相同的规约时,可以更加顺利地交流和合作,避免因误解或不一致导致的开发冲突。
  • 提高软件可扩展性:设计规约不仅关注现有功能的实现,还考虑未来的扩展性。通过遵循规约,开发人员在设计时能够预见未来的变化,并构建出灵活的架构,使软件更容易适应未来的需求变化。
  • 降低培训成本:对于新加入的团队成员,遵循设计规约可以降低他们的学习成本。他们可以快速了解项目的代码结构和设计风格,更快地融入团队并开始工作。
  • 促进最佳实践的推广:设计规约通常基于行业最佳实践和经验总结。通过推广这些规约,可以帮助团队吸收和采纳先进的软件开发理念和方法,从而提高整个团队的技术水平。



设计规约

  1. 【强制】存储方案底层数据结构的设计获得评审一致通过,并沉淀成为文档。
    说明:有缺陷的底层数据结构容易导致系统风险上升,可扩展性下降,重构成本也会因历史数据迁移和系统平滑过渡而陡然增加,所以,存储方案和数据结构需要认真地进行设计和评审,生产环境提交执行后,需要进行 double check。
    正例:评审内容包括存储介质选型、表结构设计能否满足技术方案、存取性能和存储空间能否满足业务发展、表或字段之间的辩证关系、字段名称、字段类型、索引等;数据结构变更(如在原有表中新增字段)也需要进行评审通过后上线。

  2. 【强制】在需求分析阶段,如果与系统交互的 User 超过一并且相关的 User Case 超过 5 个,使用用例图来表达更加清晰的结构化需求。

  3. 【强制】如果某个业务对象的状态超过 3 个,使用状态图来表达并且明确状态变化的各个触发条件。
    说明:状态图的核心是对象状态,首先明确对象有多少种状态,然后明确两两状态之间是否存在直接转换关系,再明确触发状态转换的条件是什么。
    正例:淘宝订单状态有已下单、待付款、已付款、待发货、已发货、已收货等。比如已下单与已收货这两种状态之间是不可能有直接转换关系的。

  4. 【强制】如果系统中某个功能的调用链路上的涉及对象超过 3 个,使用时序图来表达并且明确各调用环节的输入与输出。
    说明:时序图反映了一系列对象间的交互与协作关系,清晰立体地反映系统的调用纵深链路。

  5. 【强制】如果系统中模型类超过 5 个,并且存在复杂的依赖关系,使用类图来表达并且明确类之间的关系。
    说明:类图像建筑领域的施工图,如果搭平房,可能不需要,但如果建造蚂蚁 Z 空间大楼,肯定需要详细的施工图。

  6. 【强制】如果系统中超过 2 个对象之间存在协作关系,并且需要表示复杂的处理流程,使用活动图来表示。
    说明:活动图是流程图的扩展,增加了能够体现协作关系的对象泳道,支持表示并发等。

  7. 【推荐】系统架构设计时明确以下目标:

    • 确定系统边界。确定系统在技术层面上的做与不做。
    • 确定系统内模块之间的关系。确定模块之间的依赖关系及模块的宏观输入与输出。
    • 确定指导后续设计与演化的原则。使后续的子系统或模块设计在一个既定的框架内和技术方向上继续演化。
    • 确定非功能性需求。非功能性需求是指安全性、可用性、可扩展性等。

瑞:
1️⃣确定系统边界:

  • 理解:在开始设计一个系统时,首先需要明确这个系统的范围或边界。这涉及到确定哪些功能属于这个系统,哪些功能不属于这个系统。
  • 意义:明确系统边界有助于团队成员对系统的整体功能有一个清晰的认识,防止在开发过程中过度设计和遗漏某些功能。

2️⃣确定系统内模块之间的关系:

  • 理解:这涉及到识别系统中的各个模块,并定义它们之间的交互关系,如数据流、控制流等。
  • 意义:了解模块之间的关系有助于更好地组织代码、提高可维护性和模块的复用性。

3️⃣确定指导后续设计与演化的原则:

  • 理解:这意味着在架构设计阶段,需要为后续的子系统或模块设计制定一些标准和指导原则,以确保这些子系统或模块在设计、开发、演化过程中保持一致性。
  • 意义:这样可以确保系统的整体连贯性和可扩展性,使得新加入的子系统或模块能够与现有系统更好地集成。

4️⃣确定非功能性需求:

  • 理解:非功能性需求通常指的是那些与系统的核心功能无关,但对系统的性能、可靠性、安全性等方面有重要影响的特性。例如,系统的响应时间、可用性、安全性、可扩展性等。
  • 意义:明确非功能性需求有助于确保在设计和开发过程中充分考虑这些因素,从而构建出更加健壮和可靠的软件系统。
  1. 【推荐】需求分析与系统设计在考虑主干功能的同时,需要充分评估异常流程与业务边界。
    反例:用户在淘宝付款过程中,银行扣款成功,发送给用户扣款成功短信,但是支付宝入款时由于断网演练产生异常,淘宝订单页面依然显示未付款,导致用户投诉。

  2. 【推荐】类在设计与实现时要符合单一原则。
    说明:单一原则最易理解却是最难实现的一条规则,随着系统演进,很多时候,忘记了类设计的初衷。

瑞:要分清楚 [ 数据对象类 ] 和 [ 业务对象类 ] 的职责区别。数据对象类只负责数据的存储和传递,数据对象类内部不应该存在任何的业务逻辑的处理,通常情况下只有 setter/getter/toString ,如DTO数据传输对象。而业务对象类才是负责处理业务逻辑,不应该去维护非业务的成员属性,如Service层接口的具体实现类

  1. 【推荐】谨慎使用继承的方式来进行扩展,优先使用聚合/组合的方式来实现。
    说明:不得已使用继承的话,必须符合里氏代换原则,此原则说父类能够出现的地方子类一定能够出现,比如,“把钱交出来”,钱的子类美元、欧元、人民币等都可以出现。

瑞:里氏代换原则可以参考《瑞_23种设计模式_概述(含代码)》中的设计模式的6大法则的里氏代换原则(Liskov Substitution Principle)。比如 “BaseController” 或者 “钱有子类:人民币、美元” 等情况才使用继承

  1. 【推荐】系统设计阶段,根据依赖倒置原则,尽量依赖抽象类与接口,有利于扩展与维护。
    说明:低层次模块依赖于高层次模块的抽象,方便系统间的解耦。

瑞:依赖倒置原则可以参考《瑞_23种设计模式_概述(含代码)》中的设计模式的6大法则的依赖倒转原则(Dependence Inversion Principle)。如Spring框架的ApplicationContext类,它是一个接口,定义了各种获取bean的方法,它位于Spring框架的高层次,提供了一种全局的访问机制。低层次的模块(例如控制器、服务、数据访问对象等)通常依赖于高层次的抽象(例如接口或抽象类),而不是直接依赖于具体的实现类。这样,当实现类发生变化时,低层次的模块不需要修改代码,因为它们依赖于抽象而不是具体的实现。

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        ApplicationContext applicationContext = new AbstractApplicationContext() {
            @Override
            public Object getBean(String name) throws Exception {
                // 自定义实现
                return null;
            }

            @Override
            public <T> T getBean(String name, Class<? extends T> clazz) throws Exception {
                // 自定义实现
                return null;
            }
        }
  1. 【推荐】系统设计阶段,注意对扩展开放,对修改闭合。
    说明:极端情况下,交付的代码是不可修改的,同一业务域内的需求变化,通过模块或类的扩展来实现。

瑞:可以参考《瑞_23种设计模式_概述(含代码)》中的设计模式的6大法则的开闭原则(Open Close Principle)

  1. 【推荐】系统设计阶段,共性业务或公共行为抽取出来公共模块、公共配置、公共类、公共方法等,在系统中不出现重复代码的情况。
    说明:随着代码的重复次数不断增加,维护成本指数级上升。

瑞:即使某方法只使用两次,也应该抽出公共部分变为一个方法。如果使用IDEA开发工具,建议开启duplicated code fragment即重复代码片段检查选项,如下图所示:

在这里插入图片描述

  1. 【推荐】避免如下误解:敏捷开发 = 讲故事 + 编码 + 发布。
    说明:敏捷开发是快速交付迭代可用的系统,省略多余的设计方案,摒弃传统的审批流程,但核心关键点上的必要设计和文档沉淀是需要的。
    反例:某团队为了业务快速发展,敏捷成了产品经理催进度的借口,系统中均是勉强能运行但像面条一样的代码,可维护性和可扩展性极差,一年之后,不得不进行大规模重构,得不偿失。

  2. 【参考】设计文档的作用是明确需求、理顺逻辑、后期维护,次要目的用于指导编码。
    说明:避免为了设计而设计,系统设计文档有助于后期的系统维护和重构,所以设计结果需要进行分类归档保存。

  3. 【参考】可扩展性的本质是找到系统的变化点,并隔离变化点。
    说明:世间众多设计模式其实就是一种设计模式即隔离变化点的模式。
    正例:极致扩展性的标志,就是需求的新增,不会在原有代码交付物上进行任何形式的修改。

  4. 【参考】设计的本质就是识别和表达系统难点。
    说明:识别和表达完全是两回事,很多人错误地认为识别到系统难点在哪里,表达只是自然而然的事情,但是大家在设计评审中经常出现语焉不详,甚至是词不达意的情况。准确地表达系统难点需要具备如下能力: 表达规则和表达工具的熟练性。抽象思维和总结能力的局限性。基础知识体系的完备性。深入浅出的生动表达力。

  5. 【参考】代码即文档的观点是错误的,清晰的代码只是文档的某个片断,而不是全部。
    说明:代码的深度调用,模块层面上的依赖关系网,业务场景逻辑,非功能性需求等问题是需要相应的文档来完整地呈现的。

  6. 【参考】在做无障碍产品设计时,需要考虑到:

    • 所有可交互的控件元素必须能被 tab 键聚焦,并且焦点顺序需符合自然操作逻辑。
    • 用于登陆校验和请求拦截的验证码均需提供图形验证以外的其它方式。
    • 自定义的控件类型需明确交互方式。
      正例:用户登陆场景中,输入框的按钮都需要考虑 tab 键聚焦,符合自然逻辑的操作顺序如下,“输入用户名,输入密码,输入验证码,点击登录”,其中验证码实现语音验证方式。如果有自定义标签实现的控件设置控件类型可使用 role 属性。



本文是博主的粗浅理解,可能存在一些错误或不完善之处,如有遗漏或错误欢迎各位补充,谢谢

  如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1389224.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

K8S中使用helm安装MinIO

注意事项 使用helm部署MinIO分为两部分 helm部署MinIO operator&#xff0c;用来管理tenant&#xff08;K8S集群中只能部署一个&#xff09;helm部署MinIO tenant&#xff0c;真实的MinIO Cluster&#xff08;K8S集群中可以部署多个&#xff09; 使用helm部署到K8S集群&…

CC工具箱使用指南:【获取所有字段信息】

一、简介 这个工具的目的简单易懂&#xff0c;就是获取选定要素图层的所有字段信息。 本身不对要素图层作任何处理&#xff0c;只是一个查看属性的工具。 问我要用在什么地方&#xff0c;我也不知道-_- 二、工具参数介绍 点击【信息获取】组里的【获取所有字段信息】工具&a…

vue3二次封装element-ui中的table组件

为什么要做这件事 借助封装table组件的过程来巩固一下vue3相关知识点。 组件有哪些配置项 options:表格的配置项data: 表格数据源elementLoadingText&#xff1a;加载文案elementLoadingSpinner&#xff1a;加载图标elementLoadingBackground&#xff1a;背景遮罩的颜色elem…

解码Java SPI:深入理解与实践【七】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 解码Java SPI&#xff1a;深入理解与实践【七】 前言SPI机制简介&#xff1a;SPI的工作原理java标准SPI示例总结 前言 在编写Java应用程序时&#xff0c;我们经常需要使用不同的库和框架来扩展功能。…

NET Core发布 HTTP Error 500.31 - Failed to load ASP.NET Core runtime

记录一下踩过的坑&#xff1a; 首先&#xff0c;不论是500.31还是500.30 &#xff0c;首先确保安装了三个文件 1.NET Core RunTime 2.NET SDK 3.NET Hosting 其次&#xff0c;确保三个文件的版本一致&#xff0c;如下&#xff1a; 要装就统一装同一个大版本&#xff0c;不要东…

streamlit配合plotly绘制交互式图表

借助st.plotly_chart实现 官方介绍&#xff1a;st.plotly_chart 案例&#xff1a; import pandas as pd import plotly.graph_objs as go import plotly.express as pxst.subheader("课题组成员", dividerred) df pd.read_excel("./data/summary.xlsx"…

护眼灯到底有用吗知乎?护眼台灯的作用

近年来&#xff0c;随着电子产品的普及和使用时间的增加&#xff0c;人们对眼部健康的关注度也日益提高。为解决由此带来的问题&#xff0c;护眼台灯在这一背景下崭露头角。护眼台灯是一种融合先进技术的台灯&#xff0c;旨在缓解眼部疲劳并保护视力&#xff0c;那护眼台灯究竟…

第七站:C++面向对象训练

1:介绍 创建两个类,一个boy类,一个girl类,实现对两个类的数据输入,并通过main函数,对两个类的成员进行比较匹配 涉及: vector容器,面向对象,const关键字, stringstream(sstream.h) stringstream用法 stringstream ret;//可以将写入的数据转换成字符串 ret << &quo…

利用python将Excel文件拆分为多个CSV

目录 一、准备工作 二、拆分Excel文件为多个CSV 1、读取Excel文件&#xff1a; 2、确定要拆分的列&#xff1a; 3、创建空的字典来存储CSV文件&#xff1a; 4、循环遍历数据并根据类别拆分&#xff1a; 5、打印或返回CSV文件名字典&#xff1a; 6、保存CSV到特定目录&a…

python.24.1.16函数

python自带函数 自定义函数 参数的使用

机器学习——支持向量机SVM

1 摘要&#xff1a; 支持向量机&#xff08;SVM&#xff09;是一种二类分类模型&#xff0c;其基本模型是在特征空间上找到最佳的分离超平面使得训练集上正负样本间隔最大&#xff0c;间隔最大使它有别于感知机&#xff0c;支持向量机也可通过核技巧使它成为非线性分类器。支持…

presto 支持regexp_count

一、背景 1、查询regexp_count 函数提示未注册 用户想正则查询特定字符出现次数 function regexp_count not registered 二、调研 1、官网地址&#xff1a; Presto Documentation — Presto 0.284 Documentation 2、regexp_extract_all Regular Expression Functions —…

c++时间复杂度详解

1.基本概念 在计算机科学中&#xff0c;时间复杂性&#xff0c;又称时间复杂度&#xff0c;算法的时间复杂度是一个函数&#xff0c;它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述&#xff0c;不包括这个函数的低阶项和…

【Mybatis系列】Mybatis空值关联

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

PDF.js实现按需分片加载pdf文件

pdf.js实现按需、分片加载pdf文件 1.服务端配置 分片加载的实现是基于 HTTP-RANGE&#xff0c;即服务端的文件接口必须实现了HTTP-RANGE。 服务端文件接口实现HTTP-RANGE&#xff0c;需要服务端添加如下响应头 [{key: "Accept-Ranges",value: "bytes"}…

用Growly Draw for Mac,释放您的创意绘画天赋!

在数字化时代&#xff0c;绘画已经不再局限于传统的纸笔之中。如今&#xff0c;我们可以借助强大的绘画应用软件&#xff0c;将创意化为独特的艺术作品。而Growly Draw for Mac就是一款让您能够快速释放创意、创作精美绘画作品的应用软件。 Growly Draw for Mac是一款专为Mac用…

Ezsql

靶场说明 靶机地址解释&#xff1a; 第一行&#xff1a;目标机器 WEB 服务地址 第二行&#xff1a;目标机器 SSH 地址以及端口 第三行&#xff1a;Check 服务访问地址。 http://99bdd2da-7d5e-4b5c-a7ee-79713b8ecabc.node5.buuoj.cn:8199bdd2da-7d5e-4b5c-a7ee-79713b8ecabc…

十、Three场景实现多个物体的合并

Three场景实现多个物体的合并 目的 产品需求是让物体的光柱墙包含一个多边形的区域,二而我的多边形只能使用原型,方向,多边形。那么再研究的时候就需要将这些多边形合并成为一个形状,那么就行实现了。 原先的图形 如上图,是两个mesh组成的。首先寻找mesh合并的方法。 第…

《TrollStore巨魔商店》TrollStore2安装使用教程支持IOS14.0-16.6.1

TrollStore(巨魔商店) 简单的说就相当于一个永久的免费证书&#xff0c;它可以给你的iPhone和iPad安装任何你想要安装的App软件&#xff0c;而且不需要越狱,不用担心证书签名过期的问题&#xff0c;不需要个人签名和企业签名。 支持的版本&#xff1a; TrollStore安装和使用教…

Ubantu 安装vscode配置c/c++环境

文章目录 安装VSCode注意 snap包冲突 安装C/C编译环境注意 进程锁占用 配置C开发环境安装插件配置tasks.json配置c_cpp_properties.json 配置调试环境配置 launch.json 安装VSCode 方式一&#xff1a;ubantu 软件里面直接安装 方式二&#xff1a;官网下载deb安装包https://cod…