我们的名字叫乘法云。我们在挑战的问题是
从业务想法到软件上线,速度如何提高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...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。