大话设计模式上的一个图,我用EA画出来的:
依赖关系 |
dependency |
[di'pendənsi] |
关联关系 |
association |
[ə,səuʃi'eiʃən] |
聚合关系 |
aggregation |
[,ægrɪˈgeɪʃən] |
组合关系 |
composition |
[,kɔmpə'ziʃən] |
实现 |
realization |
[,ri:əlɪ'zeɪʃən] |
泛化 |
generalization |
[,dʒenərəlɪ'zeɪʃən] |
注意:泛化关系和实现关系又统称为一般关系;
总之:一般关系表现为继承或实现(is a),关联关系、聚合关系、合成/组合关系表现为成员变量(has a),依赖关系表现为函数中的参数(use a);
转自:http://www.cnblogs.com/ForEverKissing/archive/2007/12/13/993818.html
1、关联关系:
含义:类与类之间的连结,关联关系使一个类知道另外一个类的属性和方法;通常含有“知道”,“了解”的含义
体现:在C#中,关联关系是通过成员变量来实现的;
方向:双向或单向;
图示:实线 + 箭头;箭头指向被关联的类;
举例:“渔民”需要知道“天气”情况才能够出海
//公司关联雇员
public class Company
{
private Employee employee;
public Employee GetEmployee()
{
return employee;
}
public void SetEmployee(Employee employee)
{
this.employee = employee;
}
//公司运作
public void Run()
{
employee.StartWorking();
}
}
//A关联B
class A
{
B b = new B();
}
class B
{
}
2、依赖关系:
含义:是类与类之间的连接,表示一个类依赖于另外一个类的定义;依赖关系仅仅描述了类与类之间的一种使用与被使用的关系;
体现:在C#中体现为局部变量、方法/函数的参数或者是对静态方法的调用;
方向:单向;
图示:虚线 + 箭头;
举例:人依赖于水和空气;汽车依赖汽油
//人划船,人依赖于船
public class Person
{
//划船
public void Oarage(Boat boat)
{
boat.Oarage();
}
}
//A依赖于B
class A
{
public void Function(B b)
{ }
}
class B
{
}
3、聚合关系:
含义:是关联关系的一种,是一种强关联关系;聚合关系是整体和个体/部分之间的关系;关联关系的两个类处于同一个层次上,而聚合关系的两个类处于不同的层次上,一个是整体,一个是个体/部分;在聚合关系中,代表个体/部分的对象有可能会被多个代表整体的对象所共享;
体现:C++中,聚合关系通过将被聚合者的(数组)指针作为内部成员来实现的;
方向:单向;
图示:空心菱形 + 实线 + 箭头;箭头指向被聚合的类,也就是说,箭头指向个体/部分;
举例:鸭群与鸭子具有聚合关系;汽车由引擎、轮胎以及其它零件组成,因为汽车坏掉了,没有坏掉的引擎,轮胎和其他零件还可以继续使用。
4、组合关系:
含义:它也是关联关系的一种,但它是比聚合关系更强的关系.组合关系要求聚合关系中代表整体的对象要负责代表个体/部分的对象的整个生命周期;组合关系不能共享;在组合关系中,如果代表整体的对象被销毁或破坏,那么代表个体/部分的对象也一定会被销毁或破坏,而聚在合关系中,代表个体/部分的对象则有可能被多个代表整体的对象所共享,而不一定会随着某个代表整体的对象被销毁或破坏而被销毁或破坏;
体现:在C#中,组合关系是通过成员变量来实现的;
方向:单向;
图示:实心菱形 + 实线 + 箭头;箭头指向代表个体/部分的对象,也就是被组合的类的对象;
举例:一个人由头、四肢、等各种器官组成,因为人与这些器官具有相同的生命周期,人死了,这些器官也挂了;
5、泛化关系:
含义:它表示一个更泛化的元素和一个更具体的元素之间的关系;也就是通常所说的类的继承关系;
体现:在C#中,泛化关系通过类的继承来实现的;
方向:单向;子类继承父类;
图示:空心箭头 + 实线;箭头指向父类;
举例:动物下面可以分为哺乳动物,脊椎动物,爬行动物等
6、实现关系:
含义:它指定了两个实体之间的一份合同;即:一个实体定义一份合同,另外一个实体则保证履行该合同;
体现:在C#中,实现关系通过类实现接口来实现的,即:一个类实现某个接口;
方向:单向;子类实现接口;
图示:空心箭头 + 虚线;箭头指接口向接口;
举例:唐老鸭(对象)会说话(接口),因为一般鸭子不会说话,所以不会将说话这个方法给一般的鸭子带上;超人(对象)会飞(接口)
转自:http://www.cnblogs.com/aicro/archive/2010/08/23/1806584.html
你是我的玫瑰-类关系阐微
http://www.cnblogs.com/zjzkiss/archive/2007/05/06/736725.html
UML中关联、依赖、聚集等关系的异同
http://www.cnblogs.com/ForEverKissing/archive/2007/12/13/993818.html
UML 类与类之间的关系
http://yanwenhan.javaeye.com/blog/149450
类间的关系
http://www.cnblogs.com/floodpeak/archive/2008/02/27/1083533.html
UML解惑:图说UML中的六大关系
http://developer.51cto.com/art/201004/194204.htm
大话设计模式
前言
记得几个月前,在一次北京博客园俱乐部的活动上,最后一个环节是话题自由讨论。就是提几个话题,然后大家各自加入感兴趣的话题小组,进行自由讨论。当时金 色海洋同学提出了一个话题——“什么是业务逻辑”。当时我和大家讨论ASP.NET MVC的相关话题去了,就没能加入“业务逻辑”组的讨论,比较遗憾。
其实,一段时间内,我脑子里对“业务逻辑”的概念也是非常模糊的。但在不断地阅读、思考和实践过程中,这个概念及其相关的内容才在我脑子里渐渐清晰。我 想,很多朋友也许也对这个概念不是很了解,所以愿意结合既有资料和自己的思考,总结一篇关于业务逻辑的概述性文章,一则与朋友们分享探讨,二则也是为自己 对业务逻辑的学习做一个总结和提升。因为我还不敢说对业务逻辑内涵及外延理解的非常充分,所以文中如有不当之处,还请各位不用客气,尽管批评就好!
内容提要
===================前篇=====================
前言
内容提要
1、我把业务逻辑丢了!——找回丢失的业务逻辑
2、细说业务逻辑
2.1、业务逻辑到底是什么
2.2、业务逻辑的组成结构
2.2.1、领域实体(Domain Entity)
2.2.2、业务规则(Business Rules)
2.2.3、完整性约束(Validation)
2.2.4、业务流程及工作流(Business Processes and Workflows)
2.3、业务逻辑层职责相关争议
2.3.1、争议一:数据的格式化
2.3.2、争议二:数据合法性及完整性验证
2.3.3、争议三:CRUD
2.3.4、争议四:存储过程
===================后篇=====================
3、业务逻辑的架构模式及实现
3.1、Transcaton Script
3.1.1、概述
3.1.2、分析
3.2、Table Module
3.2.1、概述
3.2.2、分析
3.3、Active Record
3.3.1、概述
3.3.2、分析
3.4、Domain Model
3.4.1、概述
3.4.2、分析
3.5、各种架构模式的比较及选择
4、结束语
参考文献
1、我把业务逻辑丢了!——找回丢失的业务逻辑
相信朋友们基本都是软件开发人员。不论身处什么职位,我们的工作都有一个共同的目标——制作软件产品。而所谓的软件产品,一定是在某个领域内去实现某些业务 。如此看来,“业务逻辑”本应和“软件产品”是紧紧绑在一起的,没有业务逻辑,何来软件产品?
但是,我发现一个奇怪的现象,一说业务逻辑,很多人就无法形成清晰地印象。例如,经典的三层架构:表示层、业务逻辑层和数据访问层,一提到表示层或数据访 问层,大家脑子里马上能产生出清晰的概念,但一提到业务逻辑层,就有点模糊了,或者完全不知道其是什么,或者有个模糊的轮廓,但对其具体的职责、结构不是 很清楚。真是奇了怪了!我们天天和业务逻辑打交道,搞不清业务逻辑是什么。
对于这个奇怪的现象,我思前想后,结合自身的教训(我也曾很长时间搞不清业务逻辑),终于弄清楚了其原因——这和我们接触这个概念的途径和认知结构有莫大 关系。
不知道有多少人和我一样,首次接触“业务逻辑”这个概念是从分层架构中的“业务逻辑层”概念开始的,我相信不在少数。事情坏就坏在这里!为了让朋友们直观 看清“业务逻辑”的概念是怎么被我们丢掉的,请大家看一个图,这个图展示了很多人对“业务逻辑”的认知过程。
图 1-1、狭义的认知分解过程
如图1-1所示,我们先接触了分层架构,然后对每个层产生了初步的认识。其中,由于表示层和数据访问层的代码职责清晰明确,基本能正确认识。但是,由于我 们接触的分层架构的Demo大多业务极其简单,又基本是CRUD操作集中型的业务。所以,我们脑子中就产生了疑问:这个所谓的业务逻辑层是干什么的?怎么 就简单封装了一下数据访问层的操作?这有存在的必要吗?由于有了这种“先入为主”的误导,使得很多朋友脑中将“业务逻辑”和“业务逻辑层”两个概念混淆 了,始终想不明白这东西到底是什么,做什么用的。再加上很多朋友所看的、所做的系统都是CRUD操作集中型的,就形成了“业务逻辑貌似就是对数据访问操作 的简单封装”这一片面概念。
到底这一概念有没有错呢?其实没错,因为在简单的、CRUD操作集中型软件中,业务逻辑基本就是对数据访问简单的封装。但是,无错不代表全面,这是一种狭 义的业务逻辑理解,而且是狭义中的狭义。为什么这么说呢?因为我们不但是在“业务逻辑层”这么一个狭义范围内去理解业务逻辑,而且还是CRUD集中型操作 这种“非常瘦”的业务逻辑层范围内去理解,所以,可谓是在狭义的基础上的狭义。
当我们把这么一个“狭义中的狭义业务逻辑”与“业务逻辑”等同起来时,误会、迷茫、困惑、不屑就出现了。这就如同,给你一只温顺的哈巴狗,还是病怏怏的、 无精打采的小哈巴狗,而你把这只“病怏怏的小哈巴狗”与“狗”的概念等同起来了。那么你一定就会为有人养狗看家和警察养狗当警犬抓坏人而困惑:这东西这么 弱小,我一脚就踩死了,怎么弄用来看家和抓坏人呢?进而可能会产生“狗狗无用论”,“狗狗废品”等观念。当然,在现实中,很少有人只见过小哈巴狗而没见过 狼狗等其它狗类,所以,故事中的误会对 “狗”一般是不存在的。但在现实中,确实有很多人只见过业务逻辑中的“小哈巴狗”,却没有见过业务逻辑中的“狼狗”、“藏獒”,所以,这种误会在对“业务 逻辑”的理解上广泛存在。
那么,广义的情况究竟是怎么样的?请看下图。
图 1-2、广义的认知分解过程
(注意!凡是不特别说明,下文中所有“数据”一词都指需要持久化的数据,而不包括内存中的临时数据。请各位留心。)
如图1-2所示,广义的认知分解应该是这样的:软件产品都是在某个领域内实现某些特定业务,所以,软件产品天生应该分解为界面交互部分和业务逻辑部分,其中业务逻辑 部分是软件产品的核心,它客观存在于软件产品内部,但是无法对使用者产生直观刺激,因此业务逻辑不能与使用者直接交互。而界面交互部分是业务逻辑与使用者 进行交流的接口,使用者通过界面交互部分,与业务进行交流,从而使得软件产品发挥其作用。
而在具体实现系统时,界面交互部分演化成表示层,业务逻辑部分演化成业务逻辑层。所以,可以认为,数据访问层不是软件产品自然演化的直接产物,之所以出现 数据访问层,是因为某些产品的业务属于“数据操作集中型”业务,为了实现隔离、复用等目的,架构师从业务逻辑中分离出了频繁使用的数据访问业务,形成了单 独的数据访问层。从广义来说,可以认为数据访问隶属于业务逻辑,因为,数据访问操作实际上也是业务逻辑的一部分。
总结一下几个要点:(这几个要中的业务逻辑均指广义业务逻辑)
1)软件产品自然的可分为界面交互部分和业务逻辑部分。
2)从空间结构上看,业务逻辑和数据访问不是并列关系,而是隶属关系——数据访问隶属于业务逻辑。虽然在具体系统实现层面,数据访问层和业务逻辑层是并列 存在,但从概念本质层面上分析,两者是隶属关系。
3)从时间结构上看,应该是先有业务逻辑的概念,才有数据访问的概念。业务逻辑衍生自软件本身,数据访问衍生自业务逻辑。
4)因为业务逻辑是软件产品自然的一部分,所以拥有业务逻辑是软件产品的必要条件(读者可以试着举出一个不包含业务逻辑的软件)。但是一个软件可以没有数 据访问,如“计算器”、“不带存档的小游戏”等。
利用以上论述要点和认知分解,朋友们可以试试在脑中重新构筑狭义和广义“业务逻辑”的概念。看能不能把我们丢掉的业务逻辑概念找回来。关于业务逻辑更多的 细节,将在下文中讨论。
2、细说业务逻辑
2.1、业务逻辑到底是什么
在第一大节里说了那么多,相信各位基本已经形成“业务逻辑”的概念了。如果我在这里再啰嗦什么,我不嫌累各位也要嫌烦了。所以,这里我仅给出两个定义。
广义上的义务逻 辑——软件本身固有的一种品性,自然存在于软件产品内部,是软件具有的在某个业务领域内的逻辑,是软件的核心和灵魂。软件产品除界面和交互外的一切都可看 作是广义业务逻辑。
狭义上的业务逻 辑——等同于分层架构中“业务逻辑层”的职责,是软件中处理与业务相关任务的部分,一般狭义上的业务逻辑不包含数据持久化,而只关注领域内的相关业务。
对于以上两种定义,希望朋友们不要割裂开来看,而 要辩证统一的去看,这样,才能构建一个完整而辩证统一的“业务逻辑”概念。在下文中,将不再明确区分狭义和广义,“业务逻辑”一词将代表两者的辩证统一 体。
2.2、业务逻辑的组成结构
业务逻辑作为一个高层次概念,其内在结构也是非常丰富的,下面我们深入其里,去探寻一下业务逻辑都是由哪些更底层的部分构成的。
2.2.1、领域实体(Domain Entity)
通俗的说,领域实体就是这个领域内有哪些东西。例如,银行业领域内有账户、支票、前台营业员等实体;B2C电子商务领域有商品、订单、交易等实体;魔兽世 界游戏的领域内有角色、种族、道具、魔法等实体;高等代数领域有矩阵、行列式等实体。
领域实体是某个领域内各种对象的抽象,可以用名词表示(可以是具体名词或抽象名词,甚至动名词,只要其具有名词性),构成了整个业务逻辑的骨骼和静态模 型。一般每个领域实体有自己的一些属性和行为。 顺便说一句,领域实体的存在时OOA&D的基础。
在具体的软件系统中,领域实体往往会根据架构的不同有不同的映射存在形式。
其中一种叫做Business Object(BO),即业务对象,某些文献称其为“充血实体类”,这种对象完整抽象了领域内的某个实体,封装了此实体相关属性和行为。在面向对象的设计 和架构中,这种实体类很常见。
另一种叫做Data Transfer Object(DTO),某些文献称其为“贫血实体类”,其特点是仅有属性,不存在行为。这种实体类主要负责整体性传递数据。另外,与BO不同的 是,DTO可以不抽象领域实体的全部属性,而只根据需要抽象一部分。例如,某个“User”实体存在很多属性,但如果某个方法仅需要其联系方式,可以设计 一个DTO,仅有id,email,address,phone等就够了。在面向过程的设计和架构中,这种实体设计比较常见。
2.2.2、业务规则(Business Rules)
业务规则就是某个领域内运作的规则,构成了整个业务逻辑的灵魂和动态模型。业务规则作用于领域实体,领域实体遵从业务规则进行运作。
如:在银行领域内,“转账时从A账户扣除相应款项,在B账户添加相应款项,并从A账户扣除相应手续费,并通过某些途径通知A和B账户的户主”就是一条规 则。需要注意的是,业务规则比较抽象,并不是需求,需求需要具体且无二义性,而业务规则只是抽象的一种描述,例如,通知户主的途径是什么?电子邮件?电 话?短信?并没有具体描述,但在规则中有“通知”这一项,因此不能将业务规则等同于需求。
2.2.3、完整性约束(Validation)
领域实体和业务规则构建了业务逻辑的主体,但在这主体之上,还存在着一个限制,这就是完整性约束。
完整性约束是对业务领域中的数据、规则的强制性规定与约束。这种约束是系统正常运转的保证。
如“账户密码不能为空”,“身份证号必须符合具体格式规定”,“转账流程必须具有原子性,A账户扣钱、B账户存钱、A账户扣除手续费、通知户主四项操作必 须要么都做,要么都不做”,都是完整性约束。
2.2.4、业务流程及工作流(Business Processes and Workflows)
有了上述三项,业务逻辑还不能正常工作,因为还没有“启动器”和“过程托管器”。设想我们有了各种实体类,它们有各自的属性和行为,也有定义好的业务规则 和完整性约束。现在实体类仅仅具有实现业务规则的能力,但它们如何启动并交互协调完成业务规则呢?因此我们需要有东西去触发和协调实体。
业务流程或工作流是启动及托管协调领域实体完成既定规则的过程。例如,“在线订购”是一个业务流程,它包括“用户登录-选择商品-结算-下订单-付款-确 认收货”这一系列流程。各个实体如会员、订单、商品等已经包含了完成在线订购必要的行为,但仍需一个流程,才能真正完成业务。
具体到程序中,业务流程也许通过一个方法来实现,这个方法负责启动并协调各个实体类,完成一个流程。
2.3、业务逻辑层职责及相关争议
2.3.1、数据的格式化
关于数据的格式化应该放在业务层进行还是表示层进行一直存在争议。我个人的意见是这样的:
业务层送给表示层的数据应该具备以下要求。1)返回的数据应该完成了所有必要的业务处理和业务计算。 例如,若返回订单信息让表示层展示,会有个必要的数据——订单总额。这个数据需要首先用各个订单项的单价乘以数量,然后加和。那么,这个数据应该在业务层 完成计算直接返回,总之不应让表示层进行任何业务处理和计算操作。2)一次 性返回所有需要的数据,避免表示层再一个Action里调用多次业务。 打个比方,例如订单中有个“客户姓名”,这个数据不保存在订单表中,而是通过外键关联的,那么,业务层应该将“客户姓名”一并取出返回给表示层。总之,避 免表示层在一个Action里多次调用业务层。3)不携带任何格式信息,仅 仅是结构良好的纯净数据,如DTO形式。 因为,数据如何展示,是表示层的职责,如何在业务层中返回了过多格式信息,就会造成表示层的修改困难。例如,我曾听说过所里承接的一个实际项目,开始是使 用B/S,当时他们的业务层返回的数据全都附带了html代码。后来,客户嫌B/S响应不够迅速(可能是客户公司的网络条件不好),要求改成C/S,当时 全傻眼了,貌似几乎修改了整个业务层。那个项目相当庞大,7个子系统,投入200人开发了1年多,想想修改的难度吧。
2.3.2、数据合法性及完整性验证
一般做系统,都避免不了数据验证。上文曾经提到,完整性约束是业务逻辑的一部分。如此看来,数据验证一般应该放在业务层。但是,实际情况并不尽然。个人认 为数据验证的方式,目前没有统一标准,可以根据需要放在表示层或业务层。但是,我个人不提倡在“表示层的服务端”放置过多完整性验证。因为,表示层的职责 应该仅仅是接收数据并传递给业务层,不应对数据是否合法负责。过多的数据验证,不但令表示层代码臃肿,而且使得表示层职责变得不明确。
可以在“表示层的服务端”放置一些简单的验证,如空值验证,两次输入密码是否一致等,但业务关系紧密的验证,最好放在业务层。甚至有些验证只能在业务层验 证,如“当前用户名不能与已有用户名重复”,这种验证需要访问持久化数据,需要由业务层完成。
这里之所以强调“表示层的服务端”,是因为一般在B/S系统中,都会在JavaScript里加入一些基本的数据验证,如空值检查,格式正则匹配等。这主 要是为了减轻服务器负担,将大多数显然包含不合法数据的请求拒绝掉,而不发给服务端验证。当然,因为可能会出现JS被屏蔽或黑客恶意攻击行为,所以,所有 验证不论JS中是否验证过,服务端(可能是表示层的服务端部分或业务层)一定要再进行验证。
2.3.3、CRUD
CRUD,即常说的增删改查操作。关于CRUD是否是业务层的职责,一直也是争议不断。因为目前并没有权威的定义,所以这里我斗胆说一下我对这个问题的看 法。还请大家批判性阅读。
一说到“增删改查”,大家一定会觉得这理所当然是数据访问层的职责。我认为这个理解是对的,但是只对了一半!之所以这么说,是因为“增删改查”有两个层次 含义。
第一个层次,是数据访问层次上的。在这个层次上,“增删改查”只是单纯的数据库操作,“增删改查”可以理解为“插入一条记录,删除一条记录,更新一条记录 的信息,获取一条或多条记录”四个操作,其意义和着眼点完全是数据访问层面上的,不带有任何业务成分和业务知觉。这个层面上的CRUD应该属于数据访问层 的职责。
第二个层次,是业务逻辑层次上的。在这个层次上,“增删改查”是业务领域内实体的变化以及一系列相关反应,“增删改查”可以理解为“领域内新增一个业务实 体,领域内去掉一个业务实体,领域内一个业务实体更新了信息,得到领域内一个或多个业务实体的信息”。
两者最大的不同,是业务层面上的增删改查往往不是单纯的增加减少,还包括实体变化后相关的业务流程。下面举个例子:
“添加一个新的订单”——这是一条典型的“增”操作。在数据访问层面上,它的意义是“在表示订单的数据表里增加一条记录”;而在业务逻辑层面上,它的意义 除了“领域内多了一个订单实体”外,还可能包括“根据业务规则判断是否是重复下单,根据金额对下订单客户的等级做相应提升、发送Email和短信通知客户 等”。可以看到,业务层面上的“增”可能不仅是简单封装一个简单的插入记录,可能还要去做其他数据访问——提升用户等级,以及做一些非CRUD的业务操作 ——发送短信通知。
在许多稍微复杂的系统中,业务往往不仅仅是封装了一条数据访问操作,而是还有很多如计算等业务处理,一个业务操作期间可能要多次使用数据访问操作。退一步 说,即使某个业务仅仅封装了一条数据访问操作,其意义和层面也是不同的,在数据访问层面,仅仅是多了一条记录,而业务逻辑层面,是领域内多了一个业务实 体。也许其本质上都是往数据库插入一条记录,但人类的抽象思维可以将之在不同层面上区分,这也是人类思维层面的一种抽象能力的表现。例如,我们知道太阳升 起不过是地球自转使得从背阴面转到了向阳面,但当人们看日出时,很少有人会说“看!我们从背阴面转到向阳面了!”,我们会说“看!日出!”,这就是同一事 物的不同层次表现。
2.3.4、存储过程
也许是性能上的诱惑,许多人喜欢在数据库系统中写很复杂的存储过程。这样,许多业务操作就被写到存储过程中去了。我个人建议,除非对性能要求极高,否则最 好还是不要用存储过程实现业务。例如,在一般的系统中,某个业务操作可能需要1秒,而是用了存储过程只用0.1秒,看上去存储过程将效率提高了10倍。但 对大多数用户来说,1秒和0.1秒的差别并不大,但是这样做的话,业务会变得十分不容易维护。所以,我个人觉得,除非十分必要,还是不要用存储过程实现业 务。
3、业务逻辑的架构模式及实现
Martin Fowler在《Patterns of Enterprise Application Architecture》一书中,总结了四种企业应用中业务逻辑的组织方式 :Transcation Script,Domain Model,Table Module及Service Layer,另外,本书的第十章“Data Source Architecture Patterns”中包含一种模式——Active Record。结合软件体系结构的近期发展及个人的理解,我更倾向将Active Record归入业务逻辑的组织模式,而Service Layer应该不算做业务逻辑特有的模式,所以,在本文中,将介绍四种模式:Transcation Script,Table Module,Active Record及Domain Model。
3.1、Transction Script
3.1.1、概述
Transction Script(以下简称TS)是一种面向过程的业务逻辑组织方式。这里首先要强调一点,这里的Transction一词与数据库系统中表示“事务”的 Transction没有任何联系。TS是将领域中的业务分解为一个个业务过程,每个过程实现一项业务功能,具体到程序中,一个业务过程往往映射到一个方法。TS是完全面向 过程的业务组织模式,适合应用于业务逻辑较简单的场合。
应该说,我们见到的绝大多数系统都是以TS组织业务的。例如PetShop及Oxite等经典示例。有时为了方便维护,开发者会将同一领域实体相关的业务 方法集中到一个类中,这里虽然用到了领域实体和类的概念,但和面向对象没有任何关系,完全是面向过程的。
当使用TS时,可以不需要数据访问层,而是将数据操作执行代码(如执行SQL或存储过程的代码)直接嵌入在业务方法中,有时为了复用性和维护性可以编写一 个helper类封装数据库的操作。当然这并不是说TS不能配合数据访问层使用,但由于应用TS的场合一般业务非常简单,如果配合Repository或 ORM使用,业务逻辑层往往就会变得非常“瘦”,看起来仅仅是对数据访问层的封装。一般在需要支持多数据库的场合,要配合Repository和 Abstract Factory使用。
TS的示意图如下所示:
图3-1、 Transcation Script架构示意
可以看到,在TS中,业务层并没有面向对象的东西。也许会用到类,但类只是组织业务方法的模块,每个模块中有一个个业务方法,每个业务方法完成一个业务流 程,完全按面向过程结构组织。
3.1.2、分析
应该说,如果具备以下条件之一 ,你可以考虑TS:
1)系统业务十分简单直观,并且频繁变动的可能性不大
2)工期很紧,需要尽量压缩设计的时间,尽快投入编码
3)不能熟练掌握和使用OO进行系统的设计与开发
4)厌恶OO,就是喜欢面向过程
1)设计阶段投入较小,启动耗费低。因为TS较容易掌握,使用起点低,所以使用TS的初期投入较少
2)在业务比较简单直观的情况下,TS结构的代码直观易懂,具有良好的可维护性
1)容易造成代码冗余。因为各个业务自行组织流程,所以减少了复用的机会,可能产生重复性代码
2)因为TS天生不适合业务复杂的系统,当系统业务较复杂时,可能会令业务层代码繁杂不堪
3.2、Table Module
3.2.1、概述
Table Module(以下简称TM)同样是一种面向过程的业务逻辑组织方式,与TS不同的是,TM更贴近关系型数据库结构。在TS中,一般使用DTO等进行数据表示和传递,其着眼点一般在单个对象。而TM一般根 据数据表组织业务模块,每个模块对应一个表,其中包含了这个表的相应处理。并且在业务层内,使用库-表结构的对象进行数据操作,做到最大限度与数据表的对 应。业务组织一般按照面向过程组织。
一般当业务相对简单且业务基本集中在CRUD操作时,可以考虑TM。使用TM意味着使用数据驱动设计。通常自己实现一套库-表结构操作对象的库是难度比较 大的,所以一般选用TM时,所使用的平台应该包括这么一套库。如.NET平台上的ADO.net就内置了丰富的库-表操 作,DataSet,DataTable,DataAdapter等在TM架构的实现中可以起到非常方便的作用。
使用TM后,一般不需要再配合Reponsitory或ORM,因为此时的业务层也是面向过程和面向关系型结构的,无须映射。
TM的示意图如下:
图3-2、Table Module架构示意
在使用TM后,业务代码中往往有各种对象对应数据库中的库、表、记录、字段等元素,并提供类似关系数据库的操作。
3.2.2、分析
如果同时 具备以下条件,你可以考虑TM:
1)系统业务较直观,以CRUD操作比较集中
2)整个开发的指导思想是数据驱动
3)所选用的平台有成熟的库-表操作库支持
1)类似关系数据库的数据操作方式非常直观,使得设计和编写数据操作功能的代码简单高效
1)TM需要完全的数据驱动,从业务到UI传递、存放数据都要以表结构形式,造成一定程度上的不灵活
2)当业务并非CRUD集中型操作,特别是领域模型和数据库表模型差异较大时,使用TM组织业务的难度非常大
3.3、Active Record
3.3.1、概述
Active Record(以下简称AR)是一种面向对象的业务逻辑组织方式。AR适用于在业务较简单的情况下,应用面向对象思想进行设计。它的基本思想就是将领域中每个实体抽象出一个业务类(BO),然后,将这个实体的数据和 行为封装成类的属性和方法。特别的,将CRUD功能也封装进BO中。也就是说,AR中的BO同时具备业务方法和持久化功能。其本身具有ORM的特性,其内 部要处理关系实体间的关联问题。
使用AR时,一般最好有相应框架支持,否则完全手工实现AR有点麻烦。像Castle框架中就有AR功能,Linq to sql也有AR的意思。使用AR后,一般不需要再单独使用数据访问层。
AR的组织架构如下图:
图3-3、Active Record架构示意
从图3-3中可以看出,AR对业务领域进行了一个简单的OO抽象,将各个实体抽象为AR业务对象,AR业务对象内含有数据、业务方法及数据访问相关的 ORM方法。另外,AR业务对象要维护实体间简单的一对多和多对多等关系。
3.3.2、分析
如果同时 具备以下条件,你可以考虑AR:
1)系统业务较直观
2)想尝试使用或习惯于使用OO进行系统设计与实现
3)平台上有成熟的AR框架可以用
1)使用OO的方式进行设计与实现,能在一定程度上避免冗余代码问题)
2)使用AR后,与某个实体相关的数据和业务全部集中于AR业务对象中,模块内聚性好,便于维护
3)实践证明,AR结构的业务层编码效率很高
1)AR仍需要关注数据之间的关联,在一定程度上带有数据表和影子,没有完全摆脱数据驱动,所以当业务领域和数据库结构差距大时,实施困难
2)AR的CRUD是以个体为粒度的,当进行批量操作时,如一次查数千个数据,如果严格尊从AR就需要生成数千个AR业务对象,这简直是场灾难。所以在有 大规模查询的情况下,可以考虑使用TS配合AR
3)如果业务非常复杂,AR将力不从心
3.4、Domain Model
3.4.1、概述
Domain Model(以下简称DM)是一种适合领域驱动和为复杂业务系统组织业务的面向对象业务逻辑组织方式。前面三种架构模式都有一个共同的缺点——不适合业务 复杂的系统。那么何为复杂何为简单?很抱歉,我给不出明确答案,而且我估计世界上任何一个人都很难给出标准的无争议答案。因为软件系统中的复杂和简单本身 就是一个难以量化的指标,很多时候,只能靠专业人员的经验了。
我个人估计,世界上95%的软件系统其业务难度都不会超出上述三种模式的能力范围,而若你不幸遇到剩下的5%,恐怕目前只有Domain Model能帮你了。Domain Model是一种纯面向对象的业务架构模式,它的核心思想是获取领域中的各种实体抽象,然后完全按照现实领域中的情况去建模和运行。并且业务对象是“持久 化无知”的。 关于“持久化无知”下面细讨论。这个模式十分复杂和难以掌握,但一旦掌握并使用,其能力绝对会超乎你的想象。
下面看一下DM的架构示意图:
图3-4、 Domain Model架构示意
从图3-4中可以看出,DM看上去是个十分纠结的模式,而实际上,它确实很纠结!实际上,我认为如果能熟练掌握并运用DM进行业务逻辑的组织,那这人绝对 是架构师中的大师级人物(我目前是做不到)。
还是先结合图示分析一下DM中的要点。
第一,DM中的业务对象是纯业务对象,不含数据访问操作。这个可以和AR中的业务对象对比一下。也就是说,DM中的业务对象是纯业务对象,它们只关注与业 务的实现。
第二,DM的组织内部对象多,关系复杂,而这种关系不再只是那种简单的一对一、一对多的关系,而是领域中的各种依赖和关联的抽象,关系类型多,非常复杂。
第三,DM需要业务部分“持久化无知”。所谓持久化无知,指业务部分只需执行业务功能,而不必关系持久化。在使用DM时,必须设计一套ORM机制(注意这 里用到了“机制”一词,而不是“框架”或“库”),使得在业务系统运行时,自动在必要的时候执行数据持久化操作。这也是为什么上图数据源和业务层间的箭头 是虚线的关系。
上文曾说过,DM要最大程度模拟现实情况。而现实世界和软件世界最大的区别就是现实世界是“内存无限大、永不停机的”,可以把现实世界看成在一个无限大内 存里永不停止运行的程序。而软件世界不同,它的内存有限制,我们不能将所有对象都放在内存,而且一旦掉电,它就会停止运行,正因如此,我们才需要持久化机 制去配合DM模拟现实世界。为了让业务更接近现实,它必须对持久化过程毫无感觉。而一套持久化机制默默为其营造了一个好似内存无限大、永不停机的环境,因 此DM才得以发挥威力。
第四,DM往往需要Services Layer的配合。因为DM内部仅有一个个业务对象,它们互相调用,并没有提供一个友好的接口与UI交互,所以在使用DM时,往往在其上对各种UI需要的 服务进行封装(回顾一下Facade模式),形成一个Services Layer,以方便与UI交互。
3.4.2、分析
如果同时 具备以下条件,你可以考虑DM:
1)系统业务极为复杂
2)有功底扎实和经验丰富的精通OO的架构及设计师
3)项目经费和时间充足
4)贯彻领域驱动设计
1)完全的OO思想运用,将使你享受到OO的所有优势
2)应付复杂业务的强力杀手锏。如果DM运用得当,将会使得复杂业务被高效解决
1)使用门槛极高,难度极大,如果团队中没有精通OO和系统架构且经验丰富的专家很难实施
2)设计过程极为复杂,可能会导致设计瘫痪
3)如何设计良好的ORM机制辅助DM是一大难题
3.5、各种架构模式的比较及选择
相信看过上文内容后,各位一定对各种业务组织模式及其特点、优劣、应用场景有了清晰地认识,如果我在这里再喋喋不休讨论各种模式的比较及如何选择,难免有 侮辱各位智商之嫌O(∩_∩)O~,所以这里我只给大家呈现一幅决策网络图,以期起到一个梳理和归纳总结的作用。
图3-5、业务架构模式决策网络
(郑重声明:图3-5为本人原创,并非摘录自已有文献,因此此图的选型流程仅代表个人意见。由于笔者水平有限,不能保证此图一定合理和正确。因此在实际选 型时请多多参考已有文献及咨询相关专家,此图只起总结归纳和探讨作用,不作为任何指导和规范。若因遵循此图选型而给项目带来的任何经济及其他方面损失,笔 者不承担任何责任。)
4、结束语
本文通过两篇文章的篇幅,先后介绍了业务逻辑的定义、相关理论及经典的业务逻辑相关的架构模式。本文中阐述了不少已有理论,亦掺杂诸多个人理解及看法。因 此请各位在阅读时多进行批判吸收,同时参考以后经典文献及书目综合理解业务逻辑,切勿仅看我一家之言。
另外,由于本文仅仅是综述性文章,不能具名业务逻辑的各个方面,在深度上也基本是浅尝辄止。因此,若希望深入理解业务逻辑,可以看到相关经典书籍及文献。
参考文献
[1] [意]Dino Esposito, Andrea Saltarello, .NET软件架构之美英文版(原名Microsoft .NET Architecting Application for the Enterprise), 人民邮电出版社, 2009
[2] [美]Martin Fowler, 企业应用架构模式影印版(原名Patterns of Enterprise Application Architecture), 中国电力出版社, 2004
[3] [美]Mclaughlin, Pollice, West, 深入浅出面向对象分析与设计影印版(原名Head First OOA&D), 东南大学出版社, 2007
[4] Google, www.google.com
原文地址:http://blog.csdn.net/eroswang/archive/2010/06/02/5642550.aspx
1、阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有 区别?
(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回值 < 0时并且(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是 正常的,继续接收。只是阻塞模式下recv会阻塞着接收数据,非阻塞模式下如果没有数据会返回,不会阻塞着读,因此需要循环读取。
2、阻塞模式与非阻塞模式下write的返回值各代表什么意思? 有没有区别?
阻塞与非阻塞write返回值没有区分,都是 <0:出错,=0:连接关闭,>0发送数据大小,特别:返回值 <0时并且 (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)的情况下认为连接是正常的, 继续发送。只是阻塞模式下write会阻塞着发送数据,非阻塞模式下如果暂时无法发送数据会返回,不会阻塞着 write,因此需要循环发送。
3、阻塞模式下read返回 值 < 0 && errno != EINTR && errno != EWOULDBLOCK & amp;& errno != EAGAIN时,连接异常,需要关闭,read返回值 < 0 && amp; (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)时表示没有数据, 需要继续接收,如果返回值大于0表示接送到数据。
非阻塞模式下read返回值 < 0表示没有数据,= 0表示 连接断开,> 0表示接收到数据。
这2种模式下的返回值是不是这么理解,有没有更详细的理解或更准确的说明?
4、阻塞模式与非阻塞模式下是否send返回 值 < 0 && (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) 表示暂时发送失败,需要重试,如果send返回值 <= 0, && errno != EINTR && amp; errno != EWOULDBLOCK && errno != EAGAIN时,连接异常,需要关闭,如果send返回 值 > 0则表示发送了数据?send的返回值是否这么理解,阻塞模式与非阻塞模式下send返回值=0是否都是发送失败,还是那个模式下表示暂时 不可发送,需要 重发?
一、PL/SQL出现的目的
结构化查询语言(Structured Query Language,简称SQL)是用来访问关系型数据库一种通用语言,它属于第四代语言(4GL),其执行特点是非过程化,即不用指明执行的具体方法和途径,而是简单的调用相应语句来直接取得结果即可。显然,这种不关注任何实现细节的语言对于开发者来说有着极大的便利。然而,对于有些复杂的业务流程又要求相应的程序来描述,那么4GL就有些无能为力了。PL/SQL的出现正是为了解决这一问题,PL/SQL是一种过程化语言,属于第三代语言,它与C,C++,Java等语言一样关注于处理细节,因此可以用来实现比较复杂的业务逻辑。
本教程分两部分,第一部分主要对PL/SQL的编程基础进行讨论,第二部分结合一个案例来讲解PL/SQL编程。希望读者阅读本文后能够对PL/SQL编程有一个总体上的认识,为今后深入PL/SQL编程打下一个基础。
二、PL/SQL编程基础
掌握一门编程语言首要是要了解其基本的语法结构,即程序结构、数据类型、控制结构以及相应的内嵌函数(或编程接口)。
1、PL/SQL程序结构
PL/SQL程序都是以块(block)为基本单位。如下所示为一段完整的PL/SQL块:
/*声明部分,以declare开头*/ declare v_id integer; v_name varchar(20); cursor c_emp is select * from employee where emp_id=3; /*执行部分,以begin开头*/ begin open c_emp; --打开游标 loop fetch c_emp into v_id,v_name; --从游标取数据 exit when c_emp%notfound ; end loop ; close c_emp; --关闭游标 dbms_output.PUT_LINE(v_name); /*异常处理部分,以exception开始*/ exception when no_data_found then dbms_output.PUT_LINE('没有数据'); end ; |
number[(precision, scale)] |
varchar2[(size)] |
v_id number; |
v_id :=5; |
3、控制结构
PL/SQL程序段中有三种程序结构:条件结构、循环结构和顺序结构。
条件结构
与其它语言完全类似,语法结构如下:
if condition then statement1 else statement2 end if ; |
循环结构
这一结构与其他语言不太一样,在PL/SQL程序中有三种循环结构:
a. loop … end loop; b. while condition loop … end loop; c. for variable in low_bound . . upper_bound loop … end loop; |
其中的“…”代表循环体。
顺序结构
实际就是goto的运用,不过从程序控制的角度来看,尽量少用goto可以使得程序结构更加的清晰。
4、SQL基本命令
PL/SQL使用的数据库操作语言还是基于SQL的,所以熟悉SQL是进行PL/SQL编程的基础。表1-1为SQL语言的分类。
表1-1 SQL语言分类
类别 | SQL语句 |
数据定义语言(DDL) | Create ,Drop,Grant,Revoke, … |
数据操纵语言(DML) | Update,Insert,Delete, … |
数据控制语言(DCL) | Commit,Rollback,Savapoint, … |
其他 | Alter System,Connect,Allocate, … |
三、过程与函数
PL/SQL中的过程和函数与其他语言的过程和函数的概念一样,都是为了执行一定的任务而组合在一起的语句。过程无返回值,函数有返回值。其语法结构为:
过程:Create or replace procedure procname(参数列表) as PL/SQL语句块
函数:Create or replace function funcname(参数列表) return 返回值 as PL/SQL语句块
这里为了更为方面的说明过程的运用,下面给出一个示例:
问题:假设有一张表t1,有f1和f2两个字段,f1为number类型,f2为varchar2类型,然后往t1里写两条记录,内容自定。
Create or replace procedure test_procedure as V_f11 number :=1; /*声明变量并赋初值*/ V_f12 number :=2; V_f21 varchar2(20) :=’first’; V_f22 varchar2(20) :=’second’; Begin Insert into t1 values (V_f11, V_f21); Insert into t1 values (V_f12, V_f22); End test_procedure; /*test_procedure可以省略*/ |
至此,test_procedure存储过程已经完成,然后经过编译后就可以在其他PL/SQL块或者过程中调用了。由于函数与过程具有很大的相似性,所以这里就不再重复了。
四、游标
这里特别提出游标的概念,是因为它在PL/SQL的编程中非常的重要。其定义为:用游标来指代一个DML SQL操作返回的结果集。即当一个对数据库的查询操作返回一组结果集时,用游标来标注这组结果集,以后通过对游标的操作来获取结果集中的数据信息。定义游标的语法结构如下:
cursor cursor_name is SQL语句; |
在本文第一段代码中有一句话如下:
cursor c_emp is select * from employee where emp_id=3; |
其含义是定义一个游标c_emp,其代表着employee表中所有emp_id字段为3的结果集。当需要操作该结果集时,必须完成三步:打开游标、使用fetch语句将游标里的数据取出、关闭游标。请参照本文第一段代码的注释理解游标操作的三步骤。
五、其他概念
PL/SQL中包的概念很重要,主要是对一组功能相近的过程和函数进行封装,类似于面向对象中的名字空间的概念。
触发器是一种特殊的存储过程,其调用者比较特殊,是当发生特定的事件才被调用,主要用于多表之间的消息通知。
六、调试环境
PL/SQL的调试环境目前比较多,除了Oracle自带有调试环境Sql*plus以外,本人推荐TOAD这个工具,该工具用户界面友好,可以提高程序的编制效率。
最佳编程语录(Best Programming Quotations)
A good programmer is someone who looks both ways before crossing a one-way street. — Doug Linder, systems administrator好的程序员这样一类人,这类人在横穿一条单行道前都要先看一下路两边。– Doug Linder, 系统管理员
A most important, but also most elusive, aspect of any tool is its influence on the habits of those who train themselves in its use. If the tool is a programming language this influence is, whether we like it or not, an influence on our thinking habits. — Edsger Dijkstra, computer scientist关于工具,一个最重要的,也是最不易察觉的方面是,工具对使用此工具的人的习惯的潜移默化的影响。如果这个工具是一门程序语言,不管我们是否喜欢它,它都会影响我们的思维惯式。 –Edsger Dijkstra, 计算机科学家,著名的“程序=数据结构+算法”的提出者。
Being abstract is something profoundly different from being vague… The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise. — Edsger Dijkstra抽象和模糊完全地不同,抽象的目的并不是把事情变模糊,而去创建一个新的语义层,在那里是绝对精确的描述。 — Edsger Dijkstra
Besides a mathematical inclination, an exceptionally good mastery of one’s native tongue is the most vital asset of a competent programmer. — Edsger Dijkstra除了数学爱好,对于一个有能力的程序员来说,出色地掌握自己的母语是最宝贵的财富。– Edsger Dijkstra
C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do, it blows away your whole leg. — Bjarne Stroustrup, developer of the C++ programming languageC很容易使你搬起石头砸自己的脚,而C++把这事变得更难,但是如果一定要这么做,那么你的整条腿都会被炸飞 -Bjarne Stroustrup, C++语言的发明者
Commentary: most debugging problems are fixed easily; identifying the location of the problem is hard. — unknown修复bug很容易,但是定位bug却很困难 – 匿名
Considering the current sad state of our computer programs, software development is clearly still a black art, and cannot yet be called an engineering discipline. — Bill Clinton, former President of the United States看看当前计算机程序糟糕的事态,软件开发明显一直是一门妖术,其仍然不能被称为一个工程学。 –比尔.克林顿 美国前总统
For a long time it puzzled me how something so expensive, so leading edge, could be so useless, and then it occurred to me that a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are, in short, a perfect match. — Bill Bryson, author, from Notes from a Big Country长期以来,有个事一直困扰着我,那就是越是昂贵的,越是前沿的,就越可能是没用的。然后,困扰我的另一个事是,计算机是一个死的机器,却可以不可思议地去完成那些巧妙的事情,而计算机程序员是那么聪明人却在做着不可思议的愚蠢的事情,简而言之,他们真是天生的一对。– Bill Bryson旅游文学作家 Big Country中的笔记
Given enough eyeballs, all bugs are shallow (e.g., given a large enough beta-tester and co-developer base, almost every problem will be characterized quickly and the fix obvious to someone). — Eric S. Raymond, programmer and advocate of open source software, from The Cathedral and the Bazaar足够多的眼睛,就可让所有问题浮现(比如:只要给于足够多的beta测试者和开发人员一起工作,那么,几所所有的问题都会很快的出现,而修正也会是显而易见的)
Good code is its own best documentation. As you’re about to add a comment, ask yourself, ‘How can I improve the code so that this comment isn’t needed?’ Improve the code and then document it to make it even clearer. — Steve McConnell, software engineer and author, from Code Complete好的代码自己本身就是最好的文档。当你打算加注释的时候,问问自己‘我如何才能把我的代码改善到不需增加注释?’重构自己的代码,然后使文档让其更清楚。 — Steve McConnell《代码大全》的作者
Hey! It compiles! Ship it! — unknown嘿,编译通过了!出货!–匿名
Inside every well-written large program is a well-written small program. — Charles Antony Richard Hoare, computer scientist在每个编写精良的大程序里面都是一个编写精良的小程序。 –Charles Antony Richard Hoare,计算机科学家
It should be noted that no ethically-trained software engineer would ever consent to write a DestroyBaghdad procedure. Basic professional ethics would instead require him to write a DestroyCity procedure, to which Baghdad could be given as a parameter. — Nathaniel S. Borenstein, computer scientist需要注意的是,没有哪个经过规范培训的工程师会赞成写一个DestoryBaghdad(摧毁巴克达)的函数。最基本的职业规范会告诉他们应该去写一个叫DestoryCity的函数,然后把“Baghdad”(巴克达)当成这个函数的参数。—— Nathaniel S. Borenstein, 计算机科学家
Managing programmers is like herding cats. — unknown管理程序员就如同养一群猫一样 –匿名
Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates, co-founder of Microsoft Corporation用代码行数来衡量编程的进度,就如同用航空器零件的重量来衡量航空飞机的制造进度一样。——Bill Gates,微软创始人
More good code has been written in languages denounced as bad than in languages proclaimed wonderful — much more. — Bjarne Stroustrup, from The Design and Evolution of C++好的代码都都在的批评声中写成的,而差的则是在表杨声中写成的。——Bjarne Stroustrup, 摘自《The Design and Evolution of C++》
Programs must be written for people to read, and only incidentally for machines to execute. — Harold Abelson and Gerald Jay Sussman, computer scientists and authors, from The Structure and Interpretation of Computer Programs代码应该是写给其他人来读的,而能让机器运行的仅仅是附带着的。—— Harold Abelson 与 Gerald Jay Sussman, 计算机科学家和作家,摘自《The Structure and Interpretation of Computer Programs》
Real programmers don’t comment their code. If it was hard to write, it should be hard to understand. — unknown真正程序员从来不写代码的注释,如果代码非常难写,那么同样代码的注释也会非常难懂 –匿名
Simplicity is prerequisite for reliability. — Edsger Dijkstra简单是可靠的前提条件 — 迪杰斯特拉
The C programming language — a language which combines the flexibility of assembly language with the power of assembly language. — unknownC语言—— 一门同时具有了汇编语言灵活性和汇编语言强大能力的语言。– 匿名
The first 90% of the code accounts for the first 90% of the development time. The remaining 10% of the code accounts for the other 90% of the development time. — Tom Cargill, object-oriented programming expert at Bell Labs开始的90%的代码用了90%的开发时间,而剩下的最后的10%的代码会需要另外90%的开发时间。– Tom Cargill,面向对象编程专家,贝尔实验室
The important point is that the cost of adding a feature isn’t just the time it takes to code it. The cost also includes the addition of an obstacle to future expansion. Sure, any given feature list can be implemented, given enough coding time. But in addition to coming out late, you will usually wind up with a codebase that is so fragile that new ideas that should be dead-simple wind up taking longer and longer to work into the tangled existing web. The trick is to pick the features that don’t fight each other. — John Carmack, computer game programmer增加一个功能特性的成本并不单单是为这些功能编码所花费时间的成本,还这个成本应该包括特性扩展的障碍成本。当然,任何的功能清单都可以被实现,只需要有足够的时间。但是除些之外,你应该对你的代码库的脆弱性感到紧张,而那些新的想法应该足够的简单,而不是去花费更多更多的时间去纠缠于现有的蜘蛛网。这里的决窃是挑选那些不会和别人冲突的的功能。
The key to performance is elegance, not battalions of special cases. The terrible temptation to tweak should be resisted unless the payoff is really noticeable. — Jon Bently and M. Douglas McIlroy, both computer scientists at Bell Labs表现的关键是精美和典雅的,并不是使用大量的特殊案例。对于任何调整的冲动都应该是被限制的,除非其回报真的是值得注意的。– Jon Bently and M. Douglas McIlroy, 二者都是贝尔试验实的计算机科学家
The last good thing written in C was Franz Schubert’s Symphony Number 9. — Erwin Dieterich, programmer
最后一件用C做的好作品就是弗朗茨.舒伯特的C大调第9交响曲 — Erwin Dieterich, programmer程序员
The problem with using C++ … is that there’s already a strong tendency in the language to require you to know everything before you can do anything. — Larry Wall, developer of the Perl language使用C++最大的问题是..在C++语言里,存在这一种很强的趋势,就是如果你不明白C++语言的细节,你就无法做好任何事情。– Larry Wall, developer of the Perl language
The sooner you start to code, the longer the program will take. — Roy Carlson, University of Wisconsin你越早开始动手编码,你所花费来编程的时间就越长 — Roy Carlson, University of Wisconsin
The value of a prototype is in the education it gives you, not in the code itself. — Alan Cooper, software author, from The Inmates are Running the Asylum原型的价值在于他给你的教训,而不是代码自身 — Alan Cooper, software author, from The Inmates are Running the Asylum
There are only two kinds of programming languages: those people always bitch about and those nobody uses. — Bjarne Stroustrup世界上只有两类编程语言:人们都抱怨的语言和从来没有人使用的语言 — Bjarne Stroustrup
There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies. — Charles Antony Richard Hoare世界上有两个设计软件的方法,一种方法是设计的尽量简单,以至于明显的没有什么缺陷,另外一种方式是使他尽量的复杂,以至于其缺陷不那么明显。
Ugly programs are like ugly suspension bridges: they’re much more liable to collapse than pretty ones, because the way humans (especially engineer-humans) perceive beauty is intimately related to our ability to process and understand complexity. A language that makes it hard to write elegant code makes it hard to write good code. — Eric S. Raymond丑陋的程序就像一座丑陋的吊桥:他们相比漂亮的良好的吊桥起来,更有可能会坍塌,这是因为人类(尤其是工程师)感知漂亮的东西是和我们处理和理解复杂问题的能力相关的。所以,一个程序语言如果很难以优雅地方式编程,那么其就很难写出好的代码。
Weeks of programming can save you hours of planning. — unknown多做几周的编程可以节省你做计划的时间 —— 匿名 (意思为,只有实践过了,你才更容易做计划,没有实践过,做起计划来将会很头痛)
When a programming language is created that allows programmers to program in simple English, it will be discovered that programmers cannot speak English. — unknown当程序语言被设计成允许程序以很简单的英语来编程的时候,人们将会发现编写程序的程序员都来自不会说英语的地方。 –匿名