怪怪 | Nothing, Everything

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

怪怪设计论: 抽象无处不在

现代的软件科学中, 很多内容和概念, 实际上是从数学/语言学等相当古老的领域里借来的, 为什么呢? 因为软件科学中的很多方面, 与其它学科中所碰到的问题并无不同. 一套数学理论,某个数学公式,无论从哪个层次去看,和它们有关的人分为两种:发明者,使用者. 这和软件也是相当一致的,  软件首先要有人编制, 然后别人来使用(好不好另说). 数学的一个特性就是他的抽象性, 本文讨论软件设计中, 由抽象所展开的一些问题.

对抽象的理解的误区可能使得很多人忽视了广泛存在的抽象. 因为接口和类如何抽象现实事物的种种说法, 在很多人的观念里混淆了在设计时具有的抽象, 从而对抽象的本质进行的歪曲, 忽略了除OO建模以外抽象, 或者在OO建模这个过程中选择了错误的抽象方式. 显而易见的, 比如数学实际上是一种对现实事物相当高级的抽象, 与此同时, 数学也就成了一个相当良好的解决问题的工具. 而我们编程人员所担负的责任导致我们的工作, 本质上是一个抽象和构造的过程. 所以如何抽象合理合法, 是我们首先要关注的一个问题. 那么我们首先要知道的是,什么是抽象方法?按照数学抽象方法的解释变化一下,我们可以得到如下一个描述:

抽象方法的软件设计版本
抽象方法是从考虑的问题出发,通过对各种经验事实的观察、分析、综合和比较,在人们的思维中撇开事物现象的、外部的、偶然的东西,抽出事物本质的、内在的、必然 的东西,从空间形式和数量关系上揭示客观对象的本质和规律,或者在已有软件设计成果的基础上,抽出其某一种属性作为新的软件设计对象,以此达到表现事物本质和规律 的目的的一种软件设计领域的研究方法。


以上描述,基本是把数学换为“软件设计”就能得出的结果. 比如在几何中, “点”的概念是从现实世界中的水点、雨点、起点、终点等具体事物中抽象出来的,它舍弃了事物的各种物理、化学等 性质,不考虑其大小、仅仅保留其表示位置的性质。从这里我们可以看到, 为了研究和解决问题而进行的抽象, 在数学领域中和现实世界中多么的不同. 但是进行抽象前, 一个潜在的前提被忽略了, 即几何这个数学工具要解决的问题, 决定了抽象的结果. 很显然换一个领域解决其它问题, 比如研究雨滴的物理特性, 抽象的结果就完全不同.

由于软件解决的问题往往是千差万别的, 这就导致我们抽象的结果, 从一个常规的角度看, 往往不能够逼近现实世界, 且对相同的东西, 表示的方法很不统一. 甚至突然看去, 和现实世界是那么的不同. 这也是很多OO狂热者所误解的一个想法: 与现实世界偏离太远的一组模型不是好的模型, 从而忽视了一个人类解决问题而发明的比如数学(或其它科学)这些最高效的工具, 从来和现实世界是不同的. 比如 E = MC2, 它真实的表达了事物的本质, 却并非是一个直观上与现实世界相似的表示方法.

我们考虑软件设计中, 存在某一客观事物. 往往一个熟知面向对象的设计方法的人员, 就把这一事物抽象为一个对象, 然后抽象出它的属性(数据)和方法(行为). 在这一过程中, 经常被忽视的一个问题是, 由于软件设计所面对的客观情况的复杂性, 我们常常会面临解决不同的问题, 在解决不同的问题时, 应该使用不同的抽象. 由于在脑海里没有清晰的问题域, 在很多人看来, 这(同一事物不同抽象)就硬生生的把一个事物割裂开来(其实可以不同抽象同一实现来重新统一, 但设计的合理仍然依赖于不同抽象的必要性), 不自然, 于是不合理不合法.

比如贫血模型的好与坏, 比如Martin所划分的"事物脚本", "表模块", "领域模型", 都是在这样情况下产生争论的. 这个在上个关于充血贫血讨论的回帖中已经有论述, 我已经把回帖单独提出来, 有兴趣的朋友可以讨论. 拿Martin划分的三种方式来说, 以本文开头对于抽象的定义, 想必大家可以达成一个共识, 即无论采用那种方式, 都是对事物的一种抽象, 区别只是好坏问题. 看过我的回帖的, 应该有这么一个印象, 即谁好谁坏, 并不是以符合那种方式就可以分辨的(Martin同学也承认).

在我们的某个项目实现和实施的过程中, 除了对象, 方法, 属性这些东西, 还有什么是对事物的抽象? 不知道大家还记不记得数据库教科书里面教我们的那些? 没错, 就是那些几NF之类枯燥无味乱七八糟的东西. 我发现这样一个事实: 讨论面向对象软件设计的各位牛人之中, 很少有关注数据库设计的. 其实数据库设计的书现在也是车载斗量; 从深度和实用性讲, 数据仓库是一门更博大精深的学问. 其实咱们大多数讨论谈到的数据库, 在数据仓库大牛, 如Ralph Kimball眼里, 不过是个源操作环境(名词可能记的不准确). 而百万行级上百个表甚至更多的数据, 如果要产生价值, 不使用数据仓库的种种设计方法, 那么其实跟废数据区别不大.Ralph是什么观点呢? 数据的设计是如此的重要, 如果没有良好的数据表现形式, 沃尔玛的老板永远不会知道啤酒和尿布之间存在着什么样的联系, 结果基于数据做出的决定让啤酒大幅的增加了销量.

某些兄弟提到, 将软件(不包含数据库等)设计的结果作为数据库设计(作为数据的结构设计的一个子集)的前提和约束. 通过这样的手段, 把数据设计稳定下来, 绝对是一种行之有效的手段, 但它很难变成一种放之四海皆准的设计手段. 这个是自顶而下方法论大师们的一个误导(大嘴们经常犯这个错误): 光拿出一个方法, 却忘了交代该方法所针对的问题.

请注意数据仓库领域中"维度建模"这个词, 不用搞清楚数据仓库到底是什么, 也不用搞清楚什么维度不维度的; 存在这个就足以说明, 建模不只是纯粹的软件结构设计的问题. 至少在Ralph所研究的系统里, 恐怕数据仓库的设计要比软件结构设计重要的多. 道理很简单: 数据的结构是合理的, 那么针对数据的操作可以有各种合理的版本, 未来业务变化, 新增不同数据和构筑在不同数据之间的处理也很容易; 同时, 请不要忽视一点: 数据不应只是简单的行的堆积, 数据本身是存在广泛联系的, 而且数据本身也要表现出这种联系; 更要命的是, 数据如果被要求发挥最大的价值, 那么其表现形式的抽象过程比其它任何东西都需要小心对待.

在我看来, 这个(数据驱动还是对象驱动)问题的关键点在于, 用户到底要的是数据, 还是软件? 可能大多数人回答是软件. 其实拿沃尔玛来说, 他要的是数据, 以及和数据相互作用之后数据. 当然如果没有软件, 沃尔玛的全部员工翻所有数据翻10年也翻不完, 更不论计算了. 但是如果只有软件, 那么我只能一摊双手, 告诉你这儿社么都没有. 软件是人收集数据的簸箕, 观看数据的窗口, 是计算数据的工具. 让我们来看看Brooks曾经说过什么吧:

原文引用更普遍的是, 战略上突破常来自数据或表的重新表达--这是程序的核心所在. 如果提供了程序流程图, 而没有表数据, 我仍然会很迷惑. 而给我看表数据, 往往就不再需要流程图, 程序结构是非常清晰的.

