`

(转)如何优雅进行表和字段命名

 
阅读更多
原文:
https://zhuanlan.zhihu.com/p/20785905

作者:仁风H
链接:https://zhuanlan.zhihu.com/p/20785905
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

数据库表结构设计作为后端软件开发不可或缺的一环,是每个后端工程师都会经历的过程。笔者也多次经历过这样的过程,也尝试过多种不同的设计方案,也从一些优秀的框架中学到不少,但并没有发现相关的文章对其进行总结。所以本文尝试把笔者看到的、学到的总结下来,希望对阅读本文的读者有所启发。

表结构设计主要有两个目的,一是让表结构更加的更具有表现力,做到数据库表的自描述,减少注释甚至不使用注释;二是满足系统效率和扩展性的需要,让系统性能更好,后期维护更简单。

本文主要探讨的是如何优雅的设计表结构,让人能够直观的从命名中窥探设计意图,传达设计者的设计目的,让团队成员达成共识,减少沟通成本。本文不讨论表结构设计对性能的影响,也不讨论数据库设计中的范式与反范式设计。本文将从数据库表的命名和字段的命名两个方面展开。

数据库表的命名

使用名词作为表名

仔细想想便可发现,数据库表中存在的所有数据都是现实世界各种操作的结果,它们有的是中间过程结果,有的是最终数据结果。不论怎样,它们是一份一份没有任何动作的,静态的记录。而表本身就是存储这些记录的容器,从这样的层面理解,表名应该采用名词的形式是完全符合逻辑的。

比如我们要设计一个存储用户邀请的表,invitation 就比 invite 更加的优雅。

相关表采用统一前缀

我们知道,大型系统的设计往往按模块或者子系统进行划分,一个一个模块的处理问题,保证模块间的低耦合,模块内的高内聚。数据库表设计也一样,我们可以对相关联的表采用相同的前缀,使开发人员一眼看上去就知道哪几个表是相关的。

比如对于用户基本信息表、用户的详细信息表和用户的微信绑定表如下的命名更可取:

user
user_profile
user_wechat
字段的命名

本节先介绍几个比较通用的原则,使得字段的含义更容易理解,描述性更强,之后进行简单的总结分类,以便让我们明白这些原则背后的逻辑。

使用动词被动形式+描述性后缀

通过前面我们知道,数据库表中的所有记录都是静态的结果性数据,它是由一定的用户操作产生的。那么它是如何产生的?经过什么样的操作产生的呢?
在解答之前先看一个例子,下面是一个简单的 article 表结构:

id: integer
title: varchar
content: text
user_id: integer
create_time: timestamp
这样的设计本身是没有问题的,目前用的也很多。这个设计主要的问题是没有体现出 user_id 与这篇文章的关系,需要经过一定的猜测和思考才能得出。create_time 虽然还比较直观,但没有体现出这篇文章实在过去的某个时间创建的。

然后我们在来看修改后的设计:

id: integer
title: varchar
content: text
created_by: integer
created_at: timestamp
通过把 user_id 替换为 created_by、create_time 替换为 created_at,使得我们更容易理解对应的文章是被指定的人在指定的时间创建出来的,而不需要我们的多方猜测或者查阅文档,使得整个表结构的描述性更强。
时间区分当前时间和未来时间

英语中表时间的时候, at 一般跟一个时间点,而 in 有表示在未来的某个时间之内的意思。结合起来,笔者倾向于用 at 表示过去或者现在的时间,而用 in 表示未来的时间。比如日历中的 event 有开始时间和结束时间的概念,我觉得如下的命名是比较合理的:

starts_at 事件的开始时间,相对 ends_in 它属于当前时间,采用 _at 后缀
ends_in 事件的结束时间,相对 ends_in 它属于未来时间,从用 _in 后缀
其他我们比较常用的比如 created_at、updated_at、expires_in 都属于这种类型。

使用第三人称单数

当我们采用动词+介词的时候我更倾向与使用第三人称单数,因为字段描述的这个实体是单数的,通过使用第三人称单数,我们可以自然语言的方式表达出需要的意思。比如以 event 为例,翻译成英语是这样的:

The event starts at 2016-05-05 12:00:00
完全符合英语的语法,也表达了我们想要表达的意思。

区分单数与复数

单数与复数主要是对字段内容的描述,比如通知(notification)有接收人这个字段,如果我们需要通知能够发送给多个人,那么 receivers 这样的字段名称明显好于 receiver,因为 receivers 体现了通知可以发送给多个人这一个事实。

前面从四个原则出发介绍了如何让字段更具有描述性,简单总结下来我觉得从语义上来说,字段可以分为两种类型:描述性字段和动作性字段。

描述性字段是对对应数据库记录(或者说实体)的补充说明,比如以人作为实体,那么人的身高、体重和血压就属于这类描述性字段。

描述性字段如果是动词+介词的形式,动词需要采用第三人称单数的形式,比如 starts_at。然后根据字段的内容,如果内容有多个元素或实体,我们需要使用复数,否则使用单数形式。

动作性字段不仅能对所属实体进行补充说明,还能对这个实体的所涉及操作有所描述。比如我们有 article 这个实体, article 的 created_by 和 created_at 就属于动作性字段,因为它不仅表达了 article 的创建者和创建时间这层信息,它还表达了这个 article 是指定的人被创建的,而不是凭空生成的。
分享到:
评论

相关推荐

    SpringBoot+Mybatis,返回Map的时候,将Map内的Key转换为驼峰的命名

    在Java编程中,驼峰命名法(Camel Case)是常用的变量和方法命名规则,它使得代码更易读、更符合编程规范。然而,数据库中的字段名通常采用下划线命名法(Underscore Case),如`user_name`,这与Java中的驼峰命名法...

    C#下的SQL Server命名规范

    3. **避免使用SQL保留关键字**:与表命名相同,字段命名也应避免使用SQL保留关键字。 4. **ID字段统一命名为`id`**:每个表的主键统一命名为`id`,以保持一致性。 - 示例:`departments`表中的`id`字段表示部门...

    优雅的对象转换解决方案,为什么更推荐MapStruct呢.docx

    - 使用反射库如Apache的BeanUtils或BeanCopier可以简化转换,但它们依赖于属性名称和类型的完全匹配,这在不同团队间可能存在命名差异的情况下并不适用。此外,反射操作对性能有一定影响,尽管可以通过缓存提高效率...

    用ASP.NET在同一网页中显示主从关系表的相关数据

    - **对于主表**:字段名行对应的Table ID命名为`t0`;每条记录行对应的Table ID则依次命名为`t1`, `t2`, …, `tn`(n为记录行的数量),而与这些记录行Table相对应的ImageButton的ID则命名为`e1`, `e2`, …, `en`。 ...

    C#命名规范

    本文基于一份关于C#命名规范的资料,对其进行详细解读,旨在帮助开发者更好地理解和应用这些规范。 #### 二、文件头部注释 在每个C#文件的顶部,应包含版权和文件信息等注释。例如: ```csharp /*---------------...

    asp.net路径转向实例

    在ASP.NET中,路径转向通常通过`System.Web.Routing`命名空间中的类和方法来实现。这个实例将深入探讨如何在C#编程环境下使用ASP.NET进行路径转向。 首先,我们要理解ASP.NET路由的基本概念。路由是一种规则,它...

    Go语言json编码驼峰转下划线、下划线转驼峰的实现

    但是这种方式不够优雅,尤其是当结构体包含大量字段时,手动添加标签将是一项耗时且容易出错的工作。 #### 三、解决方案概述 为了解决上述问题,本文提出了一种通用的方法,通过自定义结构体并实现`MarshalJSON`...

    xStream完美转换XML、JSON

    例如,设置日期格式,忽略某些字段,或者自定义命名策略。 ```java XStream xstream = new XStream(); xstream.autodetectAnnotations(true); // 自动检测注解 xstream.processAnnotations(Person.class); // 处理...

    让Laravel的数据迁移优雅地创建MySQL fulltext -mysql-fulltext-laravel.zip

    全文索引是数据库中用于提升大型文本数据搜索速度的特殊索引类型,它可以对文本字段中的词进行索引,以快速找到含有指定词汇的记录。 为了解决Laravel框架与MySQL全文索引结合使用的复杂性,开发者们需要寻找一种...

    赏心悦目的SQL-教你怎么写的美观

    1. **缩进与空格**:在创建表或定义字段时,使用适当的缩进和空格可以使代码更加清晰。例如,每个字段定义应该单独占一行,并在逗号后添加空格,如`[IpAddress] [nvarchar](15) NOT NULL,`。 2. **注释**:在复杂的...

    C++读取GPS并解析 NMEA 数据轨迹绘制,提供完整源代码(代码优雅无BUG)

    遵循良好的编程实践,如清晰的命名规则、模块化设计、注释和文档,以及适当的测试,以确保代码的优雅和无错误运行。 9. **文件“gps_g60”**: 这个文件可能是项目中的一个源代码文件,可能包含了具体的GPS数据...

    自制图片格式转换和保存入库工具源码

    图片格式转换涉及到对图片数据的读取、解析和重新编码,这通常通过使用图像处理库如.NET Framework中的System.Drawing命名空间来实现。 2. C#类:C#是一种面向对象的编程语言,它的核心是类。在这个项目中,可能会...

    hibernate的继承映射关系

    这种方式需要在根类对应的表中增加一个字段来标识具体类的类型,通常命名为class或者subclass,以此来区分不同子类的实例。例如,对于Employee类的表,可以通过一个名为type的字段,其值可以是“HourlyEmployee”或...

    通过实践编写优雅的JavaScript代码

    ### 变量和字段命名 变量和字段的命名对代码的可读性有极大的影响。在JavaScript代码中,变量名应该反映它所代表的数据的含义。例如,使用`currentYear`来代替`y`,使用`daysSinceLastVisit`来代替`daysSLV`。避免...

    Demo02职工管理系统——链表版.7z

    为了提高代码的可读性和可维护性,可以遵循良好的编程习惯,如适当的命名、注释和封装。 此外,C++中的异常处理也非常重要,特别是在处理可能失败的操作(如动态内存分配或无效的输入)时。确保在可能出现错误的...

    C#编程规范

    - **使代码的逻辑更清晰、更易于理解**:良好的命名和结构化可以帮助读者快速理解代码意图。 **术语定义** - **Pascal大小写**:用于标识符,首字母以及后续每个单词的首字母均大写,如`BackColor`。 - **Camel大...

    链表学生成绩管理系统

    在实际项目中,为了确保代码的可维护性和可读性,通常会遵循良好的编程实践,如使用注释来解释代码的功能,遵循命名约定,以及适当的错误处理机制。此外,还可能使用设计模式,如迭代器模式,来更优雅地遍历链表。 ...

    Laravel开发-eloquent-single-table-inheritance

    - 首先,你需要创建一个基础模型类,通常命名为`BaseModel`,并指定与之关联的数据库表。 - 然后,为每种类型创建一个子模型,如`UserModel`, `AdminModel`等,它们都继承自`BaseModel`。 - 在每个子模型中,可以...

    mybatis代码生成工具

    【描述】提到的“修改了字段的注释方式”意味着在生成的代码中,对于数据库表的字段,该工具会生成更加优雅和易读的注释。这不仅提升了代码的可读性,也有助于团队成员更好地理解数据模型和业务逻辑。"欢迎体验下载...

    gson源码.rar

    6. **FieldNamingPolicy**: 定义了字段命名策略,如默认的、下划线转驼峰等,用于处理Java字段和JSON键之间的映射。 7. **ExclusionStrategies**: 允许用户定义哪些字段在序列化或反序列化过程中被忽略。 8. **...

Global site tag (gtag.js) - Google Analytics