初识

作者: EGGIP | 来源:发表于2020-03-31 00:03 被阅读0次

    翻译自Designing with types: Introduction

    一个熟悉的例子

    为了逐步向你展示类型的威力,我将采用一个非常基本,但是很能说明问题的例子,如下:

    type Contact = {
        FirstName: string;
        MiddleInitial: string;
        LastName: string;
    
        EmailAddress: string;
        // 邮箱是否被验证过
        IsEmailVerified: bool;
    
        // 通讯地址1
        Address1: string;
        // 通讯地址2
        Address2: string;
        City: string;
        State: string;
        // 邮政编码
        Zip: string;
        // 地址是否被验证过
        IsAddressValid: bool;
    }
    

    我们定义了一个Contact类型,我相信你一定经常见到这样的代码,那我们会如何通过类型系统对它进行重构呢?

    使用“原子”类型

    作为一个切入点,你可以问这样一些问题:我们会如何对这个实体进行更新?有哪些业务规则?

    对于Contact而言,也许你可以问产品经理:Address1不变的情况下,Zip可以变吗?他们是关联的吗?当然有些东西我们不用追问也知道,例如FirstNameEmailAddress之间是没有什么关联的。

    通过这些探讨,我想大家都应该看出一个设计原则:

    物以类聚,人以群分

    将彼此关联的东西放在一起,以便维持它们的一致性;反过来,千万不要将彼此不相关的东西凑一起。

    在这个例子中,很明显一共有三组:姓名、邮箱地址、通讯住址。

    当然这里面还有两个标志字段:IsEmailVerifiedIsAddressValid,它们应该分属于邮箱地址和住址吗?就目前而言,算是吧,毕竟它们之间有那么一丁点联系。例如:如果邮箱地址更新了,那么IsEmailVerified将会被重置为false

    对于通讯地址,这里还是值得深思熟虑一下。似乎将地址这个概念单独的抽取出来,形成一个公共类型将是非常有用的。当然IsAddressValid这个标志字段还是应该和地址关联在一起,理由同上。这么看来,我们将定义两个类型:

    1. PostalAddress:代表通用的通讯地址
    2. PostalContactInfo:代表通讯联系信息

    如下:

    type PostalAddress = {
        Address1: string;
        Address2: string;
        City: string;
        State: string;
        Zip: string;
    }
    
    type PostalContactInfo = {
        Address: PostalAddress;
        IsAddressValid: bool;
    }
    

    最后,我们可以用上option类型来润色一下。

    type PersonalName = {
        FirstName: string;
    
        // 通过option类型代表MiddleInitial是可选的
        MiddleInitial: string option;
        LastName: string;
    }
    

    成果

    type PersonalName = {
        FirstName: string;
        MiddleInitial: string option;
        LastName: string;
    }
    
    type EmailContactInfo = {
        EmailAddress: string;
        IsEmailVerified: bool;
    }
    
    type PostalAddress = {
        Address1: string;
        Address2: string;
        City: string;
        State: string;
        Zip: string;
    }
    
    type PostalContactInfo = {
        Address: PostalAddress;
        IsAddressValid: bool;
    }
    
    type Contact = {
        Name: PersonalName;
        EmailContactInfo: EmailContactInfo;
        PostalContactInfo: PostalContactInfo;
    }
    

    现在,我们还没有定义任何的方法或函数,但是这些代码已经更好的体现出了领域概念。这仅仅是开始!

    相关文章

      网友评论

          本文标题:初识

          本文链接:https://www.haomeiwen.com/subject/oukiuhtx.html