怪怪 | Nothing, Everything

"有过一个发疯的时刻,有感觉的钢琴以为它是世界上仅有的一架钢琴,宇宙的全部和谐都发生在它身上." - 狄德罗
随笔 - 104, 文章 - 3, 评论 - 2004, 引用 - 44
数据加载中……

回帖整理: 关于面向对象与数据操作的集合贴

以后关于这个话题, 零碎但有些价值的讨论统一更新至此帖, 有一定内容了再定期整理。

原帖: 关于业务层代码的组织

回复:

你说的稍微有点简略,不过如果你指的业务操作是数据库相关操作的话:这个问题1年前干嘴仗的结果好像说的很清楚了。

CRUD这类操作不属于BL的范畴,应该放入边界对象里; 对象是否贫血, 要看对象是否真的存在自身的业务逻辑。那种认为相关数据操作应该在对象身上就更面向对象的说法,实际上是没真正学过这方面知识的人的一知半解。

不过大嘴Fowler的书里ActiveRecord等两个方式的一个表现出来的特征就是CRUD在对象上(有时通过基类搞定),这种设计很多时候也是行之有效的; 同时是不少ORM/半ORM工具箱所采取的做法之一(虽然我对ORM极端不感冒)。不过, ActiveRecord的实质还是处理行数据等操作,其对象形式只是一个伪装; 以我的观点,恰恰是不那么干净的设计,这样的对象干脆就叫混血对象吧。

另外, ActiveRecord...,我有时候真想不通能给咱带来什么好处。难道Object.Delete()打起字来比较爽? 所以我个人觉得你这种做法很不错, 只是我不喜欢代码生成的方式 :P

同时,我认为如果是彻底贫血的对象, 可以好好考察一下它是否真有必要以确定为某一具体型别的对象的面目出现; 而不是反过来对该型别的对象缺乏操作耿耿于怀, 恨不得把所有和它沾边的事情都交给它负责。

资料:
别在领域模型迷失了自己,在当前讨论的这个论题中,我们着重要把握的是找准“系统边界”; 比如,对于该文中的“域控制器”, 我们应结合上下文去体会其角色, 就不难理解设计对象时的要点了。

还有一些其他的素材,包括思归在一些主角的博客里的留言也很有画龙点睛的作用(以至于到现在还有印象),一时收集不全了,慢慢找吧。

posted on 2008-03-12 06:14 怪怪 阅读(1378) 评论(16)  编辑 收藏

评论

#1楼    回复  引用  查看    

我做的项目中有一些内容属于所谓的“贫血”对象
还有一些则包含了一些“领域逻辑”
仔细看一下发现
那些“贫血”对象绝大多数就是针对于数据访问的
是不是可以认为,它们存在,就是因为它们的“贫血”
因为“贫血”,它们的职责仅用于与数据库的对象进行交互;
那些包含了一些“领域逻辑”的对象则往往与数据访问无关
这些对象有着更多的行为。

你的这句“而不是反过来对该型别的对象缺乏操作耿耿于怀, 恨不得把所有和它沾边的事情都交给它负责。”,是不是可以帮我确认自己的观点?
2008-03-12 10:11 | Anders Cui      

#2楼    回复  引用  查看    

直接用代码体现我的方法(不擅言辞)
BLL API:
public interface IPhotosList:NClay.IDataPageProperty
{
string CategoryID
{
get;
set;
}
IList<Entities.Photos> Photos
{
get;
set;
}
}

BLL HANDLER:
public void List(Api.IPhotosList logic, Photos.Mapper p, CategoryPhotos.Mapper cp, Expression exp)
{

if (!Common.IsEmpty(logic.CategoryID))
exp &= p.ID.In(cp.PhotoID, cp.CategoryID == logic.CategoryID);
logic.DataPage.PageSize = 20;
logic.DataPage.OrderField = p.CreateDate.DESC.Name;
logic.Photos = exp.List<Photos>(logic);


}
补充:handler参数是注入的.
2008-03-12 11:12 | henry      

