精华内容
下载资源
问答
  • API 设计规范

    千次阅读 2020-09-12 18:15:55
    文章目录目录API 设计规范Design-First(设计优先)Code-First(编码优先) API 设计规范 通常,设计 API 规范有两个方向,Design-First(设计优先) 或 Code-First(编码优先)。 Design-First(设计优先) 即优先...

    目录

    API 实现方式

    通常,设计 API 规范有两个方向,Design-First(设计优先) 或 Code-First(编码优先)。

    Design-First(设计优先)

    即优先设计 API 规范,设计完成后再着手进行代码开发工作。推荐使用 OpenAPI-GUI v3 来设计 API 描述文件。

    采用 Design-First 就意味着,将设计 API 路由、参数等工作提前,后续整个软件开发的流程都需要围绕着 API 规范为核心,当然这需要有一定的设计经验的开发人员才能胜任。

    Design-First 有很多好处:

    • 提高开发效率。开发团队将根据 API 规范进行并行开发和对接工作,而无需等待接口逻辑开发完毕。
    • 降低接口开发的成本,无需修改代码逻辑即可轻松地修改 API 规范,因为 API 描述语言(如:OpenAPI)与编码语言无关。
    • 开发人员更加专注于设计 API 规范,对比 Code-First 可以描写更多 API 的细节,如:校验规则、范例数据等,同时开发人员对 API 的全局一致性、扩展性、规范性也有更好的把控。
    • 在联调开发的过程中可以提前发现和解决问题,避免问题在开发完毕后修改的成本过高。
    • 由于 API 描述更加标准化,可以方便做更多的 API 生态延伸,比如基于 API 规范生成 Mock API Server,开发 API 自动化测试代码,接入 API 网关等。

    Code-First(编码优先)

    即通过代码中关于 API 描述特性、注解或注释自动生成 API 描述文件的设计方式,如:JAVA 生态的 SpringFox。

    适合倾向于在代码上编写 API 规范,通过自动化设施自动生成文档的团队。

    Code-First 的优点:

    • 节省时间。对于 API 开发者,编码的同时可以获得一份满足基本要求的 API 文档。
    • 方便接入自动化 CI/CD 流程中。

    虽然 Code-First 省去了开发者设计 API 描述文件的阶段,提高了 API 开发者的效率,但是从整个团队的角度来看,效率并不一定提升了,反而有可能降低了效率。

    不同 API 开发者的经验和习惯的不同,极有可能在编码的过程中对 API 的限制条件考虑不全,又或者框架生成 API 文档的程序完善度不够,种种因素导致最终生成的 API 的描述无法达到理想标准。

    而很多 API 开发者习惯开发完成后才推送代码,并生成 API 文档,也导致了团队的进程阻塞于此,拖后了整个团队的开发进程。另一方面,API 在开发完成如果没有测试,很有可能导致 API 对接者在对接的过程中遇到重重阻碍。

    如果使用 Code-First 设计方向,建议:

    • 选用完善程度比较高的生成组件。
    • 对 API 的描述尽可能的细致、完整。
    • 优先设计路由、请求、响应等规则,详细的逻辑代码在 API 设计完成后再着手开发。

    API 设计规范

    为用户设计 API

    API 并不是用来盲目的暴露一些数据或业务处理能力的,它就像我们每天使用的任何形式的接口一样(例如:微波炉的操作按钮),用来帮助用户完成他们的目标。所以,需要从用户的视角来决定一个 API 的设计是否友好,在设计 API 的时候要充分考虑 UI/UE 的操作流程。

    反之,如果以开发者的视角去设计 API,那么通常的后果是开发出的 API 往往都偏重与于功能的实现过程和原理,而不是用户如何能简单平滑的使用这个 API 来达到他们的目的。

    所以,一个好的 API 设计一定是面向用户的,充分隐藏底层复杂原理的。要设计出让用户容易理解和容易使用的 API。

    识别 API 的目标

    识别 API 的目标,最基本的需要对以下方面有深刻且精准的认识:

    • Who,谁使用这个 API?
    • What,用户拿这个 API 能做什么事?
    • How,用户如何做这件事?
    • What Need,用户想要做这件事的话还需要什么?
    • What Return,用户会得到什么?

    Mock API Server

    Mock API Server 基于 API 描述文件自动生成 Mock API,通过提供真实 API 响应的范例数据来模拟真实的 API 服务,并且支持路由及参数校验。

    使用场景

    1. API 对接/调试:通常在公司项目中,API 使用者(如:前端、App、自动化 API 测试开发人员)的开发进度会比后端 API 开发人员提前开始开发实现。而使用基于 API 文档的 Mock API 可提供模拟真实 API 响应的沙盒环境,以便 API 使用者提前开始调试工作。另一方面 API 使用者可以及时反馈 API 设计问题,在完成 API 实现之前提早完善 API 设计,使得 API 开发工作更加高效和趋于完美。
    2. API 测试:当需要对部分 API 进行统一测试时,可以替换其他 API 为 Mock API,而无需关心其他依赖 API 是否满足测试条件。
    3. 外部 API 服务:通常外部 API 服务可能会有不可靠、收费、访问限制等情况,所以可以替换外部 API 服务为 Mock API,通过 Mock 外部 API 服务的真实数据来调试程序逻辑。

    使用步骤

    1. API 规范设计:OpenAPI 规范。
    2. 生成范例数据 :Swagger Editor 可自动通过参数生成 Example。
    3. 生成 Mock API:Swagger CodeGen 可以自定生成 Mock API Server。
    展开全文
  • 前端设计规范

    2019-01-10 10:13:11
    项目目录结构规范 JS代码规范 HTML代码规范 CSS代码规范 百度前端设计规范

    一. 项目目录结构规范

    二. JS代码规范

    三. HTML代码规范

    四. CSS代码规范

    五. 百度前端设计规范

    六. 写代码前进行设计的具体流程

    (1)对于比较小的项目

    • 了解流程
    • 写大纲(类似于伪代码)
      例如:
    class Car {
      run(){},
      stop(){},
    }
    
    • 实现细节

    (2)对于比较大的项目

    • 阅读文档,分析需求
    • 画原型图或草图(方便自己理解整体架构)
    • 写大纲或伪代码(如果项目比较大还要细分模块)
    • 实现细节

    ( 更多请参考如何写高质量的代码 )

    展开全文
  • 网络基础10 Restful API设计规范

    万次阅读 2017-11-03 19:58:30
    Restful API设计规范总结

    概念

    Restful API用来规范应用如何在HTTP层与API提供方进行数据交互 。

    Restful API描述了HTTP层里客户端和服务器端的数据交互规则:客户端通过向服务器端发送HTTP(S)请求,接收服务器的响应,完成一次HTTP交互。这个交互过程中,REST架构约定两个重要方面就是HTTP请求的所采用方法,以及请求的链接。

    在请求层面,Restful API规范可以简单粗暴抽象成以下两个规则:

    1. 请求API的URL表示用来定位资源
    2. 请求的METHOD表示对这个资源进行的操作

    API的URL

    版本号

    在Restful API中,API应当尽量兼容之前的版本。Web端很容易为了适配服务端的新的API接口进行版本升级,而Android、IOS等客户端必须通过用户主动升级产品到新版本,才能适配新接。

    为了解决这个问题,在设计Restful API时一般情况下会在URL中保留版本号,并同时兼容多个版本:

    【GET】  /v1/users/{user_id}  // 版本 v1 的查询用户列表的 API 接口
    【GET】  /v2/users/{user_id}  // 版本 v2 的查询用户列表的 API 接口
    

    现在可以在不改变V1版本的接口情况下,新增V2版本的接口满足新的业务需求。服务端会同时兼容多个版本,但是同时维护版本过多也会成为不小的负担。

    常见的做法是,不维护全部的兼容版本,而是只维护最新的几个兼容版本,例如维护最新的三个兼容版本。在一段时间后,大部分的用户升级到新的版本后,废弃一些使用量较少的服务端老版本的API接口,并要求使用产品老旧版本的用户墙纸升级。

    不合理的URL

    URL用来定位资源,跟要进行的操作区分开,这就意味这URL不该有任何动词

    下面示例中的getcreatesearch等动词,都不应该出现在REST架构的后端接口路径中。在以前,这些接口中的动名词通常对应后台的某个函数。比如:

    /api/getUser
    /api/createApp
    /api/searchResult
    /api/deleteAllUsers
    

    当我们需要对单个用户进行操作时,根据操作的方式不同可能需要下面的这些接口:

    /api/getUser 
    //  用来获取某个用户的信息,还需要以参数方式传入用户 id 信息)
    
    /api/updateUser 
    // 用来更新用户信息
    
    /api/deleteUser
    // 用来删除单个用户
    
    /api/resetUser 
    // 重置用户的信息
    

    这样的弊端在于:

    1. URL更长了
    2. 对一个资源实体进行不同的操作就是一个不同URL,造成URL过多难以管理。

    其实当你回过头看「URL」这个术语的定义时,更能理解这一点。URL的意思是统一资源定位符,这个术语已经清晰的表明,一个URL应该用来定位资源,而不应该掺入对操作行为的描述。

    Restful的URL

    在REST架构的URL应该是这个样子:

    1. URL中不应该出现任何表示操作的动词,链接只用于对应资源
    2. URL中应该单复数区分,推荐的实践是永远只用复数;比如GET /api/users表示获取用户的列表;如果获取单个资源,传入ID,比如/api/users/123表示获取单个用户的信息;
    3. 按照资源的逻辑层级,对URL进行嵌套,比如一个用户属于某个团队,而这个团队也是众多团队之一;那么获取这个用户的接口可能是这样:
    GET /api/teams/123/members/234
    // 表示获取 id 为 123 的小组下,id 为234 的成员信息
    

    按照类似的规则,可以写出如下的接口:

    /api/teams 
    // 对应团队列表
    
    /api/teams/123 
    // 对应 ID 为 123 的团队
    
    /api/teams/123/members 
    // 对应 ID 为 123 的团队下的成员列表
    
    /api/teams/123/members/456 
    // 对应 ID 为 123 的团队下 ID 为 456 的成员
    

    特殊情况

    有的时候一个资源变化难以使用标准的Restful API来命名,可以考虑使用一些特殊的Actions命名。比如,“密码修改”这个接口的命名很难完全使用名词来构建路径,此时可以引入Action:

    PUT  /v1/users/{user_id}/password/actions/modify
    // 密码修改
    

    大小写

    根据RFC3986定义,URL是大小写明暗的,所以为了避免歧义,尽量使用小写字母。

    API的请求方法

    在很多系统中,几乎只用GET和POST方法来完成了所有的接口操作。这个行为类似于全用<div>来布局。实际上,我们不只有GET和POST可用,在REST架构中,有以下几个重要的请求方法:GET,POST,PUT,PATCH,DELETE。这几个方法都可以与对数据的 CRUD 操作对应起来。

    CRUD 是指在做计算处理时的增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写。即增删改查

    简单来说,GET用于查询资源,POST用于创建资源,PUT用于更新服务端的资源的全部信息,PATCH 用于更新服务端的资源的部分信息,DELETE 用于删除服务端的资源。

    GET          /users                # 查询用户信息列表
    GET          /users/1001           # 查看某个用户信息
    POST         /users                # 新建用户信息
    PUT          /users/1001           # 更新用户信息(全部字段)
    PATCH        /users/1001           # 更新用户信息(部分字段)
    DELETE       /users/1001           # 删除用户信息
    

    GET

    资源的读取,用GET请求,比如:

    GET /api/users
    // 表示读取用户列表
    

    GET应当实现为一个安全幂等的方法。用于获取数据而不应该产生副作用。

    POST

    资源的创建,用POST方法;

    POST 是一个非幂等的方法,多次调用会造成不同效果;

    幂等(Idempotent):如果对服务器资源的多次请求与一次请求造成的副作用是一样的的话,那这个请求方法可以被认为是幂等。

    比如下面的请求会在服务器上创建一个name属性为John的用户,多次请求就会创建多个这样的用户。

    POST /api/users
    
    {
      "name": "John"
    }
    

    PUT和PATCH

    用于更新的HTTP方法有两个,PUT和PATCH。

    他们都应当被实现为幂等方法,即多次同样的更新请求应当对服务器产生同样的副作用。

    PUT和PATCH有各自不同的使用场景:

    • PUT用于更新资源的全部信息,在请求的body中需要传入修改后的全部资源主体;
    • PATCH用于局部更新,在body中只需要传入需要改动的资源字段。

    设想服务器中有以下用户资源/api/users/123

    {
     "id": 123,
     "name": "Original",
     "age": 20
    }
    

    当我们往后台发送更新请求时,PATCH 和 PUT 造成的效果是不一样。

    PUT /api/users/123
    
    {
     "name": "PUT Update"
    }
    

    上述 PUT 请求操作后的内容是:

    {
     "id": 123,
     "name": "PUT Update"
    }
    

    可以观察到,资源原有的 age 字段被清除掉了。

    而如果改用 PATCH 的话,

    PATCH /api/users/123
    
    {
     "name": "PATCH Update"
    }
    

    更新后的内容是:

    {
     "id": 123,
     "name": "PATCH Update",
     "age": 20
    }
    

    请求中指定的name属性被更新了,而原有的age属性则保持不变。

    PATCH的作用在于如果一个资源有很多字段,在进行局部更新时,只需要传入需要修改的字段即可。否则在用PUT的情况下,你不得不将整个资源模型全都发送回服务器,造成网络资源的极大浪费。

    DELETE

    资源的删除,相应的请求HTTP方法就是DELETE。这个也应当被实现为一个幂等的方法。如:

    DELETE /api/users/123
    

    用于删除服务器上ID123的资源,多次请求产生副作用都是,是服务器上ID123的资源不存在。

    HEAD和OPTIONS

    HEAD和OPTIONS不太常用

    • HEAD:获取资源的头部信息,比如只想了解某个文件的大小、某个资源的修改日期等
    • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。针对非简单请求的CORS请求,会在正式通信之前增加一次HTTP查询请求,称为“预检”请求,对应的请求方法就是OPTION

    不符合CRUD的情况

    在实际资源操作中,总会有一些不符合CRUD的情况,一般会添加控制参数或者把动作转换成资源,Github采用的后者,比如『喜欢』一个gist,就增加一个/gists/:id/star子资源,然后对齐进行操作,『喜欢』使用PUT /gists/:id/star,『取消喜欢』使用DELETE /gists/:id/star

    查询参数

    REST风格的接口地址,表示的可能是单个资源,也可能是资源的集合;当我们需要访问资源集合时,设计良好的接口应当接受参数,允许只返回满足某些特定条件的资源列表。

    公共参数

    常规的公共查询参数有:

    参数名 作用
    offset 返回记录的开始位置
    limit 返回记录的数量
    keyword 提供关键词进行搜索
    sort 指定排序的字段
    orderby 指定排序方式

    具体来看:

    (1)以offsetlimit参数来进行分页:

    GET /api/users?offset=0&limit=20
    

    (2)使用keyword提供关键词进行搜索:

    GET /api/users?keyword=john
    

    (3)使用sort参数和orderby参数进行排序

    GET /api/users?sort=age&orderby=asc    // 按年龄升序
    GET /api/users?sort=age&orderby=desc   // 按年龄降序
    

    有的时候也可以只用orderby来进行排序:

    GET /api/users?se&orderby=age_asc      // 按年龄升序
    GET /api/users?se&orderby=age_desc     // 按年龄降序
    

    个性参数

    上面介绍的offsetlimitorderby是一些公共参数。此外,业务场景中还存在许多个性化的参数:

    【GET】  /v1/categorys/{category_id}/enable=[1|0]&os_type={field}&device_ids={field,field,…}
    

    注意不要过度设计,只返回用户需要的查询参数,此外,需要考虑是否对查询参数创建数据库索引以提高查询性能。

    语义化

    设计合适的API URL,以及选择合适的请求方法,可以语义化的描述一个HTTP请求的操作。

    当我们都熟悉且遵循这样的规范后,基本可以看到一个REST风格的接口就知道如何使用这个接口进行CRUD操作了。

    比如下面这面这个接口就表示搜索ID123的图书馆的书,并且书的信息里包含关键字game,返回前十条满足条件的结果。

    GET /api/libraries/123/books?keyword=game&sort=price&limit=10&offset=0
    

    同样,下面这个请求的意思也就很明显了吧。

    PATCH /api/companies/123/employees/234
    
    {
        "salary": 2300
    }
    

    状态码

    服务端会在响应头的status code中向用户返回的状态码,它说明了请求的大致情况,是否正常完成、需要进一步处理、出现的错误。大改分为几个区间:

    • 2xx,请求正常处理并返回
    • 3xx,重定向,请求的资源位置发生变化
    • 4xx,客户端发送请求错误
    • 5xx,服务端错误

    常见的有以下一些:

    状态码 状态信息 说明
    200 OK 请求成功
    201 Created 创建成功
    204 No Content 删除数据成功
    301 Moved Permanently 请求的资源已经永久性地移动到另外一个地方,
    后续所有的请求都应该直接访问新地址。
    服务端会把新地址写在Location头部字段,方便客户端使用
    304 Not Modified 请求的资源和之前的版本一样,没有发生改变。用来缓存资源
    400 Bad Request 请求语法错误,body数据格式有误,body缺少必须的字段等,
    导致服务端无法处理
    401 Unauthorized 未授权
    403 Forbidden 有授权(与401相对),但是被拒绝
    404 Not Found 客户端要访问的资源不存在
    405 Method Not Allowed 服务端接收到了请求,资源存在,但是不支持对应的方法。
    服务端必须返回Allow头部,告诉客户端哪些方法是允许的
    406 Not Acceptable 用户请求的格式不可得
    (比如用户请求JSON格式,但是只有XML格式)
    500 Internal Server Error 服务器发生错误
    503 Service Unavailable 服务器因为负载过高或者维护,暂时无法提供服务。

    错误处理

    当RESTful API接口出现非2xx的HTTP错误码响应时,采用全局的异常结构响应信息。

    一般来说,返回的信息中将error作为键名,出错信息作为键值即可。

    {
      error: "Invalid API key"
    }
    

    也可以采取下面的结构:

    HTTP/1.1 400 Bad Request
    Content-Type: application/json
    
    {
        "code": "INVALID_ARGUMENT",
        "message": "{error message}",
        "cause": "{cause message}",
        "request_id": "01234567-89ab-cdef-0123-456789abcdef",
        "host_id": "{server identity}",
        "server_time": "2014-01-01T12:00:00Z"
    }
    

    返回结果

    返回内容

    最好采用JSON作为返回内容的格式。如果用户需要其他格式,比如XML,应该在请求头的Accept字段中指定。

    对于不支持的格式,服务端需要返回正确的状态码并给出详细说明。

    返回规范

    针对不同操作,服务器向用户返回的结果应该符合以下规范。

    【GET】     /{version}/{resources}                    // 返回资源对象的列表(数组)
    【GET】     /{version}/{resources}/{resource_id}      // 返回单个资源对象
    【POST】    /{version}/{resources}                    // 返回新生成的资源对象
    【PUT】     /{version}/{resources}/{resource_id}      // 返回完整的资源对象
    【PATCH】   /{version}/{resources}/{resource_id}      // 返回完整的资源对象
    【DELETE】  /{version}/{resources}/{resource_id}      // 状态码 200,返回完整的资源对象。
    【DELETE】  /{version}/{resources}/{resource_id}      // 状态码 204,返回一个空文档
    

    Hypermedia API

    RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

    比如,当用户向api.example.com的根目录发出请求,会得到这样一个文档。

    {
      "link": {
        "rel": "collection https://www.example.com/zoos",
        "href": "https://api.example.com/zoos",
        "title": "List of zoos",
        "type": "application/vnd.yourformat+json"
      }
    }
    

    上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步该调用什么API了。rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题,type表示返回类型。

    Hypermedia API的设计被称为HATEOAS。Github的API就是这种设计,访问api.github.com会得到一个所有可用API的网址列表。

    {
      "current_user_url": "https://api.github.com/user",
      "authorizations_url": "https://api.github.com/authorizations",
      // ...
    }
    

    从上面可以看到,如果想获取当前用户的信息,应该去访问api.github.com/user, 然后就得到了下面结果。

    {
      "message": "Requires authentication",
      "documentation_url": "https://developer.github.com/v3"
    }
    

    其他

    1. API的身份认证应该使用OAuth 2.0框架。
    2. 服务器返回的数据格式,应该尽量使用JSON,避免使用XML。

    关于REST的更多详细规范,可以参考这个仓库

    参考

    展开全文
  • 数据库设计规范

    千次阅读 2018-02-20 00:24:12
    基于阿里数据库设计规范扩展而来 设计规范 【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循: 不是频繁修改的字段。 不是 varchar 超长字段,更不能是 text 字段。 ...

    基于阿里数据库设计规范扩展而来

    设计规范

    1. 【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循:

      • 不是频繁修改的字段。
      • 不是 varchar 超长字段,更不能是 text 字段。

      正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存 储类目名称,避免关联查询。

    2. 【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:如果预计2年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。

    3. 【推荐】id必须是主键,每个表必须有主键,且保持增长趋势的, 小型系统可以依赖于 MySQL 的自增主键,大型系统或者需要分库分表时才使用内置的 ID 生成器

    4. 【强制】id类型没有特殊要求,必须使用bigint unsigned,禁止使用int,即使现在的数据量很小。id如果是数字类型的话,必须是8个字节。参见最后例子

      • 方便对接外部系统,还有可能产生很多废数据
      • 避免废弃数据对系统id的影响
      • 未来分库分表,自动生成id,一般也是8个字节
    5. 【推荐】字段尽量设置为 NOT NULL, 为字段提供默认值。 如字符型的默认值为一个空字符值串’’;数值型默认值为数值 0;逻辑型的默认值为数值 0;

    6. 【推荐】每个字段和表必须提供清晰的注释

    7. 【推荐】时间统一格式:‘YYYY-MM-DD HH:MM:SS’

    8. 【强制】更新数据表记录时,必须同时更新记录对应的 gmt_modified 字段值为当前时间,

    命名规范

    1. 【强制】表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint ( 1表示是,0表示否)。
      说明:任何字段如果为非负数,必须是 unsigned。
      正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。
    2. 【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。 说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库 名、表名、字段名,都不允许出现任何大写字母,避免节外生枝。 正例:health_user,rdc_config,level3_name 反例:HealthUser,rdcConfig,level_3_name
    3. 【强制】表名不使用复数名词。 说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数 形式,符合表达习惯。
    4. 【强制】禁用保留字,如 desc、range、match、delayed 等,请参考 MySQL 官方保留字。
    5. 【强制】主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。
      说明:pk_ 即 primary key;uk_ 即 unique key;idx_ 即 index 的简称。
    6. 【强制】小数类型为 decimal,禁止使用 float 和 double。
      说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不 正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。
    7. 【强制】如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
    8. 【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长 度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。
    9. 【强制】表必备三字段:id, is_delete,gmt_create, gmt_modified。 说明:其中id必为主键,类型为unsigned bigint、单表时自增、步长为1。gmt_create, gmt_modified 的类型均为 date_time 类型,前者现在时表示主动创建,后者过去分词表示被 动更新。
    10. 【强制】所有命名必须使用全名,有默认约定的除外,如果超过 30 个字符,使用缩写,请尽量名字易懂简短,如 description --> desc;information --> info;address --> addr 等
    11. 【推荐】表的命名最好是加上“业务名称_表的作用”。 正例:health_user / trade_config
    12. 【推荐】库名与应用名称尽量一致。如health
    13. 【推荐】如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释
    14. 【推荐】所有时间字段,都以 gmt_开始,后面加上动词的过去式,最后不要加上 time 单词,例如 gmt_create

    类型规范

    1. 表示状态字段(0-255)的使用 TINYINT UNSINGED,禁止使用枚举 类型,注释必须清晰地说明每个枚举的含义,以及是否多选等

    2. 表示boolean类型的都使用TINYINT(1),因为mysql本身是没有boolean类型的,在自动生成代码的时候,DO对象的字段就是boolean类型,例如 is_delete;其余所有时候都使用TINYINT(4)

      TINYINT(4),这个括号里面的数值并不是表示使用多大空间存储,而是最大显示宽度,并且只有字段指定zerofill时有用,没有zerofill,(m)就是无用的,例如id BIGINT ZEROFILL NOT NULL,所以建表时就使用默认就好了,不需要加括号了,除非有特殊需求,例如TINYINT(1)代表boolean类型。

      TINYINT(1),TINYINT(4)都是存储一个字节,并不会因为括号里的数字改变。例如TINYINT(4)存储22则会显示0022,因为最大宽度为4,达不到的情况下用0来补充。

    3. 【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。

      类型 字节 表示范围
      tinyint 1 无符号值: 0~255;有符号值: -128~127
      smallint 2 无符号值: 0~65536;有符号值: -32768~32767
      mediumint 3 无符号值: 0~16777215;有符号值: -8388608~8388607
      int 4 无符号值: 0~4294967295;有符号值: -2147483648~2147483647
      bigint 8 无符号值: 0~((2³²×²)-1);有符号值: -(2³²×²)/2 ~ (2³²×²)/2-1
    4. 非负的数字类型字段,都添加上 UNSINGED, 如可以使用 INT UNSINGED 字段存 IPV4

    5. 时间字段使用时间日期类型,不要使用字符串类型存储,日期使用DATE类型,年使用YEAR类型,日期时间使用DATETIME

    6. 字符串VARCHAR(N), 其中 N表示字符个数,请尽量减少 N 的大小,参考:code VARCHAR(32);name VARCHAR(32);memo VARCHAR(512);

    7. Blob 和 Text 类型所存储的数据量大,删除和修改操作容易在数 据表里产生大量的碎片,避免使用 Blob 或 Text 类型

    索引规范

    1. 【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。

      不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明 显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必 然有脏数据产生。

    2. 【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时, 保证被关联的字段需要有索引。

      即使双表 join 也要注意表索引、SQL 性能。

    3. 【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度即可。 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度来确定。

    4. 【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。

      索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。

    5. 【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。

      正例:where a=? and b=? order by c; 索引:a_b_c 反例:索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引 a_b 无法排序。

    6. 【推荐】利用覆盖索引来进行查询操作,避免回表。
      说明:如果一本书需要知道第11章是什么标题,会翻开第11章对应的那一页吗?目录浏览一下就好,这个目录就是起到覆盖索引的作用。

      正例:能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的效果,用explain的结果,extra列会出现:using index。

    7. 【推荐】利用延迟关联或者子查询优化超多分页场景。
      说明:MySQL并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。

      正例:先快速定位需要获取的 id 段,然后再关联:
      SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

    8. 【推荐】SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。

      说明:

      1. consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。
      2. ref 指的是使用普通的索引(normal index)。
      3. range 对索引进行范围检索。
        反例:explain 表的结果,type=index,索引物理文件全扫描,速度非常慢,这个 index 级 别比较 range 还低,与全表扫描是小巫见大巫。
    9. 【推荐】建组合索引的时候,区分度最高的在最左边。
      正例:如果 where a=? and b=? ,a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即 可。

      说明:存在非等号和等号混合判断条件时,在建索引时,请把等号条件的列前置。如:where a>? and b=? 那么即使 a 的区分度更高,也必须把 b 放在索引的最前列。

    10. 【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。

    11. 【参考】创建索引时避免有如下极端误解

      • 宁滥勿缺。认为一个查询就需要建一个索引。
      • 宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。
      • 抵制惟一索引。认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。
    12. 总结

          • 索引占磁盘空间,不要重复的索引,尽量短  
          • 只给常用的查询条件加索引  
          • 过滤性高的列建索引,取值范围固定的列不建索引 
          • 唯一的记录添加唯一索引  
          • 频繁更新的列不要建索引  
          • 不要对索引列运算  
          • 同样过滤效果下,保持索引长度最小  
          • 合理利用组合索引,注意索引字段先后顺序  
          • 多列组合索引,过滤性高的字段最前  
          • order by 字段建立索引,避免 filesort  
          • 组合索引,不同的排序顺序不能使用索引  
          • <>!=无法使用索引
      

    SQL规范

    1. 【强制】不要使用 count(列名)或 count(常量)来替代 count(),count()是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。

      count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

    2. 【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,

      count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。

    3. 【强制】当某一列col的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为 NULL,因此使用 sum()时需注意 NPE 问题。

      正例:可以使用如下方式来避免sum的NPE问题:SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;

    4. 【强制】使用 ISNULL()来判断是否为 NULL 值。 说明:NULL 与任何值的直接比较都为 NULL。

      • NULL<>NULL的返回结果是NULL,而不是false。
      • NULL=NULL的返回结果是NULL,而不是true。
      • NULL<>1的返回结果是NULL,而不是true。
    5. 【强制】 在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。

    6. 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。 说明:以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为 级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻 塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

    7. 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

    8. 【强制】数据订正时,删除和修改记录时,要先 select,避免出现误删除,确认无误才能执行更新语句。

    9. 【推荐】in操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控
      制在 1000 个之内。

    10. 【参考】如果有全球化需要,所有的字符存储与表示,均以 utf-8 编码,注意字符统计函数 的区别。

      说明:
      SELECT LENGTH(“轻松工作”); 返回为12
      SELECT CHARACTER_LENGTH(“轻松工作”); 返回为4 如果需要存储表情,那么选择 utfmb4 来进行存储,注意它与 utf-8 编码的区别。

    11. 【参考】TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE 无事务且不触发trigger,有可能造成事故,故不建议在开发代码中使用此语句。 说明:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。

    12. 【推荐】不要写一个大而全的数据更新接口。传入为 POJO 类,不管是不是自己的目标更新字 段,都进行 update table set c1=value1,c2=value2,c3=value3; 这是不对的。执行 SQL 时,不要更新无改动的字段,一是易出错;二是效率低;三是增加 binlog 存储。

    13. 总结

      • 能够快速缩小结果集的 WHERE 条件写在前面,如果有恒量条 件,也尽量放在前面 ,例如 where 1=1  
      • 避免使用 GROUP BY、DISTINCT 等语句的使用,避免联表查 询和子查询 
      • 能够使用索引的字段尽量进行有效的合理排列  
      • 针对索引字段使用 >, >=, =, <, <=, IF NULL 和 BETWEEN 将会 使用索引,如果对某个索引字段进行 LIKE 查询,使用 LIKE   ‘%abc%’ 不能使用索引,使用 LIKE ‘abc%’ 将能够使用索引  
      • 如果在 SQL 里使用了 MySQL部分自带函数,索引将失效
      • 避免直接使用 select *,只取需要的字段,增加使用覆盖索引使用的可能  
      • 对于大数据量的查询,尽量避免在 SQL 语句中使用 order by 字
      句 
      • 连表查询的情况下,要确保关联条件的数据类型一致,避免嵌
      套子查询  
      • 对于连续的数值,使用 between 代替 in  
      • where 语句中尽量不要使用 CASE 条件  
      • 当只要一行数据时使用 LIMIT 1
      

    例子

    CREATE TABLE `health_package` (
      `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '序号',
      `package_id` int unsigned NOT NULL COMMENT '套系 id',
      `module_id`  int unsigned NOT NULL COMMENT '模块 id',
      `is_delete` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '是否删除,0-未删除,1-删除,默认为0',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Create time, common column by DB rules',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Modified time,common column by DB rules ',
      PRIMARY KEY (`id`)
    ) COMMENT='This table stores module and package of health for ...';
    
    展开全文
  • RTL设计之设计规范

    2019-02-26 12:32:46
    在新人刚开始接触RTL代码设计时,遵守适当的设计规范显的尤为重要!遵守设计规范,能够帮助我们避免一些常见的基础性错误,使设计的RTL代码具有更好的可读性、可综合性、稳定性和可靠性,能够避免后期浪费大量调试...
  • 接口设计规范

    千次阅读 2018-10-19 00:46:14
    文章目录接口设计规范1 接口示例2 基本规范2.1 公共参数2.2 响应数据2.3 字段类型规范2.4 上传/下载2.5 避免精度丢失3 瘦客户端4 拓展性5 安全性6 兼容性7 性能优化 接口设计规范 接口规范化以后,会少很多坑,避免...
  • PCB设计规范

    千次阅读 2018-08-16 08:42:44
    某公司PCB设计规范参考 (密码:8k1u) 华为印制电路板(PCB)设计规范V1.0(密码:54pw)
  • APP设计规范

    千次阅读 2019-04-30 13:43:00
    APP设计规范 设计师DPI指南 本指南旨在为初级到中级设计人员提供“入门”或介绍性阅读,他们希望从一开始就学习或获得有关跨DPI和跨平台设计的更多知识。尽可能少的数学和没有不可解析...
  • API设计规范

    千次阅读 2019-02-27 11:16:37
    1 端点规范 ...1.1端点的基本设计规范 短小便于输入 人可以读懂 没有大小写混用 方便修改 不会暴露服务架构 规则统一 1.2 HTTP方法和端点 端点和HTTP可以被认定是操作对象和操作方法的关系。 URI...
  • 这次想写下关于APP设计规范文档的内容,规范文档这个东西,实际上大部分中小型公司没有这方面的需求,也没精力去制作这样一个系统性的东西,所以文章篇幅不长。 但设计规范本身是个非常有助于保持产品品牌统一的好...
  • 4数据库字段设计规范 1最小模式 无符号省空间 过大的长度会消耗更多的内存 尽可能把所有列定义为not null 5数据库SQL开发规范6数据库操作行为规范
  • PDM设计规范

    2018-01-15 21:06:04
    pdm设计规范 1.设计Model注意事项: Models Properties中 code项填写 [系统id],name项填写 [系统名称] 2.设计Physical Diagram注意事项: Physical Diagram Properties中 code项填写 [模块id],name项填写 ...
  • 你了解UI设计的规范吗?  很多新人在开始做移动端UI设计的时候,对界面的尺寸规范不是那么清楚,很多时候都是凭借... UI设计规范是基于用户界面而制定的一套可复用设计库,也是为了方便设计师、开发和测试人员共同
  • 交互设计规范

    千次阅读 2014-01-10 17:14:35
    熟悉现有的设计规范 多学习精彩案例 站在巨人的肩膀上创新吧 以下为收集整理的网友的文档,仅供学习参考: 1[产品设计规范]vista用户体验指南 2[产品设计规范]界面组件级交互设计规范 3[产品设计规范]BS应用界面...
  • .NET设计规范————类型设计规范

    千次阅读 2016-07-17 22:24:26
    第四章类型设计规范从CLR的角度看,只有值类型和引用类型两种类型,但是从框架设计的角度我们把类型从逻辑上分了更多的组。如下所示: 类是引用类型的一般情况,占了框架中的大多情况,类的流行归于它支持面向对象...
  • .NET设计规范.pdf

    热门讨论 2010-07-14 17:33:25
    清晰版本.NET设计规范.pdf 清晰版本.NET设计规范.pdf 清晰版本.NET设计规范.pdf清晰版本.NET设计规范.pdf 清晰版本.NET设计规范.pdf 清晰版本.NET设计规范.pdf 清晰版本.NET设计规范.pdf
  • 随想002:设计规范

    千次阅读 多人点赞 2019-01-25 10:50:54
    嵌入式程序设计规范、原理图设计规范、PCB设计规范... 但是 试图用规范来消除重复错误的尝试可能是徒劳的! 规范能够起到多大作用,取决于研发人员的执行程度和理解程度。 问题往往出现在对规范的理解上,规范...
  • 所以,要明确的知道Web界面应该包含哪些基本要素及基本的设计规范,才能够进行高效的设计输出,当然,还要知道当下的web主流的设计方式有哪些。 设计规范存在的目的 1 在多人的团队里,通常不同的人员负责不同的流程...
  • 即将进入崭新的一年2017年啦,我们的移动端的UI设计规范也层出不穷。很多APP设计师也要在年底给公司或者是团队做一个总结。那么一个像样的APP ui设计规范也是很有必要的作品回顾。 另外,25学堂的小编相信大部分...
  • APP设计:(一)app界面常用设计规范

    万次阅读 多人点赞 2019-07-10 15:55:27
    app设计是一个看似简单...经过几年的发展逐渐成熟,也逐渐形成一些普适的设计规范,包括布局、各部件尺寸、字体运用等等。虽然说设计要创新,不能一成不变,但考虑到用户的使用习惯,提高用户体验感,在一些趋于统...
  • UI设计规范

    千次阅读 2015-06-10 09:23:55
    首先你需要学习的是三大平台的官方设计规范。 iOS开发者需要学习Android和WP平台的规范吗?需知,他山之石可以攻玉,在这些规范中都有一些理念是通用的,学习别家平台的设计可以为本平台的设计提供新思路。 ...
  • 苹果官方设计规范

    千次阅读 2020-07-12 23:54:01
    苹果官方设计规范:https://developer.apple.com/ios/human-interface-guidelines/ 设计尺寸 字体(苹方) 点和像素 Points and Pixels 图标 Icon 应用图标 App Icon 分辨率和显示规格 ...
  • 电商数据库设计 mysql 数据库设计规范
  • Android 设计规范整理

    千次阅读 2020-01-23 19:03:24
    Android UI 设计规范整理 一、屏幕尺寸关系 一般选择720*1280来作为设计稿 二、设计要点 1.UI间隔 大多数间距单位是8dp的整数倍,对齐间距和整体布局。较小的组件(如图标和排版)可以与4dp网格对齐 2.ui大小 ...
  • app项目设计规范

    千次阅读 2018-06-06 09:57:46
    Android项目设计规范 本文档为Android项目设计规范,编写初衷 清晰结构增强项目可阅读性 方便项目的日常维护 提高新需求的研发效率 1. 项目结构规范 * 模块包组织:同一模块,同一类功能建立共性名,...
  • UI设计规范-全文篇

    千次阅读 2019-05-24 15:48:04
    UI设计规范 1 1. 界面规范 1 1.1. 总体原则 1 1.2. 原则详述 2 1.2.1. 用户控制 2 1.2.2. 清楚一致的设计 2 1.3. 细节约定 3 1.3.1. 界面风格 3 1.3.2. 统一术语 14 关于UI规范的几点意见 15 深圳UI...
  • .NET设计规范————命名规范

    千次阅读 2016-03-27 17:11:03
    NET设计规范:约定、惯用法与模式前言: 最近在看《.NET设计规范:约定、管用法与模式》一书,主要还是讲.NET的设计规范,以前对这一块也不是特别在意,最近想要把这些系统的学习一下,以下基本上算是读书笔记吧。...
  • 我们在进行安卓APP设计时,需要好好调整之前的设计规范和设计细节。根据目前流行的安卓手机的系统体验来完成我们的安卓APP设计规范。应该说这是整理出最全面的安卓app设计规范。 1、安卓app设计规范之尺寸或分辨率 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 56,322
精华内容 22,528
关键字:

设计规范