引子

十几年前的一天,有段时间在读张爱玲的小说,同事看见了就说原来你爱看这种东西。我到现在都不知道他说的是哪种东西。那时候我只是单纯的觉得张爱玲写的东西有种特质,这种特质掌握了做什么事情都不会太差。后来我想明白了,这种特制叫做:善于运用技巧。

举个例子,张爱玲有个神作《金锁记》,女主经历了不幸的一生心灵扭曲,害了儿女的一生。她女儿名字叫长安。女儿30岁了,终于有人上门提亲,她却说自己女儿怎么怎么不好,还抽大烟,最后吓跑了提亲的人。这时候是这么描写长安的:

长安悄悄的走下楼来,玄色花绣鞋与白丝袜停留在日色昏黄的楼梯上。停了一会,又上去了,一级一级,走进没有光的所在。

张爱玲施展她高超的绘画功力,手绘了一个电影中的分镜。不写长安的表情,不写她的心里,只给她的脚一个特写镜头。黑白的主体轮廓,昏黄的背景,画的尽头没有光,简直是野兽派画风的一幅画。

镜头不动,只有人物的脚在动。整体包含三个画面:第一个画面是走下楼梯;第二个画面,停了一会儿,画外音:听到了提亲时的对话正好说到抽大烟的事;第三个画面是沉重的脚步走回了没有光的所在,那就是她的余生。

此时无声胜有声,一切尽在不言中。

在《CURD系统怎么做出技术含量--怎样引导面试》有朋友开玩笑说都用上了领域驱动了,就不叫CURD系统了吧。这里我解释一下,怕大家对DDD领域驱动设计有什么误解。

DDD是为解决软件复杂性而生,但不仅仅可以被用于复杂的系统。它里面提到了很多技巧,其实CURD就是其中一种技巧。这些技巧适用于任何系统,哪怕是非常小型的系统,比如《CURD系统怎么做出技术含量--怎样引导面试》里提到的谦卑对象模型、充血模型。

今天咱们再提高一下CURD系统的门槛,连DDD技巧,咱也不用。就用写咱们平时都在写的最简单的接口。能说明设计理念,也能惊艳到面试官:

大纲

  • n+m返回值设计

  • 终态设计

  • 两码一态

三种设计方法

n+m返回值设计

概述

一个接口入参有n个值,需要的返回值是m个值。在返回值中可以把入参和返回值一起返回。

这种设计便于追踪和排查问题:

为了防止调用方没有日志追踪号、打印日志过多等原因造成不方便跟踪请求的问题,可以设计返回值将入参一起打印。这样调用方可以通过一条日志方便的获取到入参和返回值。线上排查问题会非常方便。

建议使用场景

假设有个场景,调用方的系统设计不方便请求追踪,比如没有线程追踪号。在高并发量场景下可能日志是这样的:

1、thread-1|ClassName|参数1:11,参数2:11

2、thread-2|ClassName|参数1:22,参数2:22

3、thread-1|ClassName|参数1:33,参数2:33

4、thread-2|ClassName|返回值:44

5、thread-1|ClassName|返回值:55

6、thread-1|ClassName|返回值:66

你能决定55和66对应的谁是1,谁是3的返回值吗?

但是如果返回值包含了入参,就好办多了,举个返回值例子:

thread-1|ClassName|{参数1:11,参数2:11,返回值:55}

这样就一目了然。有的时候可能是调用方本身的设计问题,但是如果被调用方能通过巧妙的设计帮助调用方。一旦遇到问题,调用方可以自己先进行排查,不用马上联系被调用方帮忙。即节约了自身的成本,又体现了专业性,何乐不为。

不建议使用场景

1、公司内有规范的、完善的、各个部门严格执行的全链路追踪标准

2、入参很大,不建议全量打印,可选取部分关键或者完全不用

终态设计

概述

在《实战并发-使用分布式缓存和有限状态机》里我讲过有限状态自动机。有限状态机涉及状态流转。状态从分类上可以分成三种:初始状态、中间状态和终态。这段时间不是一直在讲TCP底层通信嘛,来一张TCP状态的流转图体会一下:

有限状态机的重点在于有限,要有起点和终点。也就是一定要有终态。在《稳定性三十六计-超时处理》我讲过:

在传统的单机系统中,调用一个函数,要么返回成功,要么返回失败。这就是两态系统(2-state system)。

在分布式系统中,由于系统是分布在不同机器上的。还可能有一种状态叫:超时。成功、失败和超时是分布式系统调用的三态。

超时不是终态,而是一种中间状态:最终有可能下游是成功了,也有可能是失败了。这时候我们需要在超时之后推定一种状态,推定成功或者失败。究竟是成功还是失败因功能而已。