#3楼 [楼主]   回复  引用  查看    

如果你指的是该对象没有和数据持久打交道,我觉得答案就是肯定的。 如果你指的是该对象不是数据在内存中的副本,则不一定了。

我的意思大概是这样: 对象作为数据在内存中的副本,可以同时具有业务逻辑,而且有时候应该具有业务逻辑从而表现为一个"充血对象"; 但如果它的业务逻辑就是没有逻辑或操作,则是一个合理的贫血对象。

我老觉得,我们最早写的代码,出于无杂念的人的智力判断,其实包含着一定合理性,只是我们意识不到; 同时那些不合理,是因为我们对其它设计知识不熟悉的缘故。

但是等有了一定成长,有时候会因为对某些设计知识熟悉但不没有深入理解,结果把最初当菜鸟时选择上的合理性也一并扼杀了。结果反而做出看着头头是道,实则很要命的设计。

关于贫血,我觉得确认其合理性的下一步, 就是质疑每一个贫血型别的存在了;用"每一个"的原因是,我还不敢说,所有贫血对象都没必要存在; 只是由于贫血对象实际上离字典只有一步之遥(想想JavaScript),我们应该考虑在不同的具体情况下,天平如何倾斜的问题。
2008-03-12 11:24 | 怪怪      

#4楼 [楼主]   回复  引用  查看    

@henry
嗯,一半是这个意思 :)

只是对于IDataPageProperty作为更基本的接口,从而拥有DataPage.PageSize这些,个人感觉从纯粹性角度来看,是在污染对象的纯洁性; 比如你的IPhotosList到底是什么身份很难确认。

当然,相比解决问题,纯洁性其实没什么重要。
2008-03-12 11:32 | 怪怪      

#5楼    回复  引用  查看    

@怪怪
其实作为接口都有其约束意义,如果接口名称表达不到其意是名称定义上的问题:)
接口并没有污染对象的纯洁性,其目的只是说明在其约束下完成的事。
2008-03-12 12:47 | henry      

#6楼 [楼主]   回复  引用  查看    

@henry
呵呵, 其实咱俩说的不是一个东西。

我的意思其实是: 如果将IPhotosList看作承载业务逻辑的对象,它*可能*因为IDataPageProperty包含了业务逻辑以外的约定。

但其实光看你这个IPhotosList,就知道能比较好的应用于上下文中。 这时候就牵扯到对业务这一概念不同的划分方式: 可以认为比如分页等特性(按你的说法“完成的事”)是业务的一部分,也可以认为这些特性更多牵扯到数据层面的概念。

如果是后者, 就可以认为IPhotosList的身份比较可疑, 同时, 如果把它看作一个业务逻辑对象的接口,它就是被污染的。因为在这种认知方式下,它暴露的接口, 与不相关的概念可能存在着某种交集的意味。

但在我臆想的你应用的环境中, 我觉得存在这样的模糊(可以采取不同的认识方法),恰恰是设计上的优势。 所以并没有吹毛求疵的意思; 在我们现在能接触的设计理念范围内,你这种设计在很多场景下是相当合理或者说出色的。

现在我所关心的东西, 是比较理论化的层面; 说实话, 也是说大话, 我希望自己能通过理念上的修正或小小的创新, 找到一种更不同一些的设计方式。
2008-03-12 13:52 | 怪怪      

#7楼    回复  引用  查看    

@怪怪
归根结底其实只是一个设计如何让开发人员知道并如何使用。就如ICollection ->IEnumerable
很多时候内聚一些东西然后抽取某个规则,如果规则没有讲述其作用开发没无从入手(MSDN的习用手法:此类型不见意直接在代码中使用)。
所以有时候太执着地去区分某些细节是不是真的有必要。
2008-03-12 17:18 | henry      

#8楼    回复  引用  查看    

我也做了几个项目了,其复杂度也不是很简单,但是我却没有发现“业务逻辑层”的存在。

只有几个小的地方是比较复杂或独立的,可以放在“逻辑层”里。

