看了infoq上greg young的一段视频,讲领域驱动设计的一些最佳实践。其中说到没有getter的setter的领域对象,很有感触,写点观后感。
为什么不要getter,setter?
先说setter。对象属性的改变可以通过两个方式,一个是通过自身的行为改变,另一个就是直接通过setter改变。对象的行为封装了领域逻辑,setter这种绕过行为的方式也就是绕过了领域逻辑,这样的改变会造就对领域而言没有意义的对象属性,也就是无效属性。那么使用这样的对象就要增加验证领域模型状态是否有效的成本,isValid? 成本倒还是小事,业务领域的复杂性会导致一个小小的无效模型污染一大片模型的连锁反应,最后都无法判断哪个模型对象有效了。没有了setter,整个世界就清净了。一旦建造,始终有效。
接下来是getter。众所周知,软件设计里最重要的原则之一是“Separation of Concerns”。我的理解是,不同的事情交给不同的东西做。领域对象行为是负责执行系统指令的(commad);而getter负责访问数据,也就是数据查询(query)。commad和query的分开,意味着不需要为了一个简单的数据查询(往往是事务脚本模式),而在内存里装载一个个满带功能的业务对象了。而且有getter,就会有别的对象调用getter,在重构中,是一个典型的smell,就是data envy,摆弄其他对象的属性。
没有getter,setter,如何查改数据? 解决方案是 一个没有getter,setter的领域系统,一个数据库查询系统,双管齐下。两者之间通过event系统来监听领域模型的数据改变。
可能抛弃getter和setter,DDD和OOP的世界会更好一点。
为什么不要getter,setter?
先说setter。对象属性的改变可以通过两个方式,一个是通过自身的行为改变,另一个就是直接通过setter改变。对象的行为封装了领域逻辑,setter这种绕过行为的方式也就是绕过了领域逻辑,这样的改变会造就对领域而言没有意义的对象属性,也就是无效属性。那么使用这样的对象就要增加验证领域模型状态是否有效的成本,isValid? 成本倒还是小事,业务领域的复杂性会导致一个小小的无效模型污染一大片模型的连锁反应,最后都无法判断哪个模型对象有效了。没有了setter,整个世界就清净了。一旦建造,始终有效。
接下来是getter。众所周知,软件设计里最重要的原则之一是“Separation of Concerns”。我的理解是,不同的事情交给不同的东西做。领域对象行为是负责执行系统指令的(commad);而getter负责访问数据,也就是数据查询(query)。commad和query的分开,意味着不需要为了一个简单的数据查询(往往是事务脚本模式),而在内存里装载一个个满带功能的业务对象了。而且有getter,就会有别的对象调用getter,在重构中,是一个典型的smell,就是data envy,摆弄其他对象的属性。
没有getter,setter,如何查改数据? 解决方案是 一个没有getter,setter的领域系统,一个数据库查询系统,双管齐下。两者之间通过event系统来监听领域模型的数据改变。
可能抛弃getter和setter,DDD和OOP的世界会更好一点。