结合业务需求变化,POJO/领域驱动对象核心及代码反模式问询
嘿,咱们先把这两个问题拆开来聊得明明白白的~
不管业务需求怎么变,这三类对象的核心定位其实是层层递进的,各自解决不同的问题:
POJO:纯粹的“数据容器”,主打轻量灵活
说白了就是个没架子的Java对象,不依赖任何框架、不带复杂逻辑,唯一的作用就是把零散的业务数据打包成结构化的东西。比如你要存客户的姓名、手机号,直接建个CustomerPOJO加对应的属性和getter/setter就行。当业务新增“会员等级”字段,直接加属性就搞定,它的核心价值就是跟着数据结构变,完全适配业务数据的调整。业务模型:绑定基础业务规则的“智能容器”
比POJO多了点“业务脑子”,它不仅装数据,还会把和这个实体相关的简单逻辑封装进去。比如CustomerModel里加个getFullName()方法,把 firstName 和 lastName 自动拼接,或者isEligibleForDiscount()判断是否符合折扣条件。当业务规则变了——比如折扣门槛从消费满1000改成2000,直接改模型里的判断逻辑就行,不用在代码里到处找地方修改,把相关逻辑聚在一起,减少重复和混乱。领域驱动对象(DDD领域实体):承载核心业务逻辑的“自治实体”
这是DDD里的核心角色,可不是简单的“数据+小逻辑”,它代表业务领域里的核心概念(比如电商的“订单”“库存”),核心特点是有唯一身份标识、能自主处理领域内的复杂逻辑、维护自身状态的一致性。比如Order实体,当用户取消订单时,它自己要处理“回滚库存”“标记订单状态为取消”“触发退款申请”这些连锁逻辑,而不是让外部代码随便修改它的状态。当业务新增“7天内才能取消订单”的规则,直接在Order的cancel()方法里加判断就行,所有相关逻辑都封装在实体内部,不管业务怎么变,核心逻辑都不会散得到处都是,保证了业务规则的一致性。
先把你贴的代码完整摆出来(虽然最后buildAndUpdateTax没写完,但核心问题已经很明显了):
@SuppressWarnings("unchecked") private static Map<String, Object> getArgs(Object obj) { return new HashMap<>((Map<String, Object>) obj); } public void buildAndUpdateCustomer(List<Object> list) { for (Object obj : list) { Map<String, Object> args = getArgs(obj); daoProvider.updateCustomerName(args); daoProvider.updateAgingMia(args); } } public void buildAndUpdateTax(List<Object> list) { for (Object o...
这段代码的问题简直是“反模式集大成者”,踩了好几个致命的坑:
完全抛弃类型安全,运行时炸锅是迟早的事
getArgs里直接把Object强转成Map<String, Object>,还加了@SuppressWarnings("unchecked")把编译器的警告压下去——这就相当于蒙着眼睛过马路!谁知道传入的obj到底是不是合法的Map?如果上游传了个String或者Customer对象进来,运行时直接抛出ClassCastException,而且这种错误编译器根本查不出来,只能等线上出问题才发现,排查起来巨头疼。可读性为0,维护者看了直接懵圈
你看buildAndUpdateCustomer里的List<Object>,谁知道这个列表里装的是什么?是Map?还是别的?后面调用updateCustomerName(args),谁知道args里必须有哪些key?比如是不是得有customerId和newName?如果传的Map里缺了key,DAO层又会报错,这种“隐式依赖”全靠老人口口相传,新人接手根本摸不着头脑,改个代码都怕踩雷。违反面向对象封装原则,逻辑拆得稀碎
本来更新客户姓名这种操作,应该是针对Customer对象来做的:customer.setNewName("xxx")然后调用dao.updateCustomer(customer)。结果这里全用Object和Map传递数据,把本该封装在业务对象里的逻辑拆成了零散的Map操作,不仅容易写错key,而且业务逻辑完全没有边界,需求一变,要改的地方可能到处都是,维护成本直线飙升。调试排查地狱,出问题找不到北
假设线上报了个空指针,说args.get("customerId")是null,你得从List<Object>的源头开始查:到底是谁传的Map缺了这个key?是上游服务?还是别的业务方法?因为没有类型约束,你没法快速定位问题,只能一步步加日志调试,效率低到离谱。
内容的提问来源于stack exchange,提问作者theyCallMeJun