其他的都是sql语句了。

为什么呢?领域模型到底是甚么呢?

是不是我不用实体类的原因呢?


我些项目大多数的时间都是考虑:

在什么时候(哪个网页/操作),把什么样的数据放在哪个表的哪个字段里面。
或者从哪个表里读取哪些信息放在哪里显示。

都考虑明白了,然后写sql语句(当然事先要设计好数据库),然后就实现了客户的需求。

也许是我直接把表当作实体类了?

2008-03-15 14:06 | 金色海洋(jyk)      

#9楼 [楼主]   回复  引用  查看    

@金色海洋(jyk)
你这种做法,之所以老被人说这说那,是因为缺少一个概念层面的支撑。我最近正在思考这个,有了结果咱再交流。
2008-03-15 15:43 | 怪怪      

#10楼    回复  引用  查看    

这个是一个原因,但不是最主要的。

最主要的是我现在还不想完全公开我的想法和现在的做法。

如果前两年就公开的话,现在一定会有很多人理解,也会有很多人使用吧。

不过公开了也是一个“危机”,因为用我的方式不需要“软件蓝领”,就是说不再需要很多人来编写代码了,因为根本就没有那么多的代码可写。
需要的是对数据库(包括SQL语句的使用)很了解,对业务逻辑很了解的人。

另一个原因就是,没有一个公司作为支撑,弄不好就是给别人做嫁衣了。

2008-03-15 18:40 | 金色海洋(jyk)      

#11楼 [楼主]   回复  引用  查看    

@金色海洋(jyk)
呵呵, 你想的太多了。

如果你愿意听逆耳之言的话(我不想让你不高兴,因为已经把你当作朋友了),我想说,高估自己不如低估自己; 尤其是你想想,大家干得活都差不多, 智力水平差不多, 也都挺懒的不愿意做重复性或者无效的劳动。

其实就我这一年对你的思路的了解,我感觉其实现实中好多人都是这么做的,当然具体方式会有些差异。 如果说我还不太清楚你表达的是什么, 咱们可以从效果上来说: 在咱们经常讨论的范围内,就像我很久以前说的,不少实用性程序员所采取的方案,在ASP.NET 1.1的时代, 就能做到除了业务逻辑, 无需写什么多余代码,那是相当的灵活。

无需否定你的方案和一些在那矫情ORM或者几层的兄弟,在很多方面更具有优势。只是可能园子里的环境给了你一种误解, 认为别人都是在绕着弯子找不痛快。 其实一些人在不恰当的场景使用了自己给自己找麻烦的做法,不过因为急于像他们心目中的专家靠拢,以期快速提高自身的价值罢了。 只是园子未必就能代表大多数埋头苦干的程序员。

另外我说的概念层面, 是指你的做法中,缺少"概念"这一要素在实际设计和代码中的体现; 我思考的也正是这个: 如何把概念严格的反应到设计和代码中(而且最大限度的利用编译器检查),又避开其他人所碰到的面向对象综合症。

既然让你不高兴的话已经说了, 我也不用客气了, 还是我原来说的,好坏你自己判断吧... 就是一些人研究的那些似乎不着边际的东西, 正是你所缺乏的; 说实话我每次看你对大家的文章说看不懂, 我不知道你是不是在表达“对我干的这些活没用”这个意思。

只是我诚恳的说一句,很多东西必须先扬后弃; 如果你不去掌握那些东西, 可能就无法把你的优势和特点升华了,到了一定地步,就会停在原地打转了。相反,如果那些研究一些东西研究的糊里糊涂的兄弟, 过了当前的阶段,必然会回归朴实,从而兼顾你现在所表现出来的优势。

愿意听这些话么? :)
2008-03-16 05:14 | 怪怪      

#12楼    回复  引用  查看    

很感谢。有一个朋友和我说心里话,我怎么会不高兴呢?

想起了论语:有朋自远方来不亦悦乎!

