0.1 版权声明
测试驱动开发与设计模式相结合的开发方式,能产生清晰的结构,弹性的设计,水到渠成地还带来稳定的代码。这里对JSON过滤库的介绍,是为了说明这种方式的好处,也是对《测试驱动开发与设计模式 - 从入门到精通》一文的补充。
JSON过滤库作为A公司项目的一部分完成,版权属于A公司。
0.2 设计目的
这个库的目的是用 “Json字符串” 匹配 “Json过滤字符串”,如果匹配,则认为过滤成功,否则失败。
Json字符串是符合Json规范的字符串,Json过滤字符串则是符合MongoDB查询操作规范的字符串。
比如Json字符串如下:
{
"name":"ron",
"sex":"male",
"position":
{
"x":100,
"y":200
}
}
如果过滤字符串如下,则是成功的,因为sex属性和position.x属性是匹配的。
{"sex":{"$eq","male"},"position":{"x":{"$lte":100}}
如果过滤如下,则是失败的,因为name属性不匹配。
{"name":{"$eq":"josh"}}
1. Constraint
- Constraint是条件约束。CommonConstraint是一般条件,CompositeConstraint是组合条件,也就是其他条件的组合,这个其他条件可以是一般条件,也可以是组合条件。
- CommonConstraint包括EqContraint,LteConstraint,RegexConstraint等,分别对应MongoDB的$eq,$lte, $regex;
- CustomedConstraint也是CommonConstraint,它是用户自定义的类型;
- CompositeConstraint包括AndConstraint,OrConstraint,和NotConstraint等,分别对应MongoDB的$and, $or, $not。
2. ConstraintTree和Node
- Json字符串实际上是一棵树,而“Json过滤字符串”则是两棵树,一棵是属性树,另一棵是条件树,后者按照Constraint的位置挂接在前一棵上。这里用ConstraintTree表示“Json过滤字符串”的树(它的数据表示是ConstraintTreeData),而Node就是树节点;
- Attribute是属性树的节点,ConstraintTreeData用root属性引用属性树;
- Constraint是条件树的节点,所有的条件最后组合成为一个AndConstraint,保存在ConstraintTreeData的subs成员中;
- 实际上这里支持多组条件的,也就是有多个条件树,所以ConstraintTreeData.subs是一个map。既然有多组条件,就需要对它们编号,所以从AndConstraint派生出Subscriber,保存这个编号。
3. 构建ConstraintTree
- 将“Json过滤字符串”传给ContraitTree进行构建。ContraintTree将ContraintTreeData给Builder,委托它完成工作。
- JsonNode表示Json字符串。因为效率的原因,它其实是一种Binary JsonNode,来自于另一个库。
- Builder解析"Json过滤字符串”,并相应地构建属性树和条件树;
- 可以多次构建,得到多个条件树,对应于多个Subsriber。
3. 过滤
- Visitor提供一个方便遍历ConstraintTreeData节点的接口;
- Visitor还包含VistorData,保存过滤的状态和结果。VisitorData是每线程构建的,所以可以用同一个ContraintTree实例并行做多个过滤。
- Traverser同时遍历ContraintTreeData的树(通过Visitor),和传入的Json字符串,剔除不满足的Subscriber,留下满足条件的。这实际上是反向过滤。
- 当然,如果Subscriber只有一个,而且被剔除了,那就说明Json字符串不符合条件,反向过滤也就是正向过滤了。
4. 对外的接口
- Filter和FilterFactory是对外的接口。FilterImp基于ContraintTree实现Filter接口。
5. 构造Json过滤字符串
- 如果对Json和MongoDB查询不熟悉,那么写Json过滤字符串算是一个不大不小的麻烦事。Cons和它的派生类帮助使用者用一种容易理解的方式来写。
- EqCons,GtCons, RegexCons等分别用来构造$eq, $gt和$regex字符串。
- Cons本身还有函数支持写组合条件,如operator &&,operator || 和 operator !分别用于$and, $or, $not等。
6. 多个Json过滤字符串
- 与Filter/FilterFactory一样,PhasedFilter/FilterFactory也是对外的接口。不过,PhasedFilter支持多步骤的过滤。也就是Json字符串可以分几次输入。
相关链接
测试驱动开发与设计模式 - 从入门到精通
测试驱动开发与设计模式 - C++书籍及网站
测试驱动开发与设计模式 - 开发实例(一)DVR-POS库
测试驱动开发与设计模式 - 开发实例(二)JSON过滤库
测试驱动开发与设计模式 - 适应并改进软件设计过程
测试驱动开发与设计模式 - 让“理想结构”与“快速变更”并行
测试驱动开发与设计模式 - 提速 — 在纸上做细节设计
网友评论