图片来自Pexels本案例只是一个简单的模拟,可能与真实情况有出入,这里只是举个例子。案例:用户选择商品放入购物车,然后下单结算。流程如下:选择商品→下单→结账→生成订单→通知。提交订单的业务逻辑如下:验证账户是否合法→调用第三方接口查看商品优惠价→扣除钱包金额→生成订单信息→通知用户下单成功放置并等待交货。代码实现:@ServicepublicclassOrderServiceImplimplementsOrderService{@AutowiredprivateUserMapperuserMapper;@AutowiredprivateProductMapperproductMapper;@AutowiredprivateOrderMapperorderMapper;@AutowiredprivateKafkaTemplatekafkaTemplate;/***购买商品,提交订单*@paramuserId用户ID*@paramproductId商品ID*@return*/publicResultsubmit(LonguserId,LongproductId)throwsBizException{//验证账号UserDOuserDO=userMapper.findById(userId);if(userDO==null){throwBizException(USER_NOT_EXISTS);}//查看商品信息和折扣信息ProductDOproductDO=productMapper.findById(productId);Doubledelta=HttpUtils.getDiscount(productId);doubleactualPayment=productDO.getPrice()-delta;Moneymoney=userDO.getMoney();if(actualPayment>money.getRemain()){//如果产品价格-优惠价格>用户钱包,则表示支付不够返回结果。fail("Insufficientbalance");}//钱包足够支付,扣除金额doubleremain=money.getRemain()-actualPayment;money.setRemain(remain);//更新账户钱包余额userMapper.update(userDO);//生成订单信息OrderDOorderDO=newOrderDO();orderDO.setUserId(userId);orderDO.setProductId(productId);orderMapper.save(orderDO);//通知用户订单已经生成,等待收货随着业务的迭代,可能会出现很多问题。①可维护性差。XxMapper基于Mybatis实现了数据操作层,也将技术细节带入了业务逻辑。如果技术实现发生变化(改用Hibernate或Mybatis版本升级导致使用变化等),业务代码也得改。xxDO是和数据表绑定的,数据表结构的变化也会影响到业务代码。调用第三方API,直接在业务代码中调用HttpUtils即可。以后如果第三方API修改了方法签名或返回值,或者RPC接口发生变化,业务代码也会随之变化。直接使用KafkaTemplate发送消息。如果技术选型改为使用RocketMQ,那么业务代码也得改。②可扩展性差。若商品因活动有其他优惠,或商品某段时间无优惠,将重新更改原码。业务逻辑与数据存储结构强依赖,数据存储结构变化对业务的影响可想而知。③可测性差由于直接依赖数据库、第三方接口、中间件,所有技术都需要落地才能进行测试,测试成本和时间都比较大。代码优化——我们上面说过,数据库操作不应该直接暴露给业务逻辑,所以数据库操作是“隔离”的。publicinterfaceUserRepository{UserfindById(LonguserId);}添加了XxRepository接口,业务逻辑直接依赖于接口/抽象而不是实现。Repository是数据仓库,不一定是DB,也可以是其他数据操作。Repository返回的对象也不是DO,与数据库结构无关。代码优化2.DO对象只有set和get操作,没有其他行为。我们说这有时候是一种贫血现象,会导致本该在业务域实体中做的事情,分散在各个服务中,低内聚,不好维护。添加域实体,相关行为直接在实体内部完成(高内聚):publicclassMoney{privatedoubleremain;publicdoublegetRemain(){returnremain;}publicvoidsetRemain(doubleremain){this.remain=remain;}/***deduction*@paramdelta*@return*/publicbooleancharge(doubledelta){if(remain