当然, 是不是真的不需要流程图, 我看他在这里也学了Martin大嘴了一把(虽然他年纪更老, 也更大牛一点). 当然也许Brooks的意思是他可以一直研究某种很复杂的表数据长达若干年直到完全搞定, 这样看我也赞同他的观点: 有表数据已经无敌了. 重要的是前半句, 如果我们把"程序流程图"没有指代但在软件设计中除了数据设计外其它内容包含进来, 他们全都没有会怎样, 数据成了废数据? 这就是千百万的$所换来的结果? 那么让我们干脆点, 问一个问题, 没有软件会怎么样?

实际上, 数据库已经存在千百万年了, 只是在计算机上实现, 是这几十年的事. 我们考虑60年代的人口普查表, 和现在的不会有什么不同. 在这个表上就存在着种种抽象: 一个人不是姓名年龄性别出生日期就能代表的, 实际上表上行, 就是对真实存在的人的抽象. 因为人口普查这个问题域, 需要这种抽象. 往往这种抽象, 还是经历几十年甚至上百年反复调整和重构, 才得到的结果. 所以抽象并建模对于人类来说实际上早就开始了. 那么进行数据驱动式的设计理由是充分的: 我们首先需要的是数据本身的表现形式的正确性. 看看Ralph和Brooks的潜台词: 数据的表达应该包括足够的信息. 在数据这一层面, 对于Brooks来说, 良好的抽象能造成软件整体的突破(对计算机世界); 对于Ralph来说, 良好的抽象能更多的挖掘出数据所隐含的信息(对现实世界).

当然, 这不说明(在一些领域内)对象驱动是不合理的, 但这足够说明, 数据库仅仅用来存储对象的状态, 而由面向对象的设计来抽象整个世界, 这个情况并不常常发生, 其原因是从某种程度上来说, 至少对于沃尔玛的老板, 追逐软件而不是数据本身是舍本逐末的. 经常的, 对于居委会老大妈来说, 数据表现形式的设计就是对世界最好也最急需的抽象. 所以对于是否对象驱动通吃, 就引出了下一个问题(答案往往是层层拨开的) : 面向对象的设计最终产生的存储对象状态的数据结构, 是不是在任何领域内都能和直接抽象出来的数据结构一样好? 抱歉我暂时没法回答这个问题, 因为这篇文章简直是走到哪儿, 写到哪儿, 我还没真正思考过这个问题. 当然, 如果我是大嘴Martin, 我会直接告诉你不能...

不过没有答案, 不妨碍不能从其它周边的角度来进行一下讨论:

公元前二百二十一年, 秦始皇统一中国. 如果我们不过分的贬低古人的智慧, 可以考虑这样一个问题, 如果OOA/OOD真的能够得到良好的数据结构, 而且比直接数据设计合理, 那么是不是OOA/OOD中, 最后能决定数据的表现形式的这一部分方法, 早在秦始皇记录到底谁有几本书好烧掉它们的时候, 就开始被人研究和发掘了呢? 毕竟薛定谔的代数方程和哥本哈根学派的矩阵力学最后的表达的都是一码事, 只要有条路通到罗马, 这条路就应该有人走才对.可历史上对数据的建模并不存在这样一个设计步骤, 当然你可以说这个那个OO里也有, 但这是OO借用人家的; 这是这个考虑的一个方面.

另一个方面, 我们需要看看抽象出来的工具中最璀璨的明珠, 数学. 数学的抽象, 不但实际上和面向对象背道而驰, 而且他们的数据表现形式, 往往和居委会老大妈掰脚趾头全无区别, 比如那些和自然数列一一对应的问题. 它们对现实世界面向过程的抽象方式, 跟真实世界简直是驴唇不对马嘴, 却更贴切的表达了很多事物的本质.

与面向对象设计相反的, 提炼关系(函数)/元素/集合的面向过程抽象方法, 关系型数据库本身和基于它的设计和抽象, 却是从数学, 尤其是集合论等抽象的工具中, 直接衍生出来的. 从这里, 我给出一个个人对软件设计的认识, 它对一些人来说是颠覆性的, 信不信由你:

面向过程和数据表现形式的设计, 是比面向对象更高层次的抽象, 而且优秀的面向过程和数据设计, 是对解决问题更有效的抽象, 因为它们抛弃了一切可以抛弃的无用负担.

当然, 能合理驾驭面向过程和关系模型的人, 恐怕脑容量得远远高于常人, 以至于Martin这个大嘴说:

原文引用事实上, 我一直坚信面向对象的最大优点在于它能够使复杂逻辑易于处理.

这很显然就是在说: Martin的脑子不够处理某些逻辑, 所以不得不借助面向对象这个拐棍. 当然估摸着脑筋够用的人很少存在, 于是大多数复杂性够高, 同时面向过程的项目失败了. 不过请考虑一下我们在集合论中学过的那些, 函数的定义, 关系的定义, 等等等等, 由集合论的方法来看, 我们解决问题时,要找到的实际上常常是一个集合S, 一个a和一个b, 以及一个连接a和b的关系R.

在这里需要申明的是我绝非一个DBA跳到程序员堆里玩深沉, 我从来没设计过真正需要数据仓库的系统, 而且我现在的工作与数据库完全无关. 同时我是一个坚定的面向对象的信徒, 我也绝对不会说, 实用主义的话应该怎么怎么样, 因为我不相信什么实用主义. 象遗留系统等问题, 是客观存在的情况, 一个新的系统是可以对由于遗留系统产生的问题进行一次抽象, 让新系统至少是新的; 上帝的归上帝, 凯撒的归凯撒, 本该如此就是最大的实用主义. 但是我要知道我使用的(面向对象这一)工具到底是干吗地的, 帮我解决了什么问题, 而不是神话之(过犹不及嘛), 这样才能最大化这一设计工具的最大价值: 面向对象的抽象方法就是把我玩不转的形式, 转化为玩的转形式的这么一个工具. 在这里, 给出第二个我个人的认识:

面向对象仅仅是帮我们前进的一个手段, 他通过增加一些从根本上讲毫无意义的细节和表达形式等冗余, 使得我们能更好的组织我们的过程与数据.

接下来说说另外一个抽象过程中经常发生的问题: 忽略了对计算机世界进行抽象和建模的重要性. 而这个问题和如何对现实世界进行建模有着相同的重要性, 很显然, Int32是一个抽象, String是一个抽象, 问题是当我们编制软件的时候, 光是这些对象是不够的(人家Martin Fowler说了, 这叫基本型迷恋), 很多人对这一点认识不深, 导致重视不足. 而对远离基本型迷恋的原因, 大嘴们给出的解释又过于浮浅, 将很多与基本型迷恋相似的问题给淹没了.

我提请大家注意一个非常重要的事实: 在.NET Framework里, 或者Java的各种框架里, 实际上存在着非常大量的与现实世界无关的模型(即使一些模型与现实世界存在着相似性). 当我们构建一个软件或系统的时候, 每个人数的都是自己的代码行数, 其实要是将操作系统也作为提供的解决方案的一部分(甚至不包括操作系统仅包含用到的基础框架), 即便上亿美金的项目, 恐怕仍然是对非现实世界无关模型的使用占很大部分.

让我们基于这一事实进行一个想像, 假设.NET Framework是一个十分蹩脚的设计(其实ASP.NET的一些方面就相当蹩脚), 那么我们基于.NET Framework的项目, 综合考虑时间/人力等等成本在解决来自Framework的问题, 还有几个能成功呢? 而现在情况是, 基础环境或多或少的和我们特定的问题不合拍, 而大多数项目中的设计, 恰恰是根本缺乏对计算机世界的合理建模而直接构筑在通用框架或工具箱提供的模型上; 又或者有一个比如各种ORM这样的通用工具, 拿一个持久化的概念, 就把我们可怜的计算机, 操作系统, 物理存储的文档或者数据库给打发了. 这样的设计必然会造成, 要么数据表现形式看上去不合时宜, 要么面向对象的设计方法看上去很别扭. 在这种情况下, 特别是那种数据驱动的项目, 不能本能的考虑去修改数据库, 难道你能轻易抱怨.NET对String的实现吗? 所以在设计伊始, 就要考虑到你这个设计如何对来自计算机世界的现有事物进行抽象, 或者对现有事物与设计中其它部分的关系进行抽象, 才能最大程度的保证设计的完备与统一.