建议使用场景

比如付款操作,不知道是否成功就推定是成功的,那用户可能没有付款就拿到了商品或者享受了服务。商家就会资金损失。所以一般会推定失败。让用户再次支付。最终通过查询或者对账发现用户实际是支付成功的,可以再把钱给用户退回去,保证交易的公平性。

退款恰恰相反,需要推定成功。告诉用户,钱退给你了。最终通过查询或者对账发现实际是退款失败了,可以系统重新发起退款,直到真正退成功为止。

后台管理系统也很需要这种终态设计。比如发布系统,发布了一个功能,发布系统如果出现了问题,这次发布没有结束。用户可能没有办法进行下一次发布。这时候可以设置超时自动结束,防止未结束的流程始终在那里,起码会干扰视线,增加判断成本。

不建议使用场景

这十几年的开发还没有遇到过什么场景不需要终态。但是有些终态是隐式的。举个例子:

在《一个反直觉的sql》里提到的事件溯源模式,就是说比如在一张数据表中,只做数据记录用,只有插入操作没有更新操作。比如一个用户行为记录表,会记录用户什么时候登陆,因为用户是APP登陆的,所以2年都没有登出操作。是不是就没有终态呢?我们从这张表本身来看,因为是事件记录,所以落库的那一瞬间,状态就是“记录完成”,本身就是终态。

两码一态

概述

两码是指系统码和业务码,一态是说通过两码就可以确定最终的状态。

很多情况下咱们是已经隐式的使用了两码一态,比如自己设计了一个单点登录接口给外部调用。一般是这样设计:

实际上这个接口有个返回值,比如登录成功会返回用户信息或者直接返回是否成功的布尔值。但是这个接口是给外部调用的,需要包装一层,最终就是返回Result<User>或者Result<Boolean>。Result是怎么定义的呢?

@Data
public class Result<T> {private boolean isSuccess;private String errorCode;private String errorMessage;private T data;
}

有没有感觉和自己平时写的代码很像?

分析一下:最外层isSuccess很多人都把它当成最终的状态来使用。比如在这个登录的场景下就代表了登录成功。但是如果isSuccess=true但是data==null?这就让人很迷惑,究竟是成功还是没有成功呢。成功了为啥我的数据没有吐给我?

稍微合理一点的是isSuccess=true代表系统处理成功,就是没有抛出什么异常。究竟业务是否成功看data。

在更加规范的场合是这么定义的:

@Data
public class Result<T> {private String sysCode;private String sysMessage;private String bizCode;private String bizMessage;private T data;
}

如果系统码sysCode为成功,是否业务成功需要看bizCode;如果sysCode失败,bizCode就不用看了,也很可能根本就没有拿到;如果sysCode为失败,看系统码是多少就可以定位问题范围,或者至少说这个问题开发人员应该查查;如果bizCode为失败,如果业务码也能定位问题范围,而这种问题一般不需要开发人员来处理。

建议使用场景

比如后台管理系统中,可以定义:连接数据库异常、空指针异常等为系统失败,对两种异常分配不同的系统码,比如S001、S002;系统正常码可以分配S000;必填参数为空、参数校验失败为业务码,比如B001、B002;业务正常可以分配B000。最终状态由两个码共同决定。当系统码异常开发人员需要处理。当业务码异常可以联系运营人员培训一下怎么老填错或者不处理。

比如我在之前的文章《一个http请求进来都经过了什么(2021版)》中设立过一个场景

假设我在超市买了我喜爱的经典搭配:烤肠+酸奶。然后我就微信扫码付款了。付款时序图大体是这样的:

不用理解这个图,关系不大。我要说的是像支付这种场景后面会涉及多个环节,比如微信支付自身还要调用银行呢。

这时候的系统码和状态码中可以加一位,代表那个环节。比如系统码定义:

WS000、WS001……BS000、BS001……

S代表系统。W代表微信,比如下游请求银行,银行处理成功了,自身异常了,会设置这个码;B代表银行,比如银行自身异常了会设置这个码。

同理,业务码定义:

WB000、WB001……BB000、BB001……

第二个B代表业务。W代表微信,比如自身校验没有通过,根本不会请求银行,会设置这个码;第一个B代表银行,比如银行最后发现用户余额不足会设置这个码。

不建议使用场景

如果是给一个进程内部自身使用的,当然就没有必要定义这么复杂。