在公司里面的交流中,技术层次的也不多。所以我比较苦闷,自己的想法和其他人的想法到底差在哪里,也只能靠猜测。

所以很想看到大家的代码,petshop的那种是不爱看了,也许应该再看看?


好向高手都不太爱发表自己的方法。

有空见面了吧,你去爬山吗?


说到概念,如果说直接用 现有的数据库来表示对象,你会接受吗?或者说理解。

上面的说法不准确,反正我是把字段(包括自己加的扩展信息)当作实体类的属性了。这样操作字段的SQL语句也就自然地变成了“业务逻辑”的实现方式了。




至于说看不懂嘛,原因就有很多了,主要的原因就是,时间比较紧,没有仔细看,当然也可以理解成你说的“对我干的这些活没用”。

现在出差也确实没有太多的时间来看关系不大的,前沿的知识。

只能说等松下来再看了。

另外就是对于猫了、鸭子了这一类的举例,理解起来也确实比较吃力。
2008-03-18 15:11 | 金色海洋(jyk)      

#13楼 [楼主]   回复  引用  查看    

@金色海洋(jyk)
我是理解而不能完全接受。 我的想法是,对机器,我们无需表现出什么概念,概念是帮助人做工作的。所以我打算在面向对象之外, 找一种新的表达概念的方法,现在我每天想的就是这个。

PetShop我觉得倒不用多看了, 先看那些书, 集中体会作者的意思。 反过来注意一下各种例子,比如像PetShop这样的, 但是扫几眼,把书中的概念对应上就可以了,然后就是琢磨。 把他们为什么这么干, 核心思想是什么体会了, 就可以用来反思自己的做法,提升它, 但不是把自己的做法往书上或者例子上靠。
2008-03-19 10:42 | 怪怪      

#14楼    回复  引用  查看    

今天看到了一个软件,已经用了(不断更新)十多年了,现在已经很完善了,只是显示速度有点慢,大家猜猜是用什么语言写的?

Access 2000 (可能一开始是用 Access 98 来写的吧)。

Access 数据库作为基础,加了一些窗体,就成了一个软件。是用ODBC连接远程的 Access 数据库,这样就实现了多用户同时操作同一个Access 文件。也就是 c/s 结构。

还有统计图片的功能。(这个不知道使用什么来实现的,反正都是在同一个窗体里显示出来的)。


======================

发现了一个以数据库为主的软件的一个很致命的问题,一旦数据库被对手掌握了,那么就意味着软件被破解了,对手可以随意而用,可以很轻松的得到“精华”。

因为对于行业的理解,业务需求的消化,全都会体现在数据结构上面。

而面向对象就安全多了,因为“精华”都隐藏在代码里面。即使发现了也不好是用,除非是核心算法。



2008-03-19 18:42 | 金色海洋(jyk)      

#15楼 [楼主]   回复  引用  查看    

@金色海洋(jyk)
倒...

别太关心这个问题。

数据结构的优点和思考的结果是可以被外泄的, 但是你对行业的理解、经验和分析能力是绝对不会外泄的..

其实对我们IT从业者来说,更多的关键是我能干什么。 代码一写出来,数据结构一设计好,就不要太在乎了, 都是过去式。

Access再好使,也比不过FoxPro啊...,可惜都快不在了。真正使用这些数据库、半数据库产品的问题是对它们形成的依赖,我从来不追求可移植性, 但是是我仍然反感这种依赖....
2008-03-19 20:33 | 怪怪      

#16楼    回复  引用  查看    

因为是同一个行业里的两款软件,一款(Access)的,已经好几年了,久经考验。字段信息也是非常丰富的。

另一款(就是我做的),刚作出来还在调试中,哈哈,所以能够得到它的数据结构的话,我就可以节省很多的时间。

轮对行业的了解嘛,我们也不差的。
2008-03-28 17:37 | 金色海洋(jyk)      

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
博客园首页

新闻频道

社区

小组

博问

网摘

闪存

  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-03-12 07:08 编辑过
成果网帮您增加网站收入


相关链接: