这套题还不错,感兴趣的猿可以试一试:前端开发工程师
参数设计
- 固定参数采用基本类型
- 参数过多(8个)建议采用对象参数
- 接口预留扩展对象,便于后期处理个性化需求
- 参数需要考虑某些涉及到资金的字段是否自增的,暴露之后是否容易猜到
返回值设计
- 提供通用的接口调用成功失败的方法
- 实现Serializable并重写id
- 规避使用枚举
- 结构体
{ "code": 200, "model": "", "msg": "" }
- 对象设计要简练
- 通用逻辑服务端处理好,前端只做展示,例如:标签展示,服务端抽象好标签文案和类型即可,前端根据类型在 做定制化的样式展示,标签可以任意扩展
- 相同作用域收敛
- 中台结构往往需要结合各个基础服务获取到的信息封装一个fat对象,那么此时我们需要对对象进行DDD模型抽象,划分不同的作用域,例如商品的资金信息,对于前端来说只需要展示价格的原价和现价,那么我们需要将这两个价格的逻辑收敛到这两个字段中,无需前端再做其他业务处理
- 逻辑控制要收敛
- 对于同一个字段,在不同业务场景下代表不同的值针对该字段增加处理类,逻辑收敛
- 根据业务逻辑分层
- 根据返回对象的业务,定好对象的父子关系,通用属性归属到父类,个性属性归属子类对象
异常处理
- 枚举定义错误码,支持可配置的错误文案
- 注解环绕的方式处理异常,逻辑收敛
功能特性
- 对于会产生数据变更的服务,做好防止重复调用处理
- 最短路径原则
- 懒加载方式使用的时候再加载
- 对于中间数据需要在多层次的方法调用中传递构建Context,放置到ThreadLocal中实现线程中随处访问,但是需要注意内存泄漏问题(1,线程池 2.使用之后主动释放)
- 通用的判定逻辑收敛到静态类中,便于后期判定逻辑修改,漏改
- 对于下游接口调用,本着先怀疑的态度,注意判定空
非功能特性
- 性能
- 限流降级,不返回数据不会对用户产生影响的接口可以采用熔断的策略,如果返回数据抽象核心和非核心,在流量过大的时候可以降级非核心业务
- sentinal
- 信号量
- hytrixs
- 底层并行调用
- 并发调用
- RxJava
- 多场景下的综合服务,底层力度控制
- 通过设计控制位,针对不同的业务场景分配不同控制位,减少不必要的调用
- 限流降级,不返回数据不会对用户产生影响的接口可以采用熔断的策略,如果返回数据抽象核心和非核心,在流量过大的时候可以降级非核心业务
- 安全性
- 登录态,用户认证
- 敏感数据脱敏,用户的个人隐私数据脱敏 收集号码中间4位占位展示
- 扩展性
- 接口升级
- 思考接口升级的时候兼容问题,是否涉及到外部调用大量修改,
- 个性化需求
- 接口升级
- 健壮性
-
下游服务调用容错处理
- 自定义注解环绕
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ResultWrapper { DefaultResultEnum defaultObj() default DefaultResultEnum.OBJECT; }
- 定义返回类型避免空指针
LIST(1, "list", Collections.EMPTY_LIST), MAP(2, "map", Collections.EMPTY_MAP), SET(3, "set", Collections.EMPTY_SET), OBJECT(4, "object", null), STRING(5, "string", ""), BOOLEAN(6, "boolean", Boolean.FALSE),
-
统一下游服务返回对象
Result<T> implements Serializable { /** * 返回码 */ private int code = 200; /** * 报错信息 */ private String msg; /** * 返回model */ private T model; public boolean isSuccess(){ return 200==code; }
-
整体接口容错处理
- 自定义注解环绕
@Around(value = "@annotation(serviceWrapper)", argNames = "joinPoint,serviceWrapper") public Object doAround(ProceedingJoinPoint joinPoint, ServiceWrapper serviceWrapper) throws Throwable { final long begin = System.currentTimeMillis(); Object object = serviceWrapper.isReturnBooleanType() ? false : null; try { object = joinPoint.proceed(); return object; } catch (Exception e) { LogControl.printLogWarn("exception", Throwables.getStackTraceAsString(e),JSON.toJSONString(joinPoint.getArgs())); DubboExtProperty.setErrorCode(GwReturnCode.SYSTEM_ERROR); } return object; }
- 自定义注解环绕
-
问题查询的便捷性
- 关键节点日志打印,代码设计的时候就需要预判可能出现的问题,和查询该问题需要的关键信息
- 重写toString方法,重点打印过程数据,如果接口会暴露出来的数据,建议只保留关键信息如:主键id
- 抛砖引玉,这是我在设计一个接口的时候考虑到的一些因素,大家如果有好的建议的欢迎留言补充
- 关键节点日志打印,代码设计的时候就需要预判可能出现的问题,和查询该问题需要的关键信息
-