2.面向对象那么好,为什么贫血模型如此流行?

2.1我们身边真的没有面向对象吗?

我们总是在强调我们的身边都是贫血模型,但是当我们仔细观察我们所引用的jar包时,我们会惊讶地发现,原来面向对象开发一直在我们身边。就拿Java开发者最熟悉的Sprin框架来说,其中充满着有血有肉的对象,这些对象在Spring的童话世界中相互协作,彼此调用构建出了一套功能复杂而完善的功能系统。
应该说正式良好的面向对象设计,让Spring在5个大版本的迭代过后还没有变成一个无法维护的焦油坑——当然些许的修改是在所难免的,因为没有人能够对未来做出预测。但是这种良好的面向对象的设计方式,让更多的修改变成了扩展,从而使代码的可维护性和扩展性大大增强。
用一句话来总结:我们身边充满了优秀的面向对象思想开发的优秀项目,它们也没有什么DDD的指导思想,而是纯粹的面向对象编程思想。

2.2我的代码为什么都是一堆get和set?

Java在国内的兴起与电商行业有着密不可分的关系,而这些电商行业都是基于WEB的应用,当我们进行WEB应用开发的时候,在早期就不可避免地用到所谓的SSH、SSM这种所谓的“三大框架”,到后期更是被SpringBoot一统江湖。在这些框架的“帮助”下,我们“省去”所有复杂逻辑的实现,只需要关注我们的业务代码。
而对于各种WEB应用来说,基本的业务逻辑就是接收数据和指令,然后按照指令对数据进行CRUD(增、删、该、查)操作。这种情况下数据,也就是对象本身就很难有什么“行为”,也就导致很难给对象设计什么行为。
拿一个添加商品的功能为例,那么基本上最初的功能就是根据输入字段新建一个商品的对象,然后设置个字段属性,然后调用ORM框架进行持久化。整个流程中都不会产什么对象行为。但是随着业务迭代,添加商品功能可能变的越来越复杂。比如需要判断商品是不是促销商品,如果是的话就设置优先展示。这时坏事情就发生了,由于在开始时,我们就在service中编写了如示例2-1所示的代码。

public class ProductService() {
	public void addProduct(ProductVO vo) {
		Product product = new Product();
		product.setName(vo.getName());
		if (vo.getType().equals("服装")) {
			product.setType(1);
		} else {
			product.setType(2);
		}
		repository.save(product);
	}
}

示例2-1
示例2-1中的完全把对象当成了一种数据容器,然后使用面向过程的编程方式来组织所有的逻辑实现。在这种简单的业务场景下,这种编码风格无可厚非。也就是说一堆面向对象开发的框架给我们隐藏了复杂的底层逻辑,而我们要处理的业务相当简单,那本面向过程开发也是完全合理的。
不过后来作为一个"懒惰"的程序员,自然而然就会在示例2-1的基础上进行修改,修改为示例2-2所示的代码。

public class ProductService() {
	public void addProduct(ProductVO vo) {
		Product product = new Product();
		product.setName(vo.getName());
		if (vo.getType().equals("服装")) {
			product.setType(1);
		} else {
			product.setType(2);
		}
		//设置促销商品优先展示
		if (vo.getPromotion().equals("是")) {
			product.setPromotion(1);
		} else {
			product.setPromoiton(0);
		}
		if (product.getPromotion() == 1) {
			product.setPreferToHomePage(1);
		}
		repository.save(product);
	}
}

示例2-2
随着口口相传,和不断迭代。这种在简单业务场景下遗留下来的风格就延续到了复杂的场景下。就算上面的方法越来越长,其中的if判断越来越多。程序员也懒得改了。这就形成了传说中的”屎山“。最后就会形成在屎山上拉屎的恶性循环。

总结

(1)面向对象距离我们并不遥远,我们使用的很多底层框架都是优秀的面向对象产物。
(2)在业务简单的初期使用面向过程加贫血模型进行编程并非有罪,只是在适当的时候要进行代码重构,适时地向面向对象进行靠拢来应对越来越复杂的业务逻辑和越来越大的代码量。然而往往开始使用面向过程后,由于人才和习惯等原因就会进行“屎山”堆积性开发,最后就会得到只要在线上能运行的代码就是好代码的结论。
(3)面向对象并不一定需要DDD,只要能够对系统进行合理的抽象和设计,完全可以构建一套自己的童话世界,让这些可爱的对象在这个童话世界里快乐生活。而这种抽象能力一般需要大佬级别的人物进行操刀,如果没有这样的人物带领,往往也难以迈出重构这一步。

最后DDD只是一种面向对象的实现“公式”和“方法论”,在面向业务领域设计时使用这套“公式”和“方法论”能够有效地降低进行面向对象系统设计的难度。也就是说DDD只是通往面向对象设计的道路之一。
后续的章节将通过各种前提来讨论如何规劝自己放弃DDD。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