coldsmog开发笔记
JS 事件笔记
Ckeditor 上传WPS图片失败问题
Springboot
SpringBoot 统一异常处理
Springboot 引入外部jar包
Springboot 打成war包
Springboot 多环境配置
SpringBoot @Scope注解学习
Springboot 快速生成项目API文档
SpringCache 缓存
Spring jetcache 二级缓存
Springboot 按条件装配类
FastJson的JsonPath语法
正则表达式语法
Spring 路径匹配
Feign 基础数据操作
监控Feign调用metrics
Springboot feign的性能优化
Jackson 设置序列化属性
SpringBoot 集成 Spring Data Mongodb 操作 MongoDB
MongoDB 的一些注意事项
MongoDB 指令对比
Jackson 解析XML
Springboot Redis注册
SpringBoot RedisTemplate批量插入
Springboot 指标监控Micrometer
springboot validation 注解校验
springboot 引入配置
Springboot 静态文件处理
Springboot 导出csv文件
Springboot 事件驱动(发布/订阅模式)
Springboot 启动过程和扩展点
Springboot 优化停机上下线
Spring自动装配 - 干饭角度学习
Springboot ShardingJDBC
Springboot的重试
springboot 动态修改端口
Oracle
Oracle 中实现自增ID
Oracle 定时任务
Oracle 解锁临时表
Oracle 检查连接数
Oracle 表空间
Oracle 解释执行SQL
markdown作图(适用typora)
服务器压测
业务对象层和数据层
并发限流处理
中间件
Yarn的使用
Dubbo学习笔记-RPC扩展和本地Mock
Dubbo学习笔记-泛化实现进行mock
Redis缓存穿透,缓存击穿,缓存雪崩
Galera 集群说明
Pip 镜像
pip 使用
MySQL命令行
数据库缓存双写方案
Git相关操作
Redis 操作时间复杂度一览
nacos 杂记
mybatis 散记
shardingjdbc
一次线上事故排查发现的Caffeine缓存死锁问题
设计模式
重新讲讲单例模式和几种实现
更优雅地实现策略模式
Http-headers
Prometheus 杂散笔记
JAVA 散记
CompletableFuture
Gson、FastJson、Jackson、json-lib对比总结
jackson 时间的序列化踩坑
JVM
自定义注解
mysql类型和java类型 转换一览表
枚举维护一个Map<value, Enum>的映射
Java中String +、concat、StringBuilder、StringBuffer 性能对比
TraceId 使用
MySQL 多数据源处理
Mybatis-plus 流式查询
JAVA发送win 桌面通知
idea 启动项目失败非代码问题杂记
Lambda 简述
Arthas 使用笔记
一种链式更新数据的数据模式
Skywalking 新增中间件插件
Redission 使用
数据导出为图片
IDEA 的热重启
Netty 工具类
maven 插件
TCP 抓包
本文档使用 MrDoc 发布
-
+
首页
业务对象层和数据层
spring mvc中 一切皆对象,包括用于表达数据库模型的DTO也是对象。但由于DDD兴起我们发现充血模型在替代贫血模型,原来简单描述数结构的对象现在添加了较多的除了get/set之外的函数。于是,我们需要重新思考一下对象和数据结构的区别。 代码整洁之道中举了一个例子去说明两者微妙的区别 ``` final String outputDir = ctxt.getOptions().getScratchDir().getAbsolutePath(); ``` 调用者不断获取返回的对象并调用对象的函数,违反了得墨忒耳定律:一个模块只干一件事调用者清楚了太多的细节,而这是明显的数据结构的特征:暴露内在的数据结构。而对象则倾向与只暴露必要的数据域,其余默认为私有域。 但这是由于一些框架和约束要求我们将简单的数据结构也要用到一堆get/set进行传参。 那么正确的做法是什么呢?如果我们要暴露数据结构,最好的方式是 final String outputdir = ctxt.options.scratchDir.absolutePath; 如果是对象,则应当抽取出合适的函数 比如ctx.getAbsolutPath(); 由此我们得到了一个结论数据结构和对象的确是有所不同。 这也是我们原先去区分service层和mapper层的原因。由mapper将数据结构的细节隐藏,提供一个对象提供给业务对象使用。 CURD项目很多时候考虑的就是从数据结构出发,完成数据的CURD,从而将各处的业务逻辑散落一地。我见过controller层中写业务逻辑的,说这是控制层的职责,也见过为了对外(用户)接口和对内(程序调用)的接口完全封装在两个service之间交叉调用的。这可能也是从数据结构着眼导致业务概念上的混乱。 而到了微服务环境,这种情况则变动尖锐和明显了起来。微服务只希望提供服务能力,将外界微服务是为一个能力提供者,而从数据结构层着眼设计的服务就显得不尽如人意。同时,微服务环境下能力提供者的变动速度可能是原来的数十倍。毕竟表结构是件大事,而因为种种原因外边能力提供者变化还是一件挺经常的事。微服务提出了防腐层的概念,但本质上也是将外部的数据结构转成了自己需要的对象,**只要对象函数没变,数据结构的变化是可以被隐藏的**。 将所有架构都抽象成业务服务层和数据结构层之后,我们的架构就清晰了很多。控制层控制是否调用业务,提供业务层必要的参数。业务层操作数据结构完成业务逻辑。而数据层隐藏具体的细节,将数据库、外部微服务等能力提供者统一转成可控的对象。架构变动万变不离其中。 充血模型是抽象的对象在开发时带来了简便,贫血模型为数据结构变动留下了较大的余地。我个人更推荐在数据转换层将贫血模式去加血,否则继承一个充血的业务对象,大概率是会让业务逻辑变得紧耦合或者冗余混乱。这就是repository层。该层以下是数据库或者内存数据结构都可,该层以上则提供充血模型
寒烟濡雨
2023年3月13日 15:17
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码