CURD系统怎么做出技术含量惊艳面试官完善版相关推荐

  1. 惊艳面试官-Java中关于随机数生成8种方式的思考

    Java中生成随机数常用的有下面这8种写法:简而言之,名称带安全的未必安全,名字简洁的未必简单. Math.random() Random ThreadLocalRandom SecureRandom ...

  2. 【客服狂收offer秘籍】惊艳面试官的自我介绍

    作为一名被面试过也面试过别人N次的客服老司机,我算是对面试时的自我介绍有一些独特的见解.今天特意写一篇[自我介绍]的超全攻略,教大家怎么准备一份满分的自我介绍,惊艳面试官! 一.自我介绍原则 1.自我 ...

  3. 想要惊艳面试官?你一张嘴就输了

    网申,校招,社招,内推-- 找工作的途径不止一个 但无论如何选择都逃不掉面试关 那么如何能在面试中表现 才能惊天地,泣鬼神--惊艳到面试官 让他愿意轻易给你提供offer? (一副认真脸) 想要在面试 ...

  4. css3边框交替动画_用css3实现惊艳面试官的背景即背景动画(高级附源码)

    我们传统的前端更多的是用javascript实现各种复杂动画,自从有了Css3 transition和animation以来,前端开发在动画这一块有了更高的自由度和格局,对动画的开发也越来越容易.这篇 ...

  5. 用CSS3实现惊艳面试官的背景及背景动画(建议收藏)

    我们传统的前端更多的是用 JavaScript 实现各种复杂动画,自从有了CSS3 transition 和 animation 以来,前端开发在动画这一块有了更高的自由度和格局,对动画的开发也越来越 ...

  6. 在业务系统中寻求技术含量

    从进入互联网公司开始工作起,每个人都在问自己,CRUD 到底有什么技术含量? 别觉得 CRUD 只是业务工程师的问题,无论你在写什么程序,基本上都是在和数据打交道,除了读就是写.只不过读写的时候还会附 ...

  7. springboot2.0项目(课程管理系统,系统简单,技术含量高)

    课程管理系统是基于springboot2.0来实现了,springboot是spring在发展史上的一个重大框架,它大大简化了spring的配置,而今年springboot重大升级,出现了spring ...

  8. 在地图上 添加柱状_如何做出一份惊艳的PPT地图页?这2个字,你一定要知道!...

    这篇文章,咱们就从一个读者私信给我的案例来说,就是这张PPT: 他当时问我的问题是,怎么把这个表格优化的更美观? 坦白讲,这是一个无解的问题,为什么这么说呢? 咱们简单对这个图表分析,就能知道,它其实 ...

  9. 面试官:哥们,你们的系统架构中为什么要引入消息中间件?

    点击上方"蓝字", 右上角选择"设为星标" 周一至五早11点半!精品文章准时送上! 本文来自石杉的架构笔记 这篇文章开始,我们把消息中间件这块高频的面试题给大家 ...

最新文章

  1. 个人使用OKR目标管理工具的感悟
  2. pyaudio与优美的声音
  3. c++调用python返回字典
  4. 10.7 netstat:查看网络状态
  5. Java Review - 并发编程_ 信号量Semaphore原理源码剖析
  6. NYOJ 269 VF
  7. java中Scanner类的使用
  8. 面试官:final、finally、finalize 有什么区别?
  9. 如何去掉Orcad Capture中元件标号下划线
  10. 时代变了,199 美元的 iPhone 都可以想了?
  11. @程序员,物联网发展的三大技术方向
  12. 详解如何基于Arduino兼容板Teensy LC实现虚拟键盘与鼠标
  13. OPENJDK8 32位版本,JAVA启动时Xmx参数的影响
  14. discuz开启url伪静态
  15. uvlayout和MAYA的接口的问题
  16. Julia安装与配置Jupyter Notebook
  17. graphpad怎么修改图片大小_Graphpad作图小技巧:如何统一图片尺寸
  18. 基于javaweb+mysql的超市进销存管理系统(java+SpringBoot+Html+Layui+echarts+mysql)
  19. ECSHOP V2.7.3文件目录结构
  20. 微信小程序wx:for 循环中item的keng

热门文章

  1. 将ppt绘制的图片转为eps格式
  2. Verilog任意整数分频器
  3. Python 地基 失灵 原始人系列 之一
  4. 计算机中agp显卡的原理,AGP显卡
  5. PHP将某个页面导出为pdf文件
  6. 计算机一级总产量怎么算,excel表格数据增长百分比-Excel表格如何计算产量增减百分比?...
  7. mtk使用android开关机动画,Android9.0 MTK 平板横屏方案修改(强制app横屏 + 开机logo/动画+关机充电横屏 + RecoveryUI 横屏)...
  8. 科技让生活更健康:洗/干衣机迎来智能化转型升级
  9. 第34本:《暗时间》
  10. New York Stock Exchange(纽约证券交易所相关数据)