我们的名字叫乘法云。我们在挑战的问题是

从业务想法到软件上线,速度如何提高10x?

上一篇文章中,我们写了一个很简单的从前端直接提交改动到后端的例子。在复杂业务下,显然是不允许前端直接改数据库的数据,毕竟浏览器不是受信的执行环境。业务规则还是必须要在后端验证的。这篇里我们来看一下对于表单提交这个场景,乘法云是如何简化开发的。

Form Demo

图片描述

这个表单例子的运行时效果如上图所示。

代表数据库表的 Reservation.ts

@sources.Mysql()
export class Reservation extends Entity {
    public seatCount: number;
    public phoneNumber: string;
}

建表 SQL,注意 phoneNumber 上有唯一性约束:

CREATE TABLE `Reservation` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `phoneNumber` varchar(255) NOT NULL UNIQUE,
  `seatCount` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;

然后就是代表这个表单的 FormDemo.xml

<Card title="餐厅座位预定" width="320px">
    <Form>
        {{ message }}
        <Input :value="&phoneNumber" label="手机号" />
        <InputNumber :value="&seatCount" label="座位数" />
        <Button @onClick="onReserveClick">预定</Button>
    </Form>
</Card>

验证逻辑,以及前后端交互的代码都在同一个文件里 FormDemo.ts

@sources.Scene
export class FormDemo extends RootSectionModel {
    @constraint.min(1)
    public seatCount: number;
    @constraint.required
    public phoneNumber: string;
    public message: string = '';

    public onBegin() {
        this.reset();
    }

    public onReserveClick() {
        if (constraint.validate(this)) {
            return;
        }
        this.saveReservation();
        setTimeout(this.clearMessage.bind(this), 1000);
    }

    @command({ runAt: 'server' })
    private saveReservation() {
        if (constraint.validate(this)) {
            return;
        }
        const reservation = this.scene.add(Reservation, this);
        try {
            this.scene.commit();
        } catch (e) {
            const existingReservations = this.scene.query(Reservation, { phoneNumber: this.phoneNumber });
            if (existingReservations.length > 0) {
                this.scene.unload(reservation);
                constraint.reportViolation(this, 'phoneNumber', {
                    message: '同一个手机号只能有一个预定',
                });
                return;
            }
            throw e;
        }
        this.reset();
        this.message = '预定成功';
    }

    private reset() {
        this.seatCount = 1;
        this.phoneNumber = '';
    }

    private clearMessage() {
        this.message = '';
    }
}

乘法云相比传统技术有以下创新点

  • 前后端共享了 validate() 方法,以及 reset() 方法
  • 后端可以通过 this 拿到前端的表单,并且通过 this 直接修改前端的表单,就好像 saveReservation 这个方法是在浏览器里执行的一样。

通过省去了前后端 RPC 交互的 Request/Response 结构体的定义,可以减少数据拷贝来拷贝去的代码,减少系统中的概念。你可以把表单本身想像为人和机器"RPC"交互的 Request/Response 结构体,所以只是在前后端交互的时候复用了同一个结构体定义而已。

当然如果 this 本身并没有绑定到界面,那么这个结构体就是纯粹服务于前后端RPC的接口定义的用途。也就是我们完全可以定义一个 NewReservationProtocol 的对象,然后由这个对象来完成前后端的RPC。这样就和传统的定义后端API的做法没有区别了。只是这里给了额外一个选择,就是不要这个额外创造出来的中间状态,选择和前端表单复用同一份状态。如何选择,当然是取决于context啦。

下一篇我们会展示更复杂更能体现差异的一些例子,敬请关注。

求前端人才

我们为顶尖工程师提供了与之相配的技术发挥空间、无后顾之忧的宽松工作环境以及有竞争力的薪酬福利。同时也为高潜质的行业新人提供充分的学习和成长机会。

这里,没有996,崇尚高效。
这里,话语权不靠职级和任命,靠的是代码的说服力。
这里,不打鸡血,我们用理性和内驱力去征服各种挑战。
这里,也会有项目排期,但不怕delay,我们有充足的时间,做到让自己更满意。

工作地点在北京西二旗,薪酬待遇见招聘链接:https://www.zhipin.com/job_de...


taowen
4.1k 声望1.4k 粉丝

Go开发者们请加入我们,滴滴出行平台技术部 taowen@didichuxing.com