至于面向过程比较容易适应, 恰恰是因为这种抽象的表达方式更本质, 除非问题域变了, 否则 f = ma 做成一个静态方法, 摆在哪里永远不会废弃. 有新情况? 来个新公式吧. 当然, 面向过程也能做到重用, 多态, 问题是逻辑复杂度高于Martin的7.42, 人脑就到了极限, 正巧这7.42到底是啥还没个准谱. 所以说, 面向对象总是有益的, 但是如果对什么是抽象, 怎么个抽法,  都抽谁, 还存在着疑问, 那么实际上降低复杂度的同时, 也提高了各种事故出现的概率. 实际上一些基本问题, 现代编程语言已经帮我们处理了(这个以后探讨), 但是来自软件概念性层面上的问题和复杂性, 只有我们自己能解决.

关于面向对象如何帮助我们, 我会在后续话题里进行讨论. 毕竟这篇文章是介绍抽象的, 同时很大篇幅的讨论了数据驱动, 对象驱动和面向过程, 面向对象等抽象方式不同的意义. 让我们回顾一下:

1. 软件设计领域内, 抽象无处不在, 在面向对象中, 在面向过程中, 在数据表现形式中, 在界面设计中(这个没有提到). 加一句在本文没有体现的(也许未来我会加上相关论述, 这个认识相当重要), 软件设计, 归根结底不应该是对现实世界抽象, 而是对"就某个问题, 使用计算机去更好的解决"这一过程的抽象, 虽然这一过程往往包含对现实世界的抽象, 但多了个大方向, 进行对现实世界的抽象时, 方式方法就不一样了. 如果不认清这个问题, 无论是面向对象(多这个大方向并不会导致"不够OO"这种问题, 只会OO的更正确)还是其它什么方法, 无论你是Anders还是Gosling, 都不可能获得正确的结果.

2. 好的抽象的唯一标准是是否在正确的问题下良好的运转, 而并非是在直观上和现实世界多么的相似. 而且我们在生活中所能看到的很多最好的抽象, 往往在直观上与现实世界的事物毫不相似, 却在问题所在的领域内更接近现实世界事物的本质.

3. 面向过程和数据表现形式的设计, 是比面向对象更高层次的抽象(难道搞出一个汽车类, 不是具体化么), 而且优秀的面向过程和数据设计, 是对解决问题更有效的抽象, 因为它们抛弃了一切可以抛弃的多余内容. 面向对象的抽象方式仅仅是帮我们前进的一个手段, 他通过为抽象增加一些从根本上讲毫无意义的细节和表达方式等冗余, 使得我们能更好的组织我们的过程与数据.

4. 在一个大的问题域内, 如果数据表现形式的设计更根本,  就绝对不存在对象驱动还是数据驱动的问题,  只能数据驱动. 同时我们也要承认, 存在着很多领域,  数据只是操作模型的附属, 在这样的情况下, 数据到底怎么设计, 甚至可以发展到毫无重要性的程度. 与Martin对复杂度的分辨不同, 到底用户要的是什么, 这不是一个7.42, 而总会偏向于某一方.

5. 在设计中, 尤其是数据驱动的设计中, 既要考虑对现实世界的抽象,  也要考虑对计算机世界的抽象. 软件部分面向对象的产物与其它已知结构的冲突(比如与数据库设计的冲突), 其原因是没有把计算机世界某一部分(如关系型数据库及构筑于其上的数据表现形式)就软件所处理的问题域进行再次的合理抽象, 或者太轻易的处理了它们(比如, 忽视了数据本质也是一个接口这个隐含的约束).

最后送给大家Brooks另一句话, 这一句话曾经指导过1000W行以上的单一项目的设计, 同时也指导了软件设计长达40余年, 并且我想它还会作为一句少有的经典, 继续存在下去:

原文引用数据的表现形式是编程的根本.

这句话本身所真正拥有的真知灼见, 比他当时语境下所要表达的含义还要多的多. 这句话绝非从什么主义出发,无论你是一个面向对象的狂热信徒还是一个随便造个二进制文件当数据持久的高人, 我想仍然需要好好咀嚼一下.

posted on 2007-09-17 01:30 怪怪 阅读(5836) 评论(55)  编辑 收藏 网摘

评论

#1楼   回复  引用  查看    

看完了……
刷了一下发现题目也变了……
我想到底是领域驱动还是数据驱动,这个问题取决于不同的人,一个高手完全可以游刃有余,但是一般人可能会有所区别,适合才是正道,之所以有那么多的方法论并存着,本质上就是有很多不同的人在不同的领域有着不同的应用,因此本无所谓对错,不依赖实际的争论则没有任何意义,正如数学不能解决文学的问题一样……
文章中提到的抽象,并谈到面向过程比面向对象更抽象,记得之前的题目说到越好的抽象就对现实更加不一致(夜深了,记忆力成立方式下降,只记住了大概意思),应该也就是说,我们为了更容易描述、构建、维护、扩展我们的程序,我们就是为了让程序还原出现实的本质,而不是追求抽象,相比面向过程虽然在抽象的意义上有所领先,但这并不是我们所要的,也正如我们不可能写出一通百通的程序,那样的高度抽象从成本的角度讲又属于一个诺亚方舟了……
但所有面向对象的追捧者都必须明白自己的本质是在写程序而不是在写作文,过度设计的灾难也就是那些不了解数据本质的人可能会从键盘底下溜出来的思想漏洞。
楼主的写作风格需要读者有一定的功力啊,我真的不确定自己是不是理解对了作者的写作意图,明天精神好点要再看一遍……
顺便占个位置,因为我相信,楼下的评论会很精彩……

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

@volnet(可以叫我大V)
"应该也就是说,我们为了更容易描述、构建、维护、扩展我们的程序,我们就是为了让程序还原出现实的本质,而不是追求抽象"

看来我表达的就像你说的, 不够好. 是这么说: 抽象的越好, 越贴近事物的本质, 往往就看似与现实越不一致; 既不是说应该追求抽象, 也不是说不应该追求抽象.

只是:
1. 很多人认为越好的抽象, 就越面向对象, 其实正好相反.
2. 即使抽象再好, 如果我们没有一定的方法就很难做到, 这是人的认知能力所限. 也是面向对象之所以蹦出来的原因.
3. 领域驱动还是数据驱动的问题基本是你说的意思, 但是经常是有明确答案的.
4. 过度设计及其灾难有一些是错用了面向对象设计方法和自顶而下的设计方法所带来的. 因为如果讲面向对象的设计展开成面向过程的设计, 你就会发现一些错误是面向过程的设计(包括过度这种错误本身)照样可能犯的, 但另一些纯粹是因为画蛇添足(而直接面向对象时看不到).

重新把面向过程包装成面向对象, 也许会发现实际上往系统内增加了一些冗余的信息. 考虑到这是让我们能更好的组织的代价, 那么挑选较少增加冗余但合理的包装方式是人人都会的. 不过我们有时候不可能先写面向过程, 再包装为对象, 所以有掌握正确的面向对象设计方法就是一个很重要的事. 未来我会逐渐开始讨论这个话题, 目前只是抛出一些大家可能还没意识到问题.
5. 关于表达方式的问题, 这个确实是实用主义出发, 没有太多精力去改进, 不过未来可以重构不是 :)
2007-09-17 03:33 | 怪怪      

#3楼   回复  引用  查看    

关注。

终于忙完了任务,可以睡觉了,唉~
2007-09-17 04:29 | 木野狐(Neil Chen)      

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

@木野狐(Neil Chen)
重构了一下, 把不应放在一起的东西分开说了, 可惜最丑陋的版本被两位给看见了..
2007-09-17 05:04 | 怪怪      

