这套题还不错,感兴趣的猿可以试一试:前端开发工程师

参数设计

  • 固定参数采用基本类型
  • 参数过多(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
        • 抛砖引玉,这是我在设计一个接口的时候考虑到的一些因素,大家如果有好的建议的欢迎留言补充