[u][i]这个系列是早前发布在部门wiki上的,引导组里的兄弟入门OOD,希望同样对刚刚走到OOD门前的同学有用。 [/i][/u]
按照面向对象的观点,软件中的实体应该是对现实世界中实体(或者概念)的模拟,这种模拟包括名称、属性(状态)和职责。打个比方,在软件世界中定义"狗"这个对象,我们需要从现实世界寻找启发,定义如下:
[img]http://dl.iteye.com/upload/attachment/151241/6e11336a-30cd-3339-b9db-3395e0653ec0.jpg[/img]
狗的属性和动作都是对现实世界中的模拟,这样你玩星际的时候招募了一条小狗,你知道其实是创建了一个狗的对象,它有类似现实世界的这些属性和动作。这种模拟就是David老师经常提到的"低表示差异"。
但是返观我们写的程序,XXXDTO,XXXDAO,XXXService,XXXController,这些怎么看都在现实世界中找不到对应的实体或者概念,你能走在路上看到对面过来一个GatewayPayOrderDAO吗?GatewayPayOrder是一个现实中的实体,如果没有我们的系统,我们可以设想有个商户拿着一张纸制的网关订单找到我们,然后我们按照上面的卡密进行充值确定点数,然后把点数打到商户的账户上,这是现实世界中的采购业务,商户卖给我们卡密,我们给他们点数。按照对现实世界的模拟,GatewayPayOrder应该类似下面这样定义:
[img]http://dl.iteye.com/upload/attachment/151243/dc7640b0-fc7e-3dcb-96ed-fab683ce17fa.jpg[/img]
订单应该是一个有属性有职责的实体,跟其他的实体一起协作完成整个业务。但是我们系统中的GatewayPayOrder却是一个标准的JavaBean,封装一堆属性,只提供set/get方法,持久化逻辑被放进DAO,业务处理逻辑被放进Service。为什么会是这样?
我对此的理解是:我们已经远离了面向对象的原始社会,生活在 "企业级开发"的现代社会。这里的"原始"和"现代"不是说落后和先进,而是说软件开发所处的环境。处在"原始社会"的人们,要自己处理所有的事情,除了要实现需求(即业务逻辑),还要关心持久化,多线程,安全,事务,分布式,远程交互等柴米油盐的琐事。随着"企业级开发"的进展,要构建的系统越来越复杂,软件被切割,分离,通用的东西被单独封装起来,比如多线程,安全,分布式被封装到应用服务器(所谓的中间件)和"组件模型"(比如EJB)中,持久化、事务被提取到专门的OR Mapping框架,远程交互被封装到RMI,Web Service中,甚至对象间的依赖关系管理也被封装到了框架(比如Spring)中。于是我们这些程序员出门有公交,吃饭有餐馆,取钱有银行,生活的基础设施健全完备。也正因为这个原因,我们需要按照框架的要求和前人已经证明过的原则重新面对"面向对象"这个概念,封装持久化逻辑的DAO,封装业务逻辑、业务规则的Service,用于分层架构层间传递数据的DTO,这些很难在现实世界中找到对应的"对象"应运而生。
在《UML和模式应用》这本书中把DAO之类的对象定名为"纯抽象",它们的出现是按照"高内聚,低耦合"的原则,把多种对象内的共有逻辑(比如持久化)单独抽取封装出来而成。由此可见,即使生活在条件优越的"现代社会",一些关键的"生存法则"还是延续了"原始社会"的经验教训,这些"生存法则"就是面向对象的理念、原则、方法。明白了这一点,我们在写XXXService,XXXDAO的时候就需要根据一些原则和方法想一想,我们是不是真的需要这样一个"对象",以及它应该承担什么样的职责,封装什么样的逻辑。
按照面向对象的观点,软件中的实体应该是对现实世界中实体(或者概念)的模拟,这种模拟包括名称、属性(状态)和职责。打个比方,在软件世界中定义"狗"这个对象,我们需要从现实世界寻找启发,定义如下:
[img]http://dl.iteye.com/upload/attachment/151241/6e11336a-30cd-3339-b9db-3395e0653ec0.jpg[/img]
狗的属性和动作都是对现实世界中的模拟,这样你玩星际的时候招募了一条小狗,你知道其实是创建了一个狗的对象,它有类似现实世界的这些属性和动作。这种模拟就是David老师经常提到的"低表示差异"。
但是返观我们写的程序,XXXDTO,XXXDAO,XXXService,XXXController,这些怎么看都在现实世界中找不到对应的实体或者概念,你能走在路上看到对面过来一个GatewayPayOrderDAO吗?GatewayPayOrder是一个现实中的实体,如果没有我们的系统,我们可以设想有个商户拿着一张纸制的网关订单找到我们,然后我们按照上面的卡密进行充值确定点数,然后把点数打到商户的账户上,这是现实世界中的采购业务,商户卖给我们卡密,我们给他们点数。按照对现实世界的模拟,GatewayPayOrder应该类似下面这样定义:
[img]http://dl.iteye.com/upload/attachment/151243/dc7640b0-fc7e-3dcb-96ed-fab683ce17fa.jpg[/img]
订单应该是一个有属性有职责的实体,跟其他的实体一起协作完成整个业务。但是我们系统中的GatewayPayOrder却是一个标准的JavaBean,封装一堆属性,只提供set/get方法,持久化逻辑被放进DAO,业务处理逻辑被放进Service。为什么会是这样?
我对此的理解是:我们已经远离了面向对象的原始社会,生活在 "企业级开发"的现代社会。这里的"原始"和"现代"不是说落后和先进,而是说软件开发所处的环境。处在"原始社会"的人们,要自己处理所有的事情,除了要实现需求(即业务逻辑),还要关心持久化,多线程,安全,事务,分布式,远程交互等柴米油盐的琐事。随着"企业级开发"的进展,要构建的系统越来越复杂,软件被切割,分离,通用的东西被单独封装起来,比如多线程,安全,分布式被封装到应用服务器(所谓的中间件)和"组件模型"(比如EJB)中,持久化、事务被提取到专门的OR Mapping框架,远程交互被封装到RMI,Web Service中,甚至对象间的依赖关系管理也被封装到了框架(比如Spring)中。于是我们这些程序员出门有公交,吃饭有餐馆,取钱有银行,生活的基础设施健全完备。也正因为这个原因,我们需要按照框架的要求和前人已经证明过的原则重新面对"面向对象"这个概念,封装持久化逻辑的DAO,封装业务逻辑、业务规则的Service,用于分层架构层间传递数据的DTO,这些很难在现实世界中找到对应的"对象"应运而生。
在《UML和模式应用》这本书中把DAO之类的对象定名为"纯抽象",它们的出现是按照"高内聚,低耦合"的原则,把多种对象内的共有逻辑(比如持久化)单独抽取封装出来而成。由此可见,即使生活在条件优越的"现代社会",一些关键的"生存法则"还是延续了"原始社会"的经验教训,这些"生存法则"就是面向对象的理念、原则、方法。明白了这一点,我们在写XXXService,XXXDAO的时候就需要根据一些原则和方法想一想,我们是不是真的需要这样一个"对象",以及它应该承担什么样的职责,封装什么样的逻辑。