#5楼   回复  引用  查看    

人最伟大的地方,就是可以将任何东西(灵异的除外)抽象成公式。。。
2007-09-17 08:15 | 邹健      

#6楼   回复  引用  查看    

早上一来就看到这篇强文,看了一遍,还有点晕,占个坑先。。。

事实上, 我一直坚信面向对象的最大优点在于它能够使复杂逻辑易于处理.
----------------------------------------
martin总说面向对象最大的优势就是处理复杂逻辑或者当业务逻辑复杂的时候怎样怎样。但是我怀疑当业务逻辑复杂到一定程度,即使再面向对象恐怕也无能为力。因为复杂度有时会达到开发人员脑力的极限。即使是大牛来,也不一定能搞定。能够完整得实现已经是最好的结果了。优美什么的只能靠边站。

软件设计领域内, 抽象无处不在
-----------------------------
关于抽象,记得以前看《C++沉思录》,就理解了一句话。面向对象,面向过程,都是抽象的手段。使用这些手段得出合理的抽象才是最根本的。即使是一句赋值,都包含了抽象。

数据的表现形式是编程的根本.
-------------------------------------
看来大牛们脑袋里的东西都是殊途同归阿,SICP里,原话记不清了。程序包括两个部分,数据和操作数据。
2007-09-17 08:53 | Cure      

#7楼   回复  引用  查看    

应该不是数据驱动应该叫做数据库驱动了,因为对象的属性的值仍然是属性。而且在持久化的过程中到底是用ORM大包大揽,还是由一个DBA来精雕细琢,那也是一个问题。我在讨论自顶向下的过程当中并没有否认数据以及数据库的设计在一个软件设计当中的重要地位,而只是强调先后关系而已。其实就理想情况来说在项目中存在一个巨牛的DBA对于整个项目的推动作用是很显著的,而且和至顶向下的设计方式没有任何冲突。我在我的文章里也说明了,遗留系统,在老系统基础上做新版又想利用原有数据库的都不适合采用此方法,因为数据库结构已经是事实的存在了。至于到时候又用什么方式来设计,我没说,也没有既定的答案,在已有的系统上开发远远比重头自己做要复杂得多,所要兼顾和做的妥协得东西太多。

面向对象是一种让开发变得简单的方法学,他有自己的适用范围,而且最重要的是,面向对象是为了让开发变得更加简单。

======================================
面向对象仅仅是帮我们前进的一个手段, 他通过增加一些从根本上讲毫无意义的细节和表达形式等冗余, 使得我们能更好的组织我们的过程与数据.
======================================
这一段正好确认了面向对象在某些时候的优越性,在过程的组织过程极其复杂以致于我们平凡的大脑无法承担的时候,面向对象可以将这些繁复的过程用我们能够理解的方式记录并且固化下来,以致于我们可以站在一个抽象的高度来解决这些问题。就像 1+2+3+4.......这样子的加法过程我们是一个个的加起来还是用公式去解决,而面向对象就是这样子的公式。


至于你所说的,数学抽象的问题,确实数学是人类有史以来创造的最伟大的抽象艺术,一个E=MC2所抽象出来的东西可能很多人一辈子都理解不完。

计算机本身就是数学抽象的一个子集,计算机本身就是离散的。而面向对象的方法论只是试图将常人难以理解的离散数学变成如同我这般的常人也能够窥到门径的方法学。而在这样的方法学中都要感叹困难,难以理解的人,未免太不知足了。回头去用C,用汇编来实现他们的目标未免又变得更加不显示。动态语言的出现无非就是让事情变得更加的简单而已。



最后要重点说一说:数据的表现形式是程序的根本。

这句话是经典,大家都是赞同的,我也是坚决的赞同,但是我这里要强调的是,什么是数据?什么是数据的表现形式。类的属性值是数据,数据库里的行是数据,甚至我们手抄的表格也是数据,在网络上传输的文本是数据。类的属性值,数据库里的行,网上传输的XML文本都是数据的表现形式,而我们的程序的作用,无非就是将数据的表现形式从一种转换到另一种,或者将不方便检索的数据转换成容易检索的数据,仅此而已。至于,面向对象,还是过程,无非是这个转换的过程用什么方法,优美不优美而已。
2007-09-17 09:30 | 亚历山大同志      

#8楼   回复  引用    

能带来思考的文章就是好文章~继续关注
2007-09-17 10:45 | txdlf[未注册用户]

#9楼   回复  引用    

在做项目的时候,其实继承、多态用的不是很多,好多都是基于对象的,就是一个对操作和数据的封装。这正好也用了面向对象一个优点,就是很好组织我们的程序代码和逻辑,很多情况下已经能解决80%以上问题了。这个好像有点象基于过程的面向对象开发~~
2007-09-17 10:59 | txdlf[未注册用户]

#10楼   回复  引用    

非常有深度的一篇东西,值得慢慢品味。
2007-09-17 11:09 | kingren[未注册用户]

#11楼   回复  引用  查看    

@kingren
同感!(已收录到PinPKM中)
抽象粒度、抽象如何上升到框架等等
学习抽象,一定要学设计模式和UML,UML又是基础

#12楼   回复  引用  查看    

面向过程和数据表现形式的设计, 是比面向对象更高层次的抽象, 而且优秀的面向过程和数据设计, 是对解决问题更有效的抽象, 因为它们抛弃了一切可以抛弃的无用负担.

原文引用:数据的表现形式是编程的根本.


这两句很是赞同。我好像就是这么做的吧。
2007-09-17 12:24 | 金色海洋(jyk)      

#13楼   回复  引用  查看    

目前我还不确定,到底是面向过程的抽象 和 面向对象的抽象 哪个更加高级,

但是我现在能感觉到, 面向对象 如果能抽象的很好, 它的可扩展性一定不错.
我现在看软件的好坏, 很大一个标准就是可扩展性,健壮性.

起码我现在还是人为, 数据库驱动方式 开发出来的程序,可扩展性不是很好,
而 如果真的能做到面向对象开发, 我一定会继续面向对象开发的路走下去,
我还是比较相信Martin.

不过楼主的文章的确值得一看,观点很新颖.
2007-09-17 13:51 | lyb      

#14楼   回复  引用  查看    

1,没有银弹.
2,客户需求是一切设计的根本.
3,使用你的程序的人就是你的客户.别拿同事不当客户,也别拿自己不当客户.
4,判断设计优劣的唯一标准是客户用起来爽不爽.
5,抽象得好与不好全看你的需求会怎么变化.
6,看不惯Book.Save()只说明你没有理解软件是什么.
2007-09-17 17:54 | deerchao      

#15楼   回复  引用  查看    

形而上学很容易让人迷惑,简单来讲,数据是数据,软件是软件,客户需要看到的是软件加工数据后的信息,至于面向对象,面向过程只不过是实现客户需求的手段罢了。

RDBMS的目的就是减少冗余,高效存储,集中管理,所以有那么多的NF,软件设计更考虑重用,可扩展性,所以有那么多的花花绿绿。 博主提到的的那些大牛肯定也想到了谁也离不开谁,只是各自在鼓吹他们拿手的那一套,不过我也看到Gosling和Anders在不同的场合都讲过,ORM:O不是关键,R不是关键,而是M。

我的项目经验是:CRUD面向对象,采用ORM,Reporting面向过程,Business Logic全部都在SP中,Data Mining是另外的话题,当然这是Based on下面的业务状况: 每周产品产量20000pcs,每个产品的物料在200+,还有想想这么多的电子元件组装成半成品,成品,要经过许许多多的测试,每个测试条目都要跟踪到,所以每月的数据量在几个主要的表上16000000++以上。

同时也观察到一个有趣的现象,经常用CRUD工具的都是普通员工,在电子邮件里观看系统定时发来的报表的人每月拿的Money比用CRUD的丰厚得多,做Sql优化的人比Coding的兄弟牛B多了。
2007-09-17 20:53 | 魔佛之间      

#16楼   回复  引用  查看    

@lyb
有空的话请思考这几个问题:
1、调用类的情况。
比如上面写的 Book.Save() 。 Book 是一个实例,.Save() 是一个方法。
那么 Book.Save() 是什么呢? 是一条语句,或者说和外形和面向过程里的语句是很像的。

比如
Book.Name = "";
Book.作者 = "";
...
Book.Save() ;

这一行一行的语句,是不是面向过程呢?调用对象,给对象赋值。


2、类的内部代码是如何实现的?
类的实现代码是什么样的呢?全都是面向对象的吗?一点面向过程的都没有吗?不是吧。呵呵。

3、用砖块盖房子的话需要用水泥,那么用类呢?

2007-09-17 21:08 | 金色海洋(jyk)      

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

@亚历山大同志
大多数人对面向对象的疑惑, 不是他们不知足而是真糊涂, 其原因说成大白话主要在于"可替换"..., 无论是组合式的还是多态, 一看就蒙了, 到底自己找的功能在哪儿实现的啊? 其实因为现代复杂一些的程序都面向对象了, 简单一些的因为容易理清楚, 面向过程了. 于是大家觉得面向过程简单. 其实如果面向过程也做相同的实现, 只能让他们更晕.

@魔佛之间
你说的没错, 所以我的观点一直是.NET社区不用去关心别的社区流行什么. 只要来龙去脉搞清楚了, 没有什么能影响你. 因为真正决定一个软件怎么写的, 不是潮流, 是来自项目或软件自身的概念.

@金色海洋(jyk)
你说的这个确是是很多朋友存在的, 知其然不知其所以然, 其实这是个障碍. 很多人觉得搞清楚面向对象的真面目很难, 其实有很多从其它角度去理解的方法.

比如: 如果经常用Delegate缓存方法, 或者经常使用Emit, 就会知道, 实际上Book.Save()就相当于Save(Book). 由此联想出去, 把所有存在的对象上所有的方法, 都用Delegate缓存了呢? 或者用emit生成一个包含所有对象所有方法的类? 在使用上感觉恐怕就完全不同了.

我这个系列主要想达到的目的, 就是把一些不是那么正规的但是有助于理解编程的思路告诉需要的人, 所以我说是"野路子" :)
2007-09-18 00:05 | 怪怪      

#18楼   回复  引用  查看    

@金色海洋(jyk)
你说的我懂, 如果一条语句一条语句的看,那就不要看面向对象了.

但我想说的是,面向对象重在解决从需求中抽象出来的类之间的关系,
让这些抽象出来的类能很好的协同工作.当需求变化的时候,能很好的应对变化.
可以说,面向对象是为应对需求变化而生的.

事实上, Book.Save()是在实现阶段才要做的事情,就是写代码的事情,
和当需求变动的时候, Book.Save能不能很好的应对变化呢?这些东西有没有想过?SP还不让你头疼吗!

数据持久化,已经有很好的工具帮我们做了,但是,业务的抽象你怎么做?
咱们不要谈什么CRUD,面向对象在CRUD上起不到太大的作用,
关键是寻求这些需要CRDU的类之间怎么样协作, 变化来的时候,如何用最简单的方法应对这些变化.

抽象就是为了解决变化而要做的, 不然你抽象它干什么?脑细胞死的还不够嘛!

假如你能和你的客户签定合同, 如果需求变化我们不改.
OK, 你就永远不需要面向对象了.

其实我觉得文中说的抽象根本不是面向对象的抽象, 说面向对象的抽象不能不谈到变化.
2007-09-18 09:26 | lyb      

#19楼   回复  引用    

不错,能让人引起思考
2007-09-18 11:39 | fc[未注册用户]

#20楼   回复  引用  查看    

>>抽象就是为了解决变化而要做的

一直都没有明白。

怎么抽象了就可以解决变化了呢?

单表的CRUD 对于我来说根本就不用写代码,配置一下就可以了。这个基础是面向过程的,而非对象。

我觉得抽象是:减少代码、减少冗余代码,没了。

面向过程也是可以抽象的呀(假设我上面的理解是正确的)。
2007-09-18 12:31 | 金色海洋(jyk)      

#21楼   回复  引用  查看    

@金色海洋(jyk)
【摘录一段我自己的话,可能你没看见这段
======================================
面向对象仅仅是帮我们前进的一个手段, 他通过增加一些从根本上讲毫无意义的细节和表达形式等冗余, 使得我们能更好的组织我们的过程与数据.
======================================
这一段正好确认了面向对象在某些时候的优越性,在过程的组织过程极其复杂以致于我们平凡的大脑无法承担的时候,面向对象可以将这些繁复的过程用我们能够理解的方式记录并且固化下来,以致于我们可以站在一个抽象的高度来解决这些问题。就像 1+2+3+4.......这样子的加法过程我们是一个个的加起来还是用公式去解决,而面向对象就是这样子的公式。】

如果真的是要抽象过程,那么估计只有函数式编程才能解决,不过C#不支持,Python可以
2007-09-18 13:56 | 亚历山大同志      

#22楼   回复  引用  查看    

@金色海洋(jyk)
>>抽象就是为了解决变化而要做的
这话是没错,但是没有说清楚前提和后果.减少冗余代码只是一个副作用,并不是抽象的主要目的.

为了解决需求变化时要改动很多地方的问题,可以把这些将来会改动的地方加一个抽象层,包装一下,这样以后要改时就只需要改这个抽象层的内部实现,而其它部分就不用变动了.
可是问题来了,"这些将来会改动的地方"是很难预知的,如果你把一个地方抽象了,而后来的变动的却是另一个地方,那这个抽象就是不成功的,因为它并没有达到"减少因变化而需要改动的地方"的目的. 更有可能,本来直接写时很容易改的,结果经过不合适的抽象,反而不好改了(比如分了五六层的一个系统,UI上需要加个字段,结果整个体系瞬间雪崩的这种情况).
2007-09-18 18:44 | deerchao      

#23楼   回复  引用  查看    

还是不懂哈哈。
举个具体的例子来说明吧,呵呵。一会我想写个帖子来说一下我的想法和思路。
写好了,在这里。我的想法和实现代码。
http://www.cnblogs.com/jyk/archive/2007/09/18/897699.html
2007-09-18 19:41 | 金色海洋(jyk)      

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

@lyb
呵呵, 你这个回答就正是我文章中说到的问题之一: 让面向对象的抽象掩盖了抽象的本质.

首先, 面向对象只是抽象的一种形式和方法(还不是最彻底的).

其次, 当需求变动的时候, 到底是Book.Save()还是Save(Book), 其本质完全没有差别, 任何一种抽象都有应对变化的能力, 包括最传统的C编程. 比如deerchao举的例子, 抽象层, 面向对象的抽象层, 照样可以用面向过程来实现, 至于怎么实现, 比如比如微软的Provider模式, 难道不能完全展开成面向过程的形式吗?

考虑我说的, 写一个遍历全部对象的算法, 将一个良好的面向对象架构的全部对象还原成数组或字典, 把全部对象的所有方法都用Emit生成为一些静态类的静态方法调用的形式, 同时将继承的关系用链表/数组或字典实现, 并写一个判断去决定什么时候应该调用哪些变量(值类型或我们自己定义的结构)和静态方法, 使得程序看起来完全不面向对象, 难道就不转了吗? 不能通过配置去改变行为了吗?

实际上面向对象的内部实现方式, 正是类似于我所说的这种形式, 但是我所描述的是一个反向的过程. 我觉得有时候要思考一个问题, 如果让我实现一门面向对象的语言, 我怎么实现它? 往往我们会发现并不比Gosling笨太多(但类似于Anders说的这个地方为什么这么设定, 就是经验决定的了), 想出来的方式不会离真实情况差太远, 当我们站在制造者而不是使用者的角度, 一切自然就水落石出了.

但是, 如亚历山大同志所说, 面向对象的优越性在于, 它能够帮我们理清思路(而不是能完成其它方式不能完成的工作, 由于面向对象建筑在更原始的方式的基础上, 如果原始的方式真的不能完成某事, 那么面向对象也不会具有这个能力), 而包括封装变化都是面向过程照样可以完成的, 其区别只是实现的成本而已.

最后, 如果仅把抽象理解为"解决变化"用的抽象, 那么这是一个谬误, 解决变化与任何一种其它需求没有区别, 就像全部其它一样仅是一个问题, 同时可以用抽象(而且还不见得是面向对象式的)的手段来搞定. 我这篇文章所直指的一个问题, 就是澄清只有面向对象才是抽象(或合理抽象, 正确抽象)的这一不正确引导, 理清抽象和面向对象的关系: 抽象无处不在, 各种抽象的方法都可以找到包括变化在内的问题的思路, 面向对象不过是通过一些人为增加的冗余(甚至是某种程度的具体化, 注意: 正好和抽象的做法相反), 来帮助我们更容易的抽象罢了..
2007-09-18 19:47 | 怪怪      

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

希望大家不要顾虑太多, 畅所欲言. 如果某些误解是广泛存在的, 无论谁对谁错, 咱们不如把它讨论清楚, 如果内容足够多, 事后我会把各种问题单独整理出来另成一文, 为更多的编程爱好者(其实我发现很多职业程序员反而算不上 -__-)铺平道路.
2007-09-18 20:03 | 怪怪      

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

@金色海洋(jyk)
关于你那篇文章我的理解.

你这个抽象的在我看来不是表单, 而是表单->数据存储这一过程, 所以是面向过程. 如果你抽象了表单(很可能接着又抽象了数据存储, 接着又.., 逐渐就变成了PetShop或者.Text Blog了...), 如果你对表单或其它某物抽象的结果中, 这个"某物"成了主语, 比如: 表单1.获取数据(), 表单1.状态一, 数据管理器.给我某表单的数据(), 就会逐渐开始有面向对象的意味了.

关于你说出现了硬编码. 这个我可以提供一个思路, 特别适合做你这个示例的过程. 用一个非编程语言的描述层, 比如xml的, 去抽象这个过程. 这个描述层的作用主要就是告诉其它东西(如C#写的程序或任何东西), 表单是如何变成数据, 数据又如何编程表单的. 但这样的方法和面向对象的不同, 在于把复杂度转移到了外部形式, 甚至可以是另一种业务语言. 这也是一个非面向对象的抽象的很好的例子.

描述时, 可以从表单->数据, 但是因为这种项目, 第一步是把现实事物, 比如"新闻", 抽象成表数据, 即产生你文章开头的表结构, 所以一般来说是从数据->表单(其实可以完全基于描述, 由描述生成表单和数据, 这样描述就不依赖于数据了, 而描述说的就是你要实现的业务如何在基础框架上进行组装), 比如这样: 一个数据表一个描述文件, 描述字段对应的表头(在你这个例子用于生成Label), 字段的输入形式和限制(用于生成验证控件), 数据可以进行的操作(如果足够简单, 可以直接写上SQL即作为操作的的标识又作为操作的具体内容都无所谓), 操作的表现形式(用于生成Button等), 如果更简单可以让数据可以进行的操作和操作在表单上的表现形式的描述合一, 分成两个, 其实可以体会成多了一个层次作为接口. 如果是反向的生成或者双向生成, 还要加上如何生成数据的那些.

然后你文章的页面没有必要写具体控件, 放一个PlaceHolder在哪儿, 写一段读描述文件逻辑/基本永远都不用改的代码动态生成即可. 我说的这个结构, 经过升级后曾经对付过一个将近一百个表的政府项目, 应该有一定实用性, 如果将描述层用图形界面单独维护, 变化也比纯OO式的做法更容易面对变化, 且工作量可以被降低到一定程度: 因为描述层的语义和语法是根据问题域严格控制的, 而编程语言则是通用的. 而且外部描述层的做法, 在很多系统中都是广泛存在的合理做法.

但是需要注意的是, 如果对这个数据<->表单过程的抽象, 最后又产生了很多类, 比如每种若干的描述层解释器, 表现层工厂, 数据管理对象, 等等, 那么这就是面向对象编程, 只不过你针对的问题域是"数据<->表单过程"罢了. 很多人对这个理解有偏差, 认为如果面向对象的内容管理系统, 就一定要有News类, Post类对现实世界的反映, 其它项目就应该有汽车类等等以此类推, 其实满不是那么回事. 这个是我在上面文章里想强调但是给忘了的. 但是即使是这样, 我回帖开头说的面向过程的总体思想却没有变: 分析与总体设计是面向过程的, 具体设计与实现是面向对象的.

另外多个嘴, 你的文章写法稍微有点问题, 没有交代清楚来龙去脉. 我从这篇文章过去, 知道你想表达的是什么, 否则突然在首页看到我也觉得突然写的很奇怪, 这也是为什么我没有在你那边回帖的原因, 你那边回帖的话就没有上下文了(尤其是让某些张嘴太随便的人一搞)....
2007-09-19 00:09 | 怪怪      

#27楼   回复  引用  查看    

老怪 ,你的文章不错啊 o(∩_∩)o...哈哈。 希望多看到你的作品
老子说: 玄之又玄 众妙之门
其实讨论了半天 ,谁都知道,不管是唯物主义 还是唯心主义 只要是“主义” 就已经离真实远了一步。
面向过程还是面向对象 ,领域驱动还是数据驱动 ,哪个唯心哪个唯物啊?不过都是隔纱观影的种种猜测,真实已经从指尖流走啦
《楞严经》讲:心能转物,即同如来
哎,都不知道俺在说啥。。。
2007-09-19 08:36 | 戏水      

#28楼   回复  引用  查看    

我不是针对新闻去抽象的,而是直接针对新闻所在的表。
就是针对表去抽象的。

2007-09-19 08:38 | 金色海洋(jyk)      

#29楼   回复  引用  查看    

再也不想看到这篇文章了,
2007-09-19 09:32 | lyb      

#30楼   回复  引用    

这篇文章还可以
2007-09-19 10:36 | programdev[未注册用户]

#31楼   回复  引用  查看    

都是高人`
2007-09-19 13:30 | 木野狐(Neil Chen)      

#32楼   回复  引用  查看    

不写程序最好。离事实最近~
2007-09-19 13:31 | 木野狐(Neil Chen)      

#33楼   回复  引用  查看    

1.这里非常重要的一句话是下面那句:(也是非常容易搞不清楚的。)
软件设计, 归根结底不应该是对现实世界抽象, 而是对"就某个问题, 使用计算机去更好的解决"这一过程的抽象,
这句话说的在理~因为编码本身确实是以人之长处发挥计算机之长处,某种程度上是人“迎合”计算机的个性癖好。

2.另一句很知名(但原话没出现在这篇文章里面),程序=算法+数据结构。

2007-09-19 15:04 | hoodlum1980      

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

@金色海洋(jyk)
这个我理解你, 没有说你抽象的是新闻, 只是说表结构本身是对新闻的抽象. 可是你代码这一部分, 抽象的不是表本身可以具有的特征和行为, 而是针对表的行为啊, 找准抽象的目标, 就可以更清晰一些了 :)

@lyb
^^, 放心, 等棒子轮完就是胡罗卜了, 如果直接从OO如何好开始, 那么对一些还不了解来龙去脉的兄弟, 不是等于鼓励那种不必要的狂热么?

@木野狐(Neil Chen)
应该说离直观的事实最近^^, 就像沈阳那个"怪坡", 不用科学的手段搞清楚, 那么对于大多数人就是车会自动往坡上溜~~
2007-09-19 20:04 | 怪怪      

#35楼   回复  引用  查看    

其实这几天讨论来讨论去,还是这篇文章写得最透彻.倒是像我这种无知浅薄的人反而是最喧嚣的.
2007-09-20 16:21 | deerchao      

#36楼   回复  引用  查看    

找到一篇关于过程建模的文章:
http://blog.csdn.net/james999/archive/2007/09/17/1788724.aspx" target="_new">http://blog.csdn.net/james999/archive/2007/09/17/1788724.aspx
这才是对过程的抽象
2007-09-21 09:06 | 亚历山大同志      

#37楼   回复  引用  查看    

谈点个人的感觉。我有好几次在最初考虑解决某个问题时都会写7、8个类以及各种接口,觉得这样就OO了,就灵活了。用了一段时间后,我又会把这些类都删掉,变成一个很简单的类,因为发现我所设想的那些变化根本不太可能出现,即使出现了变化我这些号称很灵活的设计也未必就能轻松对应。所以正应了那句经典的“没有最好的设计,只有最适合的设计”。所谓如鱼饮水,冷暖自知。
2007-09-21 11:46 | 1-2-3      

#38楼   回复  引用    

易虎互联 oop(www.easyhoo.cn)是在现有网络文化内涵的基础上,以全新的网络理念、先进的网络技术和企业管理模式建构的。本公司以多种网络经营为载体,致力于为广大用户提供:各行业各领域、“先进的 、易懂的 、实用的、 普及的”网络商务平台,是一家拥有多元化营销网络及专业服务网络的高科技公司。 2007年易虎互联深入分析互联网行业,对大量企业网站调研,针对当前企业网站的弊端,提出“营销型”网站概念,掀起广州新一轮的企业建网风暴,开创广州企业网站建设蓝海。我们的口号:“绝不做没有销售力的网站!”

2007-09-21 15:27 | weiyashi[未注册用户]

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

@deerchao
呵呵,我感觉无知不无知不用随便说。这两天我这两篇(还有一篇暂时没推到首页)讨论Bjarne Stroustrup那几句话的破文章,还不是喧嚣的要命,说实话感觉一进入一种气氛,就有点不是自己了。

你能不能把Bjarne Stroustrup原文发出来我看看?我自己有一种更好的理解,在那篇没发到首页的文章里。你确定的Bjarne Stroustrup是把面向对象和基于对象对立的?如果上下文真如你所说,那没啥问题;否则我可能被你给拖下水了... ^^

@亚历山大同志
那篇文章涉及的领域虽然我没有发言权,但是我觉得只是对他领域内过程的一种抽象方法;而金色海洋描述的从数据表->表单的过程虽然简单,但毕竟关注的也是一个过程,而不是具体的某一事物。我是从这一角度出发,说他不是对他那个过程的抽象,那他是对什么抽象?不过可能我看得不够仔细~
2007-09-22 04:24 | 怪怪      

#40楼   回复  引用  查看    

@怪怪
非常高兴,您能在 Cnblogs 上注册 :)
能留一个 MSN 么?小弟想请教一下。
2007-09-22 10:30 | 随风流月      

#41楼   回复  引用    

Preface to the first edition

C++ is a general purpose programming language designed to make programming more enjoyable for the serious programmer. Except for minor details, C++ is a superset of the C programming language.
In addition to the facilities provided by C, C++ provides flexible and efficient facilities for defining new types. A programmer can partition an application into manageable pieces by defining
new types that closely match the concepts of the application. This technique for program construction is often called data abstraction. Objects of some userdefined types contain type information.
Such objects can be used conveniently and safely in contexts in which their type cannot be determined at compile time. Programs using objects of such types are often called object based. When
used well, these techniques result in shorter, easier to understand, and easier to maintain programs.

The key concept in C++ is class. A class is a userdefined
type. Classes provide data hiding, guaranteed initialization of data, implicit type conversion for userdefined types, dynamic typing,
usercontrolled memory management, and mechanisms for overloading operators. C++ provides much better facilities for type checking and for expressing modularity than C does. It also contains
improvements that are not directly related to classes, including symbolic constants, inline substitution of functions, default function arguments, overloaded function names, free store management
operators, and a reference type. C++ retains C’s ability to deal efficiently with the fundamental objects of the hardware (bits, bytes, words, addresses, etc.). This allows the userdefined
types to be implemented with a pleasing degree of efficiency.

...........
2007-09-23 22:39 | fc[未注册用户]

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

@fc
Thanks楼上...

确定Bjarne Stroustrup是我第二篇反弹中那个意思, 不是第一篇先搞出一个大前提那样的意思...., 我居然在不了解上下文的时候就断章取义了...

现在只能想想如何跟被我误导的人道歉了...
2007-09-25 02:04 | 怪怪      

#43楼   回复  引用  查看    

@怪怪
不好意思,看见你前面的回复时已经太晚了,已经把你拖下水了。

仔细想想,我觉得作者这里的“Object Based"的意思和我原来的“Object Oriented”的意思差不多。这里的"type infomation"指的估计就是vptr。

但是,在Essential C++里,Stanley B. Lippman把书分成几部分,其中包含了“Procedural Programming", "Generic Programming", "Object-Based Programming"(下面的内容主要是与具体类有关的,如几个构造器,函数对象也即重载了小括号运算符的对象,静态成员等),“Object-Oriented Programming”(主要是继承,虚基类,多态,RTTI等)等等--早要记得这本书里有这么明显的证据就好了。

我的看法还是这样:如果严格来说的话,OB包含的范围大一些,里面包含了OO,OB是OO的基础,OO还是与多态的使用有相当密切的关系。
但是有时大师们用词也未必就非常严谨,OB有时也被用作OB减去OO的那一部分,像Lippman书里的那样;有时用于统称使用了封装的用法,包含了OO;至于像这样用OB指代使用多态的例子,非常少,可能是这里只是在强调与C的差异,不想太早拿出新名词来吓人?
2007-09-25 03:21 | deerchao      

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

BJ在这个上下文中,就如你所说是在强调与C的差距,有点用OB指代使用多态的意思,但更多的实质上是在说这种方法如何给程序员带来好处, 而不是重点强调多态的重要性和优点,所以就没有拿出OO这个词。

这个我个人觉得是当时国外对这些词在最初也没有统一的认识,而且说实话,我自己直接读英文时从来不敢按字面意思翻译,英文里很多词/词组实际上脱离了上下文就没有中文那么明确了,如果再和中文直译的各种名词一混淆就对理解造成更大的麻烦..

不还有人把这句话理解成在说Javascript这类语言不好么?其实对于咱们这几个人在这里咬文嚼字,因为心里已经有了自己的想法倒也无所谓,比如我那两篇解释,有点水平的都能看出两篇文章分别的意思和不同的角度。我难受就难受在对理解不深的入门者,万一看了那些文章带来的负面效果。以后我会更加谨慎一些,我总觉得发文和自己瞎琢磨不同,要考虑到对别人的影响。

这帖子现在只有你我进来,不妨直说,我那第一篇文章对“cannot be determined at compile time”进行了设定,而原文是没有这种设定的,文章放在那里那么久了,也没有人出来指出我这种设定不合理;还有包括大家跟你的争论,很显然大家都没有仔细看过这段,都是自己在任意解释。

无论是我自己的做法还是他们的做法,说实在的都有欠考虑,光顾自己说的爽了;这是我觉得大家都需要注意的。

说到这儿,对于路过这的,如果不知道前因后果的,就不要在看那两个帖子了,等到有空我把其中还有价值的内容提取出来。如果已经看过第一篇的,无论你是认同还是迷惑,不妨把我第二篇也看一遍,那两个帖子只能变成一对儿,一起看才能知道来龙去脉。

第一篇:http://www.cnblogs.com/guaiguai/archive/2007/09/21/901370.html" target="_new">煽风点火:也论Bjarne Stroustrup的"基于对象"的含义, 同时B4一下大师

第二篇:http://www.cnblogs.com/guaiguai/archive/2007/09/21/901898.html" target="_new">反弹和补遗:再论Bjarne Stroustrup的"基于对象"的含义
2007-09-25 19:17 | 怪怪      

#45楼   回复  引用    

其实看的懂的自然知道你在表达什么,看不懂的自然会略过(或者骂过:P),不必担心误导的问题啦
2007-09-26 09:55 | fc[未注册用户]

#46楼   回复  引用  查看    

完整看了全文和评论,钦佩作者这么勤奋,这么长的技术随笔第一次看到。可能是水平不够,看起来觉着有点玄玄的感觉。不过关于抽象有点想法也说一下。

首先严重赞同题目:《抽象无所不在》

个人理解:撇开科学计算和系统应用不谈,现在做软件的大多都可以归入数据处理这个大领域吧。所以讨论问题先明确问题域更好,虽然事物总是相通但是把软件设计上升到哲学高度纯属恶搞,呵呵。

数据,无论是数据库还是文件还是其他都是对事物静态的抽象。

软件,无论面向过程、对象、方面还是服务都是对数据加工过程的抽象。用什么方法论来指导软件的设计应当慎重考虑软件的特点和生命周期,没有银弹。

抽象,我的理解抽象至少包含对事物的静态抽象,和对事物关系的抽象。静态的抽象可能形成表格、文件、或者类。关系的抽象可能形成ER、模式、架构。对于数据处理为主的系统后边的抽象可能更难,那不是方法论难,是理解业务难。

像上边那个朋友说的,“说到抽象不得不说变化”。抽象在现在被提高空前的高度,是因为广大的数据处理应用面临需求不稳定的状况,写Compiler、OS用OO那是显摆+浪费时间。OOD以及GoF的模式的目标也就是最大程度封装变化,说白了OO的核心可以简化为OCP。

期望看到大牛更多文章。
2007-09-26 10:21 | flyingfish      

#47楼   回复  引用    

写这篇文章花了不少时间吧.:-)
没怎么细看,建议最好再排版好一些.还有把这篇文章分一些子目录.脉络会更清楚一些.
Brooks的这句话"数据的表现形式是编程的根本. "的引用在你的上下文中我个人觉得不太合适.
Brooks这里这里的"数据表现形式"其意思是指data structure的选择.
并且注意其"编程"两个字,编程更侧重的是一种implementation阶段.在他那个时间,程序员在编程的时候更多的是从computer的角度来思考问题.同时Brooks话中所暗示的意思:数据表现形式对算法的选择与程序的结构具有至关重要的影响,
说实话,我不太明白,你引用这句话支持你文章的什么样的观点.

2007-09-28 14:29 | Jeffrey Hua[未注册用户]

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

@Jeffrey Hua
你说的有道理, 我这篇文章还是有点草, 不清晰.

Brooks这句话, 我是借用来扩充到更广阔的领域. 主要是用来说明, 在对现实世界进行抽象之后, 我们也要关注来自计算机世界的实现问题, 以实现良好的对接, 而不是把这些工作扔给ORM之类的搞定.

因为数据的表现形式本身, 由于它往往客观存在的, 超越于软件的意义, 我们往往没办法去更改它的形式, 比如当我们面临一个数据库设计人员精心设计的结果时, 首先不能考虑他们的设计不合理(因为他们的考虑可能更多不是如何配合我们实现, 而是有其它重点), 而是我们应该更加注意这种情况, 避免很多人说的, 软件设计和数据设计冲突的问题.
2007-09-29 11:54 | 怪怪      

#49楼   回复  引用  查看    

引起思考的文章。。。。
看了半个小时
到底是面向过程的抽象更高级还是面向对象的抽象更高级,这是个问题
而这个问题的本质不是哪个方法更为高级,而是我们做软件的目的是什么?
我认为这是个我们应该思考的问题
2007-10-12 15:58 | Sean Zhang      

#50楼   回复  引用  查看    

拜读恨晚!
2008-05-09 18:39 | alisx      

#51楼   回复  引用  查看    

以前没有看过怪怪的长篇大论。现在总算领教了。真是务虚的很。呵呵! 要我说就两句话:抽象是找出事物的共性, 同时也反衬出特性。 一种方法论而已。还是务实的好,建议怪怪多写点技巧性的文章或者入门基础知识的文章。
2008-07-13 22:31 | mikelij      

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

@mikelij
呃...,其实我这篇文章正是破除方法论迷信用的呀..., 看来是太罗嗦了..

技巧性的文章和入门基础知识, 不是我不愿意写, 是我太菜, 写不出来呀...

我虽然和你大体意见相仿, 不过呢, 务虚也不是全然无用, 至少现阶段人类的任何成果, 中间都离不开务虚这一步。

另外, 除非按照某些人在某领域内重新将他们定义之后的理解,否则抽象和方法论根本是两个概念,更不能说抽象是一种方法论了。

比如我这篇文章, 实际上是在说,不是某一种方法论的执行结果才是抽象; 当你随便打下一行代码,就是在抽象了了; 区别仅仅是有意识的还是无意识的, 好、还是不好罢了。
2008-07-13 23:33 | 怪怪      

#53楼   回复  引用    

几年前有一个感悟:不同于“尽信书则不如无书”,而是大牛们太多了,大牛们的书也太多了,崇拜者太多了,fans太多了,最后导致大家讨论无论什么事情用到的“话语”的“语料”都来自于这些哪些的大牛,这样那样的书...

后来想想,过多的在这些漩涡中打转转意义有几何?还是真刀真枪的在实践中思考,带着思考又去实践吧
解决问题,并且有效解决问题,然后更有效地解决问题——甚至上升到解决问题的方法的方法...的方法
那么,这早已超出了技术范畴,超出了 it

于是,兴趣和乐趣已不在软件本身,也就没有时间继续在漩涡中转圈圈。

当然,某些人除外——那些人往往很清楚自己在干什么:成为技术圈子中文笔最好的,同时成为写作圈子中技术最好的,以获得自己的利益。

你想成为一个技术写手么?不是?那就要警惕了——在这个领域老外的大牛们掌握着话语霸权。要想超越他们,要不就沿用他们的话语体系并战胜他们,要不就另辟蹊径:想想老外的大牛们当年怎么出来的?
还是思考+实践,实践然后又思考。哪有那么多大牛和大牛的书以及大牛的fans来干扰他们,耽误他们思考和实践的时间呢?

最后:
>所以正应了那句经典的“没有最好的设计,只有最适合的设计”。所谓如鱼饮水,冷暖自知。
这样的设计,只有自己知道好不好,那就留着给后来维护你留下的系统的人破口大骂吧。
不妨这么理解——好的设计,能够让今后维护系统、基于系统进行扩展和规模调整的后来者,在选择维护或者扩展、伸缩方案时,“情不自禁”自然而然地选择了符合你当初设计的时候的意图的方案。
换句话说,设计首先要达到这样的目的:哪怕不依赖文档,也不依赖后来者的“人品”,也能让系统维持很高的自洽性。
先不要去论“好”“坏”,首先确保设计是“完整”的设计,是成体系的自组织的设计。偏离设计意图的后续方案,势必受到设计的“惩罚”。

然后,从解决问题的有效性的角度来评价设计的“好”与“坏”。但一定要注意,你所关注的“问题”是否是人家的设计原始意图所要解决的“问题”。
否则就像蜡笔小新同学跑去瓜果店责怪店老板不卖鱼一样可爱。

#54楼   回复  引用    

修正一下:

>在这个领域老外的大牛们掌握着话语霸权

委屈了大牛们,严格意义上来说更多的是 fans 维护着大牛们的话语霸权。
或者说那些“准”fans —— 他们迷恋的不是某个大牛,而是迷恋那些专业词汇、语料。
就像迷恋胡椒、香料的厨师或者评论家。



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 894819




相关文章:

相关链接: