钉钉背后的故事(1)— Typescript 解决复杂数据结构

dingding.jpeg

我最近也是一直在做办公系统,所以自然也少不了关注竞争对手,其中少不了阿里的钉钉,钉钉最初只有 4 个前端,继续 nw.js 开发出他们的第一版桌面应用,可能是因为没有 native 工程师吧。先来看看,nw.js 我接触还是比较早,还是 2015 我就做了个 Demo。2016 年底实际做了一个项目,用这个封装了web 的即时通讯打包成 Mac 和 window 版本桌面。

web 框架钉钉最初用得就是 angular,现在好像也使用 react。angular 我接触的比较早,好时候正好闲着在家接触 google 最新版的 angular2。因为之前已经接触过一段 javascript 也用过 jquery 做过一些项目。不过 angular2 完全推翻了我对 javascript 的认知,以及对前端 web 应用开发过程认知。我通过学习 angular2 到现在回头看收益匪浅。然后就开始学习了 react。

typescript 我也是接触比较早的,angular2 需要用 typescript 开发,所以才边学 angular 变学 typescript 的。typescript 是 c# 语言架构师设计的。当初还不了解为什么要用 typescript,随着不断学习现在逐渐了解为什么使用 typescript 来开发的原因。


png-city-map-this-program-is-a-bit-more-complicated-than-the-fly-through-cities-a-bit-under-300-lines-of-code-but-it-s-still-quite-simple-this-speaks-to-the-power-of-408.png

业务复杂,数据模型复杂业务逻辑复杂

钉钉有上百 rpc 接口,这些接口的地址、参数和返回值都需要各个平台的前端进行了解,这些接口可能被不同语言进行调用,所以需要一种通用描述语言来讲接口对应不同的语言。为了满足不同业务在钉钉有几十种的消息推送。


avengers-age-of-ultron.jpeg

所以在前端有大量数据结构,javascript 作为动态语言,没有数据类型的提示和检查,对应钉钉这样复杂大型的应用 javascript 可能显得力不从心,但是 javascript 对于跨平台又是最好选择,所以钉钉引入了 typescript 对类型进行控制。

钉钉的解决方法使用 typescript 开发前端
通过定义接口描述 idl 来支持多平台的应用开发

实时性要求高,对异步要求也是很高的

前端采用 rxjs 进行响应式编程。Rx 在响应式编程中已经占据不可动摇位置,我在 Android 编程中就用大 RxAndroid。不过看他是不是可以挡得住 Kotlin 的 corutine 的冲击


iron-man-vs-thanos.jpg

下面就是一个示例,这是示例是由钉钉开发者大会上演示示例

export const getUserById(){

}

user = {

    "uid":"1",
    "nickName":"zidea",
    "sex":"M",
    "bio":"",
    "isActive":true,
    "org":{
        "mainOrgId":"",
        "orgList":[
            {
            }
        ]
    }
}

这么复杂数据类型我们需要经验和反复才能记下来,而且有的数据类型是可选的例如这里 org 字段内容如果个人注册那么他用户信息中就没有这个字段。钉钉又不能把这些潜在的个人用户挡在门外,所以这个 org 字段是可选。
我们可以通过 typescript 以接口形式定数据类型和限制数据类型,这样使用这个数据类型时候就会在编译中检查,从而避免一些不必要的麻烦。


export enum SEX{
    Male = 'M',
    Female = 'F'
}

export interface IDepartment {
    departId:string,
    departName:string
}

export interface IOrgItem {
    orgId:string,
    orgName:string,
    departmentList:IDepartment[]
}

export interface IOrg{
    mainOrgId:string;
    orgList:IOrgItem[]
}

export interface IUSer{
    uid:number;
    nickName:string;
    sex:SEX;
    avatar:string;
    bio:string;
    isActive:boolean;
    org?:IOrg;
}

export const getUserById = (uid:number):Promise =>{
    return fetch('/users?id=' + uid).then(
        (reponse) => reponse as IUSer
    )
}

而且大家注意到了 org? 表示 org 是可选。

你可能感兴趣的:(钉钉背后的故事(1)— Typescript 解决复杂数据结构)