Technicalarticles
问 [不存价格字段不行吗?直接查询商品表获取价格]
答 [如果价格更新,应提示用户,商品的浮动信息。可以选择直接更新购物车,或者单独建立一个表,来记录更新的价格和信息,类似京东]
问 [联表查询可以从商品表中知道商品是否上架]
答 [商品不存在了如何联,只会将逻辑整复杂,未来包括降价提醒,无货提醒,下架提醒,购物车该如何查询就成了一个问题]
以下为在业务层面、逻辑层面、未来功能的可扩展性、编码的复杂度、数据统计层面来解释下购物车的设计。
业务上来看,无论是多表查还是单表存都是合理的,列出以下在购物车上的相关部分业务
库存不足提醒 (提高付款概率)
降价提醒 (提高付款概率)
商品下架提醒
有关商品的商品优惠券或其他活动 (提高付款概率)
以技术角度说明
多表的降价提醒需要第三张表支撑 <商品修改记录表>
这时购物车内的商品与商品表存在关联,检测降价的系统就需要在商家修改价格时将检测结果后查询加入本商品的购物车,顺便去查询商家修改前价格,算出差价,发送到队列或者其他的手段,用户接收到降价通知,刺激消费。这时你发现,这貌似没有什么地方有问题,如果这时候需要增加一个业务,按照用户加入购物车的时间,提示他在加入购物车后这段时间降价多少?这时是否需要在来个加入购物车的记录表,这样不断的多级关联,看似没有问题,实际将业务耦合,一次sql要关联N个表,如果这时增加sku和spu那就更不用说了。在未来量级上升后是支撑不住的,并且也不方便扩展。
[我的设计并不是最好的,仅此参考] , 在考虑到未来业务不断增加的问题,我是将价格与标题和商品的SKU加入到购物车表内,在商户修改时无需关心其他表,直接检索与修改商品相关的购物车,拿出价格,计算差价,提示用户。如果计算加入购物车这段实际降价多少,这其实与上述操作一样,对于单表的设计上,这2种需求实为一种解决方案。在查询上也是一条sql语句的实现。
当然,我们还是需要关联上,不知道未来的某一天就用的上了呢?
有很多场景,都要将标题呀,内容呀直接存储,类似与收藏的店铺和商品,无论卖家怎么做,用户购物车,订单不能动,这是基准。
商品下架,用户的购物车实际是不能动的,某猫的做法是使其变灰,让用户自行删除。
商家分很多种,商品的标题,图片或者分类修改了,都属于下架,这时的多表关联查询就彻彻底底的失效了。
其实商品的下架应该直接通知购物车下架 (变灰),并非关联查询是否下架。如果你非要这样做,那你依旧需要做一些表去记录。
我并不是说不需要做记录。而是记录的表实际是不参与业务查询的。
逻辑这里特指代码的架构编写。以php为例,可以参考我之前的文章 https://segmentfault.com/a/11...
在逻辑方面,要考虑方面比较多,类似sql的性能,代码的性能,服务器的性能等。尽量避免多表查询吧。
百度百科的定义是
可复用性(Reuseability)复用又叫重用,是重复使用的意思。目前,一般软件的复用率并不高,尤其在国内。复用的好处可以得到 较高的生产效率以及随之而来的成本降低、较高的软件质量(错误可以更快的被纠正)以及 恰当的使用复用可以改善系统的可维护性。
在购物车的设计上,重用主要提现在商品信息的存储方式上,避免多次去联表查询,在业务量大后的份表分库提现会更明显。
百度百科的定义是:
设计良好的代码允许更多的功能在必要时可以被插入到适当的位置中。这样做的目的的是为了应对未来可能需要进行的修改,而造成代码被过度工程化地开发。
正常购物车、商品、优惠券都是独立的系统及功能,不要看做商品在购物车内。现实和逻辑并非是一脉相承的。就假设在实际生活中,物品仅仅是放在购物车中,如果不结账,依旧不属于自己。为了方便扩展更多业务,尽量在设计之初,功能与功能之间不要“粘”在一起。
百度百科的定义是:
系统的可维护性是衡量一个系统的可修复(恢复)性和可改进性的难易程度。所谓可修复性是指在系统发生故障后能够排除(或抑制)故障予以修复,并返回到原来正常运行状态的可能性。而可改进性则是系统具有接受对现有功能的改进,增加新功能的可能性。
购物车的设计之初也是考虑未来商品的业务功能各种变更。不如简单点,直接将其属性存到购物车。
初期的设计,决定未来开发及重构的复杂度。功能与功能,系统与系统之间尽量避免直接关联。
后期的数据统计、计算也会受到前期设计的影响。
为何单独建这个表,也是又一定原因的,正常只需要member_cart_item表即可,根据实际下线的业务场景,正常购物到超市需要拿一个购物车,但这个购物车并非属于你,你使用之后,需要归还,他人可继续使用,将购物车公开化,并不是将购物车商品公开化。业务场景比较窄,例如京东到家和京东商城一样(我只是举例,并不清楚他们怎么做的),购物车不通用,那如何区分呢,是应该在购物车上区分还是在购物车商品上区分?我想你已经清楚了。
CREATE TABLE `member_cart` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`member_id` int(11) NOT NULL COMMENT '用户编码',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `member_cart_member_id_unique` (`member_id`),
KEY `member_cart_member_id_index` (`member_id`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
这块需要提的一点是 [并不是所有表的设计都是互相绑定,互相依赖的],就例如购物车商品表,不仅仅将商品编码存储在内,还要将商品价格,商品的简介以及商品的规格(既SKU)存储,不能因卖家下架商品,而查询不到商品的存在,比较一切以用户为主,用户是上帝的原则,不能让商品悄悄的就消失了吧。所以在做购物车商品表查询时,切记不要使用join或者表关联查询
CREATE TABLE `member_cart_item` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`cart_id` int(11) NOT NULL COMMENT '购物车编码',
`product_desc` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品sku信息',
`product_img` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品快照',
`product_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品名称',
`price` decimal(8,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
`product_id` int(11) NOT NULL COMMENT '商品编码',
`supplier_id` int(11) NOT NULL COMMENT '店铺编码',
`sku_id` int(11) NOT NULL COMMENT '商品sku编码',
`number` int(11) NOT NULL DEFAULT '1' COMMENT '商品数量',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `member_cart_item_cart_id_product_id_supplier_id_index` (`cart_id`,`product_id`,`supplier_id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
DO U LIKE?