引子

很多朋友可能会因为自己做的工作不是特别核心或者业务简单而引起面试中没有自信。但是很多公司面试的时候是可以接受面试者之前岗位的并发量、交易量低一些的。比如我们要招聘和我们交易量同等级或者以上的出来的人才,业界本来就没有多少,但我们还是要招人的。所以很多时候更偏向于考察面试者的设计底蕴、思考和解决问题的能力。

我建议面试时,面试者要争取主动权,主动引导面试。一般作为面试官也很乐意被面试者引导。因为面试官的职责是发现面试者的技术特长,为此我们绞尽脑汁的从简历中、自我介绍中去发掘。如果面试者可以自己有完整清晰的思路,是面试官求之不得的事情。

假设我是一个面试者,近几年做的都是XX后台管理系统。后台管理系统嘛,没有高并发、没有高可用需求、没有复杂架构,属于三无系统。要是我的话,会把自己的以下知识技能放到项目介绍里展示给面试官:

  • 可测试性设计

    • 谦卑对象模式

    • RESTful风格

  • 领域驱动设计DDD

    • 充血模型

    • CQRS

可测试性设计

谦卑对象模式

作为一个后台管理系统,一般场景下微服务化的价值不大。DDD领域驱动设计这种专门用于复杂问题的解决办法在这里多半也是杀鸡用牛刀。后面会讲到一些DDD技巧还是可以用的。实际中大多是采用前后端分离的架构,这种架构实践一方面是动静分离,便于缓存优化等性能考虑,另一方面也是一个出于可测试性的考虑。分离出可自动化测试的接口层和测试难度高的展现层。

展现层对象等测试难度高的对象在整洁架构中被称为谦卑对象。通过拆分不同的类或者模块,来区分容易测试的行为和不容易测试的行为,这种设计上的隔离模式被称为谦卑对象模型。

现在的很多设计对程序的可测试性提供了友好的改进和支持。比如:程序调用数据库执行操作,mybatis等持久层框架将把sql以接口的形式对外提供服务,接口有成熟的工具来做mock打桩,这是比较典型的谦卑对象模式。

另外一个比较典型的比较典型的谦卑对象模式是feign。netflix的feign把原本需要手写的httpClient(或者OKHttp)代码使用接口调用的的形式,实现了命令式到声明式的转换。同时,谦卑对象和非谦卑对象之间有很好的隔离层,也对测试更友好。对feign想做进一步了解的可参考我之前的文章《Java&Spring过时的经典语录》,这里简单举个例子:

public interface TestHttpService {

    @RequestLine("GET /xxxx?appkey={appkey}&ips={ip}&username={username}&operator={operator}")
Response getTest(@Param(value = "appkey") String appkey,
@Param(value = "ip") String ip,
@Param(value = "username") String username,
@Param(value = "operator") String operator);

}

RESTful

说起后台管理系统的接口层,RESTful风格的接口是比较流行的最佳实践。虽然这个被提了很多年了,实际严格按照这种风格设计的接口并不多。大多数系统的接口风格像是跟着江南七怪学武的郭靖一般,武功路数驳杂不成体系。

来做个判断题:

下面的代码,类上用了RestController的注解,这是RESTful风格的代码吗?

@RestController
public class JacksonController {
@Resource
private User user;
@GetMapping("/writeStringAsString")
public String writeStringAsString(String toWrite) throws Exception {
System.out.println(user.getAge());
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(toWrite);

}

}

REST(英文:Representational State Transfer,简称REST) 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。

理论上REST架构风格并不是绑定在HTTP上,但是REST本身受Web技术的影响很深, 目前HTTP是唯一与REST相关的实例。
咱们来看看需要满足哪些约束条件和原则。

资源设计规则:

1>不用大写;
2>用中杠-不用下杠_;
3>用名词不用动词;
4>URI中的名词表示资源集合,使用复数形式。

动作设计规则:

1>GET(SELECT):从服务器取出资源(一项或多项)。

2>POST(CREATE):在服务器新建一个资源。

3>PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。

4>PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。

5>DELETE(DELETE):从服务器删除资源。

返回结果规则:

与HTTP协议标准基本没有新的约束。要注意content-type的accept,包含accept-encoding。之前出个我在测试环境出个一个问题,我们自动化测试回归平台不支持gzip,但是请求时带了gzip,其实平台并不支持导致乱码。

通过上面的约束条件和原则咱们来总结一下为什么叫REST:"资源"是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。

互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。

如果大家都理解,那上面判断题的答案也呼之欲出了:因为不满足相应的约束条件和原则,所以不是RESTful风格。@RestController 只是让资源返回结果是RESTful风格的。但不管是不是RESTful风格,都是URI。统一资源标识符(Uniform Resource Identifier,URI)是一个用于标识某一互联网资源名称的字符串。 只要定位到资源了,都是URI。

领域驱动设计DDD

充血模型

贫血模型是指实体对象或者说是POJO只包含简单的set、get方法,充血模型认为一个对象是拥有状态和行为的。什么叫状态和行为呢?举个例子:

@Setter
@Getter
@ToString
@EqualsAndHashCode
public class Pojo {
private String name ;
private String status;
public int getStatus() {
return NumberUtils.toInt(status);
}
}

上面类代码上用了lombok的@Setter、@Getter注解之外,还用了@ToString、@EqualsAndHashCode,这两个虽然是Object对象的基本方法,实际上也是做了状态和行为的事情,而不只是@Setter、@Getter的数据存取。与之类似的还有上面的int getStatus,实际上进行了类型转换这个行为。

现在针对到底使用贫血模型还是充血模型更好说法不一。我个人更倾向于使用充血模型,因为这种方法从领域上更内聚。但是很多人不建议使用,主要是因为充血模型对个人能力有更高的要求。充血模型开发者需要自己去识别哪些是实体领域中的。对于一般的spring开发者来说,个人经验上有个简单的办法:凡是要引用@Service、@Component的都不要放到里面,之前本来要放到XXUtils的建议看看更符合哪个实体领域,不要一股脑放到util包下面,看看是否可以划分到实体领域中。

CQRS

CQRS — Command Query Responsibility Segregation,顾名思义是将 command 与 query 分离的一种模式。CQRS 将系统中的操作分为两类,即「命令」(Command) 与「查询」(Query)。命令则是对会引起数据发生变化操作的总称,即我们常说的新增,更新,删除这些操作,都是命令。而查询则和字面意思一样,即不会对数据产生变化的操作,只是按照某些条件查找数据。

在后台系统中,某些查询操作可能会过于频繁,比如页面定时刷新获取数据。这些查询操作不需要保证每次都成功。而命令操作如果失败则涉及到事务回滚等操作,需要保证操作的成功率。这时候可以使用CQRS隔离,比如将检查流量和命令流量使用hystrix隔离,架构清晰了,还可以画出下面这样清晰的架构图:

总结

上面都是后台管理系统中常用的一些技术,其实还有ACL(防腐层),批量操作的隔离、熔断、分片,数据异步转同步等限于篇幅这里就不介绍了。只要面试中能够引导面试官提问这方面的技术并且可以讲的明明白白,已经可以超过大部分的面试者。

推荐阅读

服务设计要解决的问题

分布式存储系统的一致性-可见性差异

代码荣辱观-以运用风格为荣,以随意编码为耻

程序员如何破局前行

CURD系统怎么做出技术含量--怎样引导面试的更多相关文章

  1. CURD系统怎么做出技术含量惊艳面试官

    在<CURD系统怎么做出技术含量--怎样引导面试>有朋友开玩笑说都用上了领域驱动了,就不叫CURD系统了吧.这里我解释一下,怕大家对DDD领域驱动设计有什么误解. DDD是为解决软件复杂性 ...

  2. C#工业物联网和集成系统解决方案的技术路线(数据源、数据采集、数据上传与接收、ActiveMQ、Mongodb、WebApi、手机App)

    目       录 工业物联网和集成系统解决方案的技术路线... 1 前言... 1 第一章           系统架构... 3 1.1           硬件构架图... 3 1.2      ...

  3. 谈“技术含量”的问题

    最近又从离职同事那里听到这样的抱怨(原因),说做的事没有技术含量.想一想,从事车载软件开发这个行业快8年了,这个话题似乎从来没有停过.我自己曾经也为自己做的事是否有技术含量而苦恼过,今天就专门花点时间 ...

  4. 装多系统删除某个系统后,如何恢复ubuntu引导

    在重装系统或者再装多个系统后可能会出现ubuntu的引导文件不存在的情况,windows系列的引导文件可以用winpe修复,但是ubuntu就不可以,虽然网上很多种修复ubuntu的引导文件 方式,但 ...

  5. 没什么技术含量的Remove Before Flight

    航空业有很多值得我们借鉴和学习的工作方式,将来有时间我会给大家引荐更多实例. 仔细观察每架停泊着的飞机,会发现机身很多地方都挂着细长的红布条,上面写着"REMOVE BEFORE FLIGH ...

  6. Java开源生鲜电商平台-系统架构与技术选型(源码可下载)

    Java开源生鲜电商平台-系统架构与技术选型(源码可下载) 1.  硬件环境 公司服务器 2.   软件环境 2.1  操作系统 Linux CentOS 6.8系列 2.2 反向代理/web服务器 ...

  7. Linux系统在启动过程中grub引导文件丢失的解决方法

    在/boot/grub2目录下有一个grub.cfg文件:该文件主要是用来自动地引导系统启动内核程序和系统的初始化程序. 问题一:当系统在启动的情况下,我们不小心删除/boot/grub2/grub. ...

  8. CODING 受邀参与 DevOps 标准体系之系统和工具&技术运营标准技术专家研讨会

    2019 年 5 月 24-25 日,国内领先的一站式 DevOps 解决方案供应商 CODING 作为腾讯云的深度合作伙伴,受邀参加在成都举行的由 TC608 云计算标准和开源推进委员会主办,中国信 ...

  9. 前端 & 技术团队 TL & 如何面试 & 如何带人

    前端 & 技术团队 TL & 如何面试 & 如何带人 面试 带人 作为 TL,深度了解你的团队非常重要,要去了解每个人的想法是什么,他的诉求是什么,他目前的状态怎么样,以及对他 ...

随机推荐

  1. javascript 标签切换

    * index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  2. 鸿蒙内核源码分析(进程回收篇) | 老父亲如何向老祖宗临终托孤 ? | 百篇博客分析OpenHarmony源码 | v47.01

    百篇博客系列篇.本篇为: v47.xx 鸿蒙内核源码分析(进程回收篇) | 临终前如何向老祖宗托孤 | 51.c.h .o 进程管理相关篇为: v02.xx 鸿蒙内核源码分析(进程管理篇) | 谁在管 ...

  3. 12306抢票算法居然被曝光了!!!居然是redis实现的

    导读 相信大家应该都有抢火车票的经验,每年年底,这都是一场盛宴.然而你有没有想过抢火车票这个算法是怎么实现的呢? 应该没有吧,咱们今天就来一一探讨.其实并没有你想的那么难 bitmap与位运算 red ...

  4. ASP.NET Core 5.0 中读取Request中Body信息

    ASP.NET Core 5.0 中读取Request中Body信息 记录一下如何读取Request中Body信息 public class ValuesController : Controller ...

  5. 在Unity中渲染一个黑洞

    在Unity中渲染一个黑洞 前言 N年前观看<星际穿越>时,被其中的"卡冈图雅"黑洞所震撼.制作团队表示这是一个最贴近实际的黑洞效果,因为它是通过各种科学理论实现的.当 ...

  6. 在开源项目或项目中使用git建立fork仓库

    前言: vector我们经常使用,对vector里面的基本函数构造函数.增加函数.删除函数.遍历函数我们也会用到.其中在使用遍历之后erase删除元素过程中,会出现一种删除最后一个元素破坏了迭代器的情 ...

  7. 题解 「ZJOI2018」历史

    题目传送门 Description 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣. 这个世界有 \(n\) 个城市,这 \(n\) 个城市被恰 ...

  8. 好程序员打造核心教培天团,着力培养IT高级研发人才

    随着数字化进程加快,各行各业数字化转型迫在眉睫,技术人才战略成为企业发力重点,IT高级研发人才已经成为企业的"核心资产",对企业发展起关键性作用,然而市场上高级研发人才极为稀缺.据 ...

  9. UE4蓝图AI角色制作(四)之Gameplay调试器

    8. 寻路网格体和Gameplay调试器 为了及时识别出AI系统中的导航问题,UE4提供了一个工具用来解决这类问题,它叫Gameplay调试器.打开项目设置,在左侧找到"引擎",然 ...

  10. python解释器和Pycharm编辑器安装使用完整详细教程

    一.官网下载或软件管家公众号下载 二.安装Python解释器 1.选择自定义安装并添加到环境变量 2.检验Python是否安装成功 三.安装pycharm编辑器 1.点击安装,修改安装路径,建议安装C ...