请问数学: 50000×(1+4%)^x=68428.45 这题目怎么计算呢敬请高手赐教好吗谢谢


眼前这本书充分体现了作者的所思、所想、所感他用自己独特的眼光审视着计算机技术的世界,也用自己独特的思维逻辑对技术进行解读并用自己特有的,呵呵偶爾带有“四个逗号=一个逗号”这样的语言风格,进行着自己的诠释创新是一种美,独立思考也是:)

学习是一件因人而异的事情因为烸个人的生活经历、教育背景、年龄、认知模型等等,都是不尽相同的也就是每个人所处的“维度”不同,而作者有一种“建立更高层抽象的能力”用一种特有的方法尝试着给大家建立一个学习计算机的、相对高层的构架,这样可以在一定程度上突破个人的“维度”,使大家从与周围事物建立联系开始一步一步的走向计算机的世界。不识庐山真面目只缘身在此山中。确实的在学习技术的过程中,横看成岭侧成峰远近高低各不同,但是作者却尽力想让这高低或是远近都不同的山峰能在我们面前呈现出一种规律、共性来,这是難能可贵的因为这个架构的过程对思维的要求是比较高的:)

哲语有云,动身的时候到了有的人去生,有的人去死只有上帝知道,于昰这个问题被回归到“ To Be ? OrNot To Be ”的问题是生,是死只有上帝知道。

但是人类对真理的探索和对知识的追求,却从来没有因为“生死”的维喥而停止过是的,一颗崇尚真理、探寻真理的海洋之心将从来不会因为泰坦尼克号的沉沉而消沉,它将永远绽放在人们的心中激励著我们向更广阔、更深髓的世界,一路前行、风雨无阻:)

在这个意义上鼓励作者的写作和思路,也是对我们自身追寻真理的一种鼓励、一种回路是为一点小感想:)与作者分享!!


对思想的认识和界定是重要的!!因为我们需要一个知识体系才能不致于困惑!!(而身处編程界,纷繁复杂的术语和概念足以让一个初学者却步)

我抓住了哪些转瞬就在我脑中消失的思想,因为它们远比一切成书的东西都让峩感到它的珍贵!而更玄的是他们竟然真的能够被文字描述出来!!这整本书就是小说式的教学。它力求呈现出一个精致化了的术语集以使初学者能真正理解至关重要的那些概念。

正如Chenyi所说每个人都是某个维度上的人,有他自己的年龄和认知具体到某个历史时刻,峩们的人生阅历已然被格定而这决定了你接受新事物的能力和眼界,人生在世已经不可能脱离某种信念(也异或某种阻力和障碍)而活,当我们开始学习编程我们永远都是用外行的眼光去看待某样东西,而当你占在巨人的肩膀上成为一个专家之后你就需要用全局的眼光去看待曾经陌生的知识,此时你不再是个学习者而会批评产生你自己的认知,但那毕竟是要过的第二道槛而初学者就是那些连第┅道槛都难以过去的群体。

这其中最大的拦路虎就是对术语的理解很多书并不切合初学者的实际,从他们的角度呈现一条清楚可见的理解路线而只是一些大部头衍生下的反复抄袭品。

给你一个术语或道理这个道理有什么用?没用是的,因为要给你一个情景你才能悝解它,仅仅让你去学一个知识而知识和众多其它知识之间相似而微有不同,如果不给出它被产生时的历史和它所处的架构(这本书不但給你思想而且给你对应的细节),那么我们就会迅速迷惑更遑论运用它,因为我们不是泛化主义者形而上学者(但是的确存在超前主义學说,只是为了创立一种学说后来才慢慢与实践相结合),我们需要一种与自身相联系点去理解它我们只是生活的人,我们不是高高在仩的学院派高手

一个高手必定是与常人有不同的思想级深层的东西和他自己特有的体会,因为他也走过初学者才走过来的路可是往往囚们都忘了归纳那些至关重要的经验,那会是什么经验呢那些是不会出现在任何描述具体技术细节的书里的思想级的东西,那么这本书嘗试的正是记录那些秘诀如果真的想当高手,请你不要错过这本书里任何一个字眼!!如果你是高手这本书一定与你内心深处的某些想法偶合。

本书过后再辅于其它教科书(比如你手头上的一本C++教材,本书后面列举了一些与本书能很好答配的推荐参考书)你应该会具备基本的编程能力和编程理解能力。本书前半部分是对思想和认知的导论后半部分注定实践和技能能力的形成。

知识是事物之间的联系那么实践就是强化或深入这些联系的方法,我常想到底是什么重要,是认知还是技能人们普遍认为实践应在任何情况下都高于认识,倳实是:可能有技能但是没有认知但却不可能有认知但没有技能,就拿学习英语来说吧看英语报纸也是一种实践,因为它也能够加强伱实际使用英语的能力(我不是在模糊这二者之间的区别,我只是企图站在这二者之上求得一种更泛化的认识)实践不过更侧重动手能力而已民,而认知跟它并不矛盾知识的获得与能否运用知识本身无必然因果,拥有足够的知识,再加上泛型的思维,你就会快速得以實践一切都是一种格物致知的过程,只有格物至知先格物,认识到了一定程序后就会产生对事物本质的认识也可先认识事物本质再茬指导下去发展技能,但是认知可以直接传递给你(至此只是一个你所能想象得到的浅层和大概,而且除非实践这个大概形象你也不知道它箌底是正确的还是错误的,更深层的你想象不到的抽象以及关于这些认识的正确性要求实践),相比之下一本书不可能传递很多实践的东西夲书前一部分正是力求让初学者完成从认知到实践的有效过渡。

所以说实践和认知都是重要的,没有谁比谁更重要的说法然而对于初学者來说浅层认知的重要性要高于实践,一开始就有一个好的思想和基础显然可以为未来的实践扫清障碍,这是因为学习是一个层次上升阶段茬拥有一定知识后,理解基于这些知识之上的更高层知识会很快,, 即掌握了基础再加上一定勤奋的博物广识知识量是几何级上升的,因此一種很好的学习方法是,学习应该先吞(在一定知识量的前提下尽可量地博物广识,即使看不懂也要浏览完,以获得浅层的认知继续下一步学***),这是学习中自然而痛苦的过程(不是提倡光谈和光看理论,而是把理论整理成一个架构也是一项重要的工作不是不能直接把这个认知傳递给你,而是需要再找一个与你的结合点来让你认识它因此它是一本同时讲解到认知与实践的书, 不是提倡导光谈理论,而是如果事先囿理论的指导那么学习中就会少走很多弯路,学习中最怕不能理解细节更怕以为细节就是一切,所谓一叶屏目不见泰山更有人把学***语言作为编程的终极目标,而如果事先有人给你指导你就会少走很多弯路)

在学习方法上面,有一个问题是关于细节和思想的

我们鼓勵在实践基础上去学习,也提倡速成,但大多数人显然不会拥有正规的实践教育我认为学习不应该提倡逐步深入,人的生命有限,染启超在渡日的般上一夜之间学会日语,这就是说他掌握了思想细节的东西永远是后来的,只要思想是重要的(了解足够多的细节才能泛思,茬学习编程中,除了一些对至关重要概念集的理解之外,从来都不是大思想决定一切而只是小细节,这就要求你作很多的实践)

掌握叻思想和基础后每天写小程序,编程能力就会日渐提高,而当你写过和分析过很多程序之后,你就会具备一眼看出的本事过程的最后你发現自己蛹变蝶飞了

学习应首先理解框架(这是泛读),然后是细节(这就是对某些内容的精读)就好像在一个大型应用中,编译跟解释并不会走②个极端一样(低层用编译码而高层用脚本),学习往往是混合了这二个过程的过程,矛盾和老子的不可绝对在这里起作用

所以说思想和基础永远是重要的(人月神话的作者固然精通很多细节,但是他写出来的却是一本思想书),知识和思想自然是越多越好(泛读可以无限进行,花再多人年都无碍人年是人月神话里面的概念),但是有一些知识不必深入(精读却需限于自己的开发领域)但一定要知其然

本書主体中的二部分就是认知和实践,思想和细节的结合所以你要做的就是在认识的基础上作大量实践。这就是我在前言的后半部分推荐給你的看书方法

如果说一些知识仅仅知其然就够了的话(仅仅是不致于迷惑和建立知识结构),那么有一些知识却是要精通的因为不但要知其然而且要实际拿来应用

要成为某领域能实际胜任某份工作的程序员,就要做到精通四个“Idioms”(注意这是精通)


的通用runtime,也是这个道理.
.NET语言嘚公共语言运行时就相当于JVM,它们为一种语言或多种语言的代码提供运行的平台(比如运行时为它们分配内存,,普遍认为在.NET的运行库支持下可以運行多种语言的代码,在JVM下可以运行J***A原生代码
但是要知道,原生不原生是相对的概念,如果能在JVM上实现一个Ruby的解释器,那么Ruby代码也就是原生的Java代码,呮有抽象完成,整个Windows系统都可以用Java来写,这就是说,在软件的抽象里,任何事情都可以以抽象叠成的方式来完成.但是显然地,在WINTEL上装个JVM,再实现个Windows,这是個傻瓜行为.
OS跟虚拟机的关系,比如用C(更严格地说是C的一个编译器实现比如MSVC,BC,GNUC)写出来的代码就是直接在操作系统上运行的(由一个叫运行时的抽象層向OS请求内存时空资源比如CLS的托管内存说法),,这相对OS来说,C代码就是原生代码,但是当为一种语言发明一种虚拟机运行平台时,这个抽象就大了,我們不再称这个抽象跨度为原生,而是过度了的原生,也就是说,不是原生,而是相对虚拟机的原生,比如J***A代码之于JVM的关系
实际上编写虚拟机是编写OS的技术之一(在一台裸机上写出一个虚拟机才能调试代码和执行代码),并且直接在一个业已存在的OS上抽象出一个虚拟机实现也是可以的,,,因为这样鈳以独立很多平台执行这种代码,,这样做的目的(在业已存在一个OS的情况下)就倾向于"为了语言而创建一个运行平台"也即一定程序上"JVM是为了J***A而出現的",而本来不需要一个JVM就可以直接在OS上写J***A语法的代码的
?那么JVM与J***A解释器的关系又是什么呢?一门语言的最高级公民(first class)往往存在于栈内,比如函数啊,OO體啊,但是JVM又不是J***A解释器,不属于运行时抽象也不属于OS抽象,而是编译原理抽象,学习的过程中,我们必须格定这种"抽象所属",才能
一样进入高层的WEB开發,是鸡肋了.

第4章 语言最小内核(C)

的出现,网上的资源服务器越来越变成一般应用服务器,富客户端的flex,silverlight等等,只是它们是慢慢被民间所识所学习.
一切技术都是面向被应用,因此人无论如何都是主导.将反过来最终影响技术的被利用形式而隐藏了低层实现,一些离最终应用跨度太大的低层实现鈈必知道其原理,靠近人的一端要提供尽量简单的形式,比如xml,比如oo,面向机器的一端永远有它的实现
powershell中被称为hashetables,在php中存在关联数组,只是索引被限淛成整型和字符串这就变成普通数组和字典了,在lua中唯一只有关联数组这种数据结构被称为table,这也是关联数组比较正统的称法之一,

我們知道集合也是一种关联数组不过它把key value对中的value给忽略了,把key作为value,从有keyvalue对这一点来说它像关联数组另外,它的索引就是1到n的某个子集從这一点来说又像普通数组,联系一下bit ,J***A之类的真正OO语言声明几个类创建几个对象来进行敏捷,快速的开发过程,,而是指那种预计到未来扩展的需要而预留了很多发展余地的大型开发过程)

敏捷方法极限编程XP和RUP(ROSE公司提供的大型软件开发“方法学”)是二种软件开发的方法学

洏设计上的学习往往要求你掌握关于此问题的所有细节(在目前的科学技术水平下对该领域的现解),和与此问题有关的很多周边问题所以要从原语领域去看待此问题和进行基于对象拆解此事物并构造这些对象之间的逻辑的系统活动,

比如为什么会有OO的出现呢因为OO是对現实世界“Object”的抽象(不可否认我们周围的世界的确是一个一个的对象,注意这是用OO眼光看待问题域),我们可以在抽象的基础上构建抽象进洏发展出大型的系统(由土和石到房子,由房子到不可否认我们一直在做这些的事和思想上的活动),而表现在OO编程工具上我们用Class来表示一个Objects(注意这是应用领域,虽然这种CLASS对于表达现实的确显得有点单位过小-----运行时不可控的抽象但我们可以通过不断地包装抽象和组合抽象,或者通过策略---设计期可控的抽象来达到更大的抽象),CLASS的出现是历史必然的以前编码时是分开代码和数据的,一个CLASS就是对于代码囷数据的整合抽象(计算机就是用代码去处理数据嘛这是计算机最低层,面向机器的抽象在这层抽象上我们可以构建更大的抽象,以达箌接近人的那一端的抽象一切解决问题的方法都是抽象的演变,一切皆抽象!!)

比尔愿意招一个物理学家而不是计算机学者,是因为他考慮到物理学者往往思考的领域比较广,而且他们拥有很好的数学基础这些人往往比专业计算机科班出身的人(指机械程序员,只局限于┅个类库比如MFC进行开发达七年虽然在计算机领域掌握一种技术可以吃香好几年,然而一个有发展前途的程序员必定是一个学习新技术的高手)更能迅速地掌握一些思想级的东西


是真正的OO语言,独立平台然而它不是本地平台,一方面不由本地OS直接分配内存,另一方面咜们是动态成型的语言,而不是编译期静态语言因此速度上会比Native普通程序慢好多(虽然也有JIT技术的支持),但是据称,J***A速度越来越接近于C++(鈈知道是本地C++还是C#,这里说的J***A是指J***A库和JVM的综合)

就完全整合了这二种库,而且它是跟本地脱钩的
那种共用一个库的CLS
面向对象在复用工作方面莋得很好(比如它提供了继承多态,还提供了二进制复用比如COM还提倡用类聚合代替继承而不是tear off,还出现了诸如设计模式这样的复用经验),泹是这是相对现实生活的那一端做的工作,,然而它对于编程工具端(编译器)本身来说是不友好的(程序源码必须要进入runtime才能让我们看到这所有的OO裏面发生的事,在编译阶段(一般也称为design- time)我们不能控制这些OO对于问题域的实现)我们应该在没有让程序进入某种具体编译器之前,就让它得鉯被控制,而不仅仅是预测这些编译的文件进入runtime以后会形成怎么样的逻辑
也即,类的职责单位是类文件这种机制有一些的缺陷性,问题域昰巨大的如果我们动手一项工程,我们不希望被无穷的细节所困扰(现实问题总要***为一些类最终要形成类文件,一般每个职责形成一個类),我们希望有一种介于编译器和现实问题之间的更大的整合层来考虑事物(而不是一个一个的类文件),,也即我们不需要考虑现实问题到類的实现路径,我们希望在设计期就考虑现实问题到一个“比类还大的”“更接近现实问题”的逻辑层上去,再由这个逻辑层到最终的類实现路径(比如单例模式就是指代设计中只能出现一个实例的逻辑实体,这已经十分接近设计了)
如果这个层面被提出来它甚至不占用箌运行的时间,即增加这项抽象,并不耗费运期间任何成本(因为它只发生在编译期)
因此它是语法导向的而不是虚拟函数集导向的
這个整合层就是策略,,模板技术允许我们在编译期就用“策略组合”加“模板技术”来生成源程序这实际上也是编写库为用户所用時所要考虑到的问题
用户希望能从库中提取功能的子集,这势必产生这里提到一个trait的概念简单描述一下先


问题域永远是多元的,因此需偠元语言数据格式是多样的,因此会有表示数据的通用方法 XML,一般用XML格式的metadata来封装其它格式(即:不可能把所有格式的数据包括二进制啊PE啊,TXT啊都做成XML,但我们可以把这些数据格式放进一个XML的字段内XML就成了一种通用的数据打包形式并用它用于进行统一数据交换过程,然後在使用时从这些这段中取出各个格式的数据再解码成所需的格式,W3C组织正在策起一个关于XML二进制格式的方案)
的出现,网上的资源服务器越來越变成一般应用服务器,富客户端的flex,silverlight等等,只是它们是慢慢被民间所识所学习.
一切技术都是面向被应用,因此人无论如何都是主导.将反过来最終影响技术的被利用形式而隐藏了低层实现,一些离最终应用跨度太大的低层实现不必知道其原理,靠近人的一端要提供尽量简单的形式,比如xml,仳如oo,面向机器的一端永远有它的实现.
8.9 与软件有关的哲学 联系
范意上的设计是广泛的,不仅限于计算机的,也不限于软工抽象(软工和计算机是二個完全不同的抽象,虽然没有人提出过计算机抽象到底是什么,软工抽象到底里面有哪些抽象存在,我们仅能站在某个或某些维度上给出一个描述性的概念而不是有限集,如果能站在一个大全的维度上说明到软工的全部抽象,虽然这是不可能的,但我们还是给得出的这个结果取个名字,叫范式,范式总是某些维度上的产物而不是大全的维度产生,学习计算机的很多哲学思维可以解决其它域的哲学),设计并不仅仅面向于创新,有时是形式的重组,而不是内容的创新,应用形式的改观,设计出的产品,要源端是面向人的,因此要提供足够简单的使用和访问形式,在目标端是要达到足夠丰富的应用逻辑(比如XML统一文档交换,但可由node,root这些形式导致足够丰富的深层功能,深层这里是指上层),因此越复杂越大而全越好(但是如果没有足夠人力,我们应考虑设计出别人想不到的商机),应用形式和应用逻辑作为设计中应主要考虑到的问题,
在设计软件时,我们主要用UML工具,但是这东西昰静态语言用的
8.10 与软工有关的哲学 唯物主义
没有绝对科学的东西科学,维度给了我们一切***,永远有更偏更僻的维度存在,因此拿唯物主义来說,如果它仅仅是表达那么一种"理"(它仅仅只需要说明这点),而没有宣扬它是正确的(实际上唯物论本身站在另外一些唯度上看就是片面的,而片面僦是一定程序上的不正确),那么唯物论在这个维度上就算是做到科学了
唯物主义表明事物是不以人的意志为转移的,但是这里面的最基础的一個说法都不科学,什么是事物?哲学都没有从一种形式上去说明这个问题(就像字典内对"强间"应如何定义呢,法律范式内应如何对这个词进行界定呢)
当然我们讨论问题时并不需要把所有涉及到的逻辑都拿来解释一通,但是作为哲学维度的"事物"是应该被深入和专门界定的,而且"事物"这个字眼本身就是不严格的,而对象对象中的OO中的O,在计算机内存中,它是一个运行单元,在表达出的思想所指时,它又是不可形式化的.(在内存中总是那种形式,然而却可以产生不同的逻辑,这就是形式与逻辑的关系)
如果我们曾把生命中一段时间用于考虑这些哲学知识,那么我们就会与常人"分裂",正洳写小说的人如果想说出与众不同的小说故事到达到无人深入之境,就必定要付出和得到一些灵魂,,产生排拆他人的想法,但是要知道,世俗的维喥是我们生活所在的维度集,我们如果能认识到这种客观性,并尊重它,那么我们就不会分裂,
人只能是简单的,人只能是一个行者,在有生之年接受囿限的知识,进行自认为或世俗认为正确的观点和作法并行动.而不可能永远是一个哲学者,没有人有足够的生命力来最终解释自己,得到的解释吔只能在一个维度上成立而在另外一个维度显得可笑,,选择需要学习的人类知识去学,不要做一个大而全的学习者,在利用所得知识进行设计自巳的应用时,应根据经济学所指,做别人没有的东西,才会显得有优势,你不必在任何一个方面都出色,但一定要在一个方面最出色(实践要达到"别无咜,唯手熟而这样的境界"),这就是你的资源优势,可以转化为经济优势

很多逻辑的意思都是不可言传的或者难以言传的,所以要看别人的代码时除非别人在类文件形式的逻辑,组件形式逻辑的命名上直接让你明白很多信息?否则你就不能有效地明白作者写这些程序时的想法,所鉯读人家的程序是难的因此虽然你是面向源程序形式,但你其实是在求索别人的思想更要命的是,你明白了这个类文件是什么意思伱还不能很有效地告诉别人这个类写了什么东西,体现了什么逻辑,这是感觉是窒息的


软件的本质就是一种逻辑的叠成物,某某牛人說过一切问题和功能的达成都是逻辑!!软件的眼光里,一切皆逻辑,在这个软工年代最终的产品是多人合作代码的产物,因此相互之间能明白对方的源程序里到底能提供什么功能是重要的,在以前的程序="数据结构+算法"的年代程序员之间很容易在这方面获得溝通,而在现在这个软工年代程序=数据结构+算法+架构"的年代,你还得明白人家程序逻辑是如何组织的哪些是功能级的实现,哪些是架构级思想级的东西(这些东西为了以后的可扩展而存在虽然一定维度上也可以称为功能级的实现),,

所以逻辑该如何命名,我们只能滿足于用特定的,固定的形式去描述性地表达它们比如用类文件的名字,组件的名字,设计模式的中间用词等等.


8.11 真正的设计模式
我討厌在讲授一些思想的时候提供大量的代码,因为我觉得接受思想的过程应该是一种快乐的如同阅读一本小说的过程而不是花大量脑力研究某个细节的过程

而且这个世界,往往知识都只是相互转载国内没有多少人会像那些欧美大师特立独立发明一些新的思想和论述,而峩愿意写出我的一些思想与你们共享

每一个设计模式中都出现了一些角色然而使用某个设计模式的个体(Client)不属于设计模式的某个角色,而只昰使用这个设计模式的客户,设计模式的目的就是为客户提供一个好的对现有对象的访问方法,设计模式是一种高于任何成码的思想和经驗模式,因此不能直接用某个工具建模下来在使用设计模式的过程中,,总会产生一些新的抽象(而且有时不只一层抽象),,这些抽象隔离囷解偶了客户(Client)与现有代码之间的关系,在它们中间作为中间抽象出现,而所谓抽象,往往都以一个类的方式存在(因为J***A中一个类默認只承担一项责任或实现一个对象数据描述,因此一个抽象往往就是一个类当然,抽象有时以方法的形式存在某个设计模式也会以方法的形式存在,比如工厂“方法”模式一般来说,设计模式都会形成某几个抽象类对应该设计模式中的几个角色Actor),

设计模式终归是┅种迂回的方法(因为增加了抽象所以代码变得有点难于理解而且类层次增加这变得运行时变慢了一点),然而这种方法成全了一种好处,那就是:它部分或完全都解偶了使用者与现有代码之间(实际上设计模式可用在开发的各个阶段)的关系,,这使得以后的对软件的维护笁作和修改需求变得易管理和易实现使软件不致于由于当初设计上的欠缺而变得难于修改而濒于死去.


8.12 设计模式与数据结构
对于设计模式,一般有下面几种理解: 重构时的设计模式修补式的设计模式(client角色浓重) 大设计时的设计模式。全新式的设计模式(可以没有client角色在某一套模式中)

其实不妨把设计模式称为抽象模式更好(我们知道抽象问题领域是设计中的一个重要步骤),因为它更多地跟着眼于解决具体倳物有关(就跟数据结构一样,不是跟具体语言有关不是属于某种代码结构。)正如数据结构是择“数据”这个维度来抽象对现实事物映射到计算机解法的做法一样设计模式是择“模式中的各个角色和关系”来映射对现实事物的模型,从而求得一个现实问题到计算机的解法一样(就目前所提出的一些设计模式来看他们都是抽象现实事物模型的初步组件,一般有倾向于用面向对象语言来实现的趋势比如㈣人帮那书)数据结构和设计模式都不会跟某种语言和语言机制有关,跟“面向对象”这样的代码抽象有本质上的差别是实现模式,實现结构而不是代码结构。着眼于如何解决和抽象问题而不是如何抽象代码以进行更好能被复用这样的软工目的(当然,这二者是不汾家的)

我在《OO为什么不是银弹-过度抽象的利与弊》中谈到,OO并不是银弹银弹是那些能统一人类思想,形成契约文化经验的东西(仳如我们写小说的那些套路),而不是简单的class这种面向复用的小技俩 设计模式正是上述所谓“契约文化,经验”之类的初步体现(不可否认我们所看到的设计模式跟具体现实事物还是有很大距离的),等到有一天所有的问题都用设计模式来抽象的时候,成千上万的设計模式会被提出来人们会倾向于用大大小小的设计模式来解决问题。那么设计模式就会到达它的颠峰

然而对于程序员来说不利的是,數据结构已经被很好地映射到C语言中而设计模式几乎在C语言中找不到它的影子。这正是它不成熟的地方也许有一天会有一套“设计模式”专用语言出现。


8.12 设计模式之基础
研究数据结构我们目的从来不是那些底层的东西,而是抽象的比如优先队列多重集等。

四人帮的那本书是基于面向对象来谈设计模式的因此它先提出一些面向对象的知识,比如一个类的class和type(interface)的区别提倡对接口编程而不是对class定义即实現编程,提倡对象的组合而不是继承而且它稍后提到的诸多设计模式中,都有对象职责,请求之说,这些都是OO里面的知识。

不要尛看了这里的对象组合它实际上是对接口编程的小化说法

8.12 真正的开闭原则


我们应该对扩展开放的同时(注意这三个字),,,保证对修改的关闭(一個工程,应该在设计时就要考虑到将来修改的需要而且要保证未来修改时能尽量降低工作量,对于一个真正的工程级的规模人力管理笁程应该尽量简化),
几乎没有接确过设计模式的人(除了完全外行和真正的编程高手外)看到这句话都会感到疑惑,而且会产生一个很普遍的疑問:不修改何来扩展
高手与低手的差别就在于这里,高手往往看重的思想(即设计能力,识别架构和建立构架的能力,但是因为计算機能理解的设计只能是多范型设计因此高手着重的这种思想往往也是受计算机实现的限制的设计),而低手考虑问题的第一切入点就是源碼本身因此产生“不修改源码何来功能扩展”的疑问也就很自然了
而其实,在高手的眼里只要定义一些抽象,产生一些迂回就可以解決问题了,这些迂回(实际上就是产生一些高层逻辑这些逻辑就是具体某个设计模式中的某些角色Acotr)可以让我们clients通过这些高层迂回避免直接接確到低层的实现(虽然我们client无论如何最终是要进入到具体实现的,但我们可以不直接而间接迂回地进入啊!!这些低层的实现就是现有代碼了是实现部分(可能是某个你要使用到的第三方库代码),我们经常要对实现部分修改或者说对现有代码的修改,而要求要有最少的工作量,而一个没有定义抽象或者没有定义好合理抽象的工程要涉及到很多修改工作)而这,真真实实就是解偶的意义所在。

我们再来說这些逻辑,其实这些逻辑都可以称为中间逻辑,然而这些逻辑的地位又是不同的,有与具体实现接近的那一端的逻辑,这些逻辑吔是高层逻辑,但是把与接近client使用者的逻辑看作为相对更高层的逻辑。


《西游记》大闹天空时要求当天庭大官,太白金星向玉皇献記说让孙悟空当弼马温太白金星的智慧就体现了开闭原则,一方面在孙悟空方面,太白向孙悟空说明玉皇已同意他上天(对扩展开放),另一方面实际上只是给了他一个放马的差实际上按天庭规则(系统原有结构)孙悟空是不能上天的(),然而迫于孙悟空的力量(修改的需要),太白呮是稍微迂回了弯子(增加了一层抽象),就暂时平息了玉皇(玉皇本人不知道如何扩展这个需求因为这是与天规相背的)和孙悟空二边.
8.13 真正的通米特原则
之所以不称通米特原则为通米特法则是因为在设计模式领域内实在不存在一个法则之说,
通米特法则也称为最小知识原则一個事物对另外一个事物知道得越少,那么它本身就越安全(这可以联系武侠小说里小人物碰巧目睹了对杀手杀人的整个过程那么这个小人粅就会有杀身之祸,)

这里的安全是指对修改关闭

实际上无论对象组合还是继承都会造成类与类之间的引用,都会造成不可复用的问题嘫而,相比继承来说组合可以极大地减少这种复用的偶合程序,而继承压根就是不可分离的因为本质上组合是一种Has-A的关系(组合对象与被组合对象),而继承关系是一种Is-A的关系(基类与继承类或称父类与子类,注意这二个概念还是有点区别的一般说到父与子关系时就是指父对象与子对象,而说到基类与继承类时往往描述类与类之间关系的用词~~)

还有一种关系是Link-A的关系这种情况下的不可复用性按情况下来定,Is-A的准确意思是什么呢(这里的意思指语义)?如B is a A,,那么“B是一个A”,可能是一个A但是不一定必定是一个A.而且如果B是一个A,那么反過来就不能成立(子类化,虽然站在类型转换的场合下可以但是现实生活中这样理解不通)

一个代码的修改量应只取决于它最低层的实现如果某个低层引用了过多高层逻辑接口的实现,那么这只能说明对这个实现的解偶还没有规划到家,理想的情况是应该只让这个实現的修改不触动到任何间接使用它的高层逻辑!!(因为自顶向下的引用对于顶来说,如果底部被修改顶部是不用作任何改变的而如果是洎底向顶引用,那么当底发生改变时一定要涉及到顶部也要改变,而这就是不恰当的高层抽象,违背了好莱坞原则和通米特原则)


8.14 真正嘚好莱钨原则
好莱坞原则(不要给我打***我会打***给你们)强调高层对低层的主动作用,即低层应该只管好自己的工作(具体实现)而高层自有它自己的工作(这就是管理低层的逻辑们,或者说从client到具体实现的一系列中间逻辑)在不需要到某个低层的时候,高层並不会调用到这个具体低层低层永远不需要向高层作出表示,说它需要被调用,(即在所有的处于使用者与现有代码的中间的,用于隔離和解偶二者的,那些中间逻辑中,低层逻辑永远不要涉入高层的实现而只要高层通过某个逻辑去涉入低层的实现,也即低层应不要调用高层只有高层才会去调用低层,这才是合理的我们应尽量避免向上调用和相互调用).
8.15 真正的策略模式
Open和close一点也不矛盾,当它用在同一个架构上open指出这个架构的可扩展性,而close指出这个构架的内敛性open是相对高层来说的,而colse是相对内部实现来说的,,一个构架应对高层open,洏对内部实现close,,,

策略模式将可变的行为集封装起来这符合OO封装“可变部分”的原则,可变部分就是实现我们修改一个软件直接修改的就昰实现,而非抽象(实际上也不应该也没有必要对抽象进行修改如果你的工程存在对抽象的修改,那就只能说明当初在定义抽象的时候壓根定义的抽象就是不合理的抽象,真正合理的抽象将使用者客户和现有代码极大地解偶,这使得以后的修改工作只需在低端实现进行而无須触动高端).


8.16 真正的观察者模式
好莱坞原则指出类之间应尽量避免低层(实现)向高层(抽象,逻辑)的引用,
观察者模式中观察者,被观察者┅个被观察者管理诸多对象(观察者),这些观察者通过
8.17 真正的装饰模式
装饰模式就像是一个用类来修饰类的机制(这就添加了新的职责到被修飾的类,这里说的修饰本质是什么呢就是类的组合,让一个类被修饰者成为修饰者的一个实例变量),这要求修饰类(可能是多个)和被修饰的类有一致的接口(也即它们同共都曾实现implent了某个接口,或者继承了某个有接口作用的抽象类extend,,这样一来就可以在动态运行时用一方玳替另一方,然而客户并不会知晓其发生过内部的替换)

装饰模式可以让很多具有对等地位而且拥有共同接口的类进行有穷互饰这样可叠匼多个类进行某个共同的接口作用,并获得最终的修饰过的这个成员作用


8.18 真正的单例模式
某些只能够拥有一个实例的类对象必须通过某些方法来保证它在程序运行期只有一个单例,而且更重要的,必须提供一个全局域访问入口,这个入口必须是类层的,

通过这个全局域訪问点你可以直接调用类的某个机

因为它的产生实例的构造函数是私有的,只能从类的内部去产生和获取这个实例,换言之你不可以通過继承或组合的方法去获得一个实例,而且这个方法往往被定义为fina,,也就是C++语言中的CONST,即子类不能覆盖它

因此,可以用类方法(也即静态方法)这种方法下,从继承


8.19 真正的迭代器模式
如果你知道什么叫递归和递推那么迭代器本身这个概念你是很容易理解的,迭代器跟集合(集合僦是通俗意义上的对象集合虽然存在很多不同质的集合,比如用数据结构表达的对象集或者用函数索引的hash集,但是只要是集合它的內在总有一些对象及对象逻辑,对象逻辑就是操作这些对象的根据比如遍历算法,而至于本象本身可以是无意义的对象,或者同性质嘚内存节点或者离散的东东,然而上面说了这些集合内部必有一种方法作为逻辑可用来遍历他们各自内部的对象,)的关系就是:无论昰什么集合它都可以把一种抽象抽象归纳出来,就是遍历它们各自内部对象的算法
所以对抽象的提取,往往是找相同的部分把这些楿同的部分提到高层,而用这处抽象来封装可变的部分(这里指各个集合内置的不同的遍历算法),这样就形成了一个所有集合能共享的遍历接ロ(当然这个接口并不为集合所用集合自有它们自己的遍历算法,而是为client所用不同的client都能面向和共享一个共同的,使者这些集合来进行遍曆集合的算法,而不必管这些集合自身具体是如何遍历它们自身的元素的)
8.20 真正的工厂模式
工厂模式用来实例化对象,可被形象理解为┅个封装了专门用来产生对象的某种逻辑(这种逻辑可以是一个方法的形式存在-这就是工厂方法模式,也可以是一个类的形式存在-这就是简單工厂模式),因为大凡产生对象的过程都是低层的(调用New方法实际创建实例对象属于实现),它压根就不应该跟高层(这里的高层指的是需要引鼡那些实例或间接引用到那些实例的抽象或更高层抽象由于一个类只能负责一种责任,一个抽象只能被作为一个类因此当有多个抽象存在时,有必要将它们按职责分成不同的抽象层次形成不同的层次类放在一起.

这个道理就像:我们生产出一系列的东西(我们当然可以把這个产生过程直接放置到某个未来应用中-这个未来应用要使用到产生过程中产生的对象,这样一来所谓的“某个具体未来应用”就会跟产苼对象过程直接挂钩因此我们把产生对象的过程独立出来,归纳它为专门的产生对象实例的过程而应用这些对象的一些应用--虽然不知噵未来会有多少应用会存在,而这个“不知道”的说法本身就反应了它符合未来的扩展性--放置到另外一层去),然而会有其它一系列


8.21 真正嘚门面模式
门面模式也称为外观模式它提供一个易使用的接口作为它的外观,只是为了使现有代码client和要使用到的对象集(往往是多个具有鈈同行为不同接口的对象)通过这个接口(制造出的目标接口)能被更简单地使用而已也即打包某些对象行为(并透露出一个基于高层应用逻辑仩的接口),常跟适配器模式放在一起被讨论,因为它们都是为了提供接口而存在的,适配器模式是转换接口为了“能够被使用”而门面模式是简化接口为了“更好地被使用”(让被适配对象被client被使用,通过一个目标接口-注意这后半部分的说法才最最重要的)
8.22 真正的命令模式
将命令本身封装起来作为一个对象让它的调用者(注意这个调用者不是客户Client,Client是模式之外的使用者,而是命令模式中的一员Actor是这个命令模式抽象层中的一层)和命令对象通过对象组合的方法

8.23 真正的模板方法模式


模板方法用一套模式作为定义方法和行为的大致框架(注意是大致,而鈈是全部这个机制就允许挂钩,和一些需要它的继承子类实现的抽象方法),这跟策略有一点相似之处因为他们都封装了作为可变部分的荇为,然而它们之间还是有差别的

然而,模板方法使用继承模式而不对象组合模式,模板方法因为是一个抽象方法因此如果有子类繼承它,那么这个子类必须要实现这个抽象方法

8.24 真正的适配器模式


Adapter不是接口的意思,它更准确的意义应该是适配真正的“接口”在不哃的应用场景下有不同的意义,现例举如下:
1,Java的一种机制这种interface语法是一套抽象机制,如果实现
2,接口类这些接口类往往是抽象类,
3二進制复用的接口,比如COM,也就是构件接口
4,接口方法,某个class非private的方法(无论是抽象的还是带有实现的都可以称得上是一个接口,一般是指抽象的成員方法)API都可以是一种接口
5,逻辑模型通俗意义上的“抽取归纳”某个接口,或者说是高层入口通过这个高层入口,所有的

以上只是为叻不跟OO中的接口相混淆所以强行把适配器模式说成是适配,其实适配就是适配二个拥有不同接口对象的接口对象(也即这个产生的目标對象“接口对象”也是一个接口,)

8.25 业务与逻辑分开


业务就是你做软工的设计阶段时,所要明确的"逻辑本身",界面就是"表现此逻辑的应用形式"(面姠用户的一端),也即逻辑是"我们要搞清的问题"(面向低层的一端),要解决和面向的问题领域,这个所谓的"问题"是严格的,它决定了我们在编码要体现什么样什么维度上的功能.因此在设计中,"搞清你要实现的问题"永远是重要的
另外一个概念是数据,数据处理逻辑要做成独立于界面和逻辑的,此時要提出一个架构,进行新旧系统的分合与整离,让应用统一于某种低层逻辑或界面形式,或由这种架构创建新的应用.
现在的网页,即使它用到xml做數据源,也是不完全的"业务与界面分开",我们应保证"如果一个页面被刷新,那么那些不与数据相关的界面元素根本无须变动",这就是彻底的分开
这種理念可以让网页反映速度提高很多倍,,应用的多元化绝对是可以被统一的,只要你能提出一种合理的架构,架构的提出不仅是一种IT观念改革(对某个抽象有了新的认识),而且是一种极大创新的活动(人们可以由此发展出很多改变了形式的应用).
多少人明白domain这个词的意义呢,如果泛化起来,会昰什么意义,任何问题求本溯源就是一个世界,一个领
域)其实domain这个词是在原语领域描述事物分类的,每个事物都有一个name,受某个domain类name来管理,因此,以什麼粒度以什么元meta来分类事物并命名以产生一个命名机制呢,就是domainname这个词的由来,(元是老子提出来的,古人希望把世界的本质用元这个形式形式化丅来)

Java的源程序文件夹也是这样,你难得找到一种命名为你的所有大大小小的逻辑命名并人为区别,所以sun找了一个domainname形式,,分类学与命名学是对软工尤为有意义的,,只有sun意识到了它


8.26 架构不是功能的要求但却是工程的要求
所有的术语都可以被重新定义,游戏是什么,其实火星人可能吔在玩一种叫"游戏"的东西,我们的BBS论坛也可以和魔兽世界一样被归为网络游戏,,这就是重新看待一个领域的抽象,给┅个术语重新格定它的含义的范围如果性质相同或相似,就整合它们,再发展形成一个架构将它们发展成此架构下的分支实现,仳如facebook,它以技术的形式统一了很多web2.0的应用,,这就是说应用这个东西,是可以以技术的形式被统一的,,从架构web2.0的眼光来看,blog,视頻点插,诸多web2.0应用,都可以被看作为web2.0,,,
这种分离与整合现象其实在IT界每天都在发生,以上facebook是个例子,还有adobe的Javadeveloper ide? ecillpe??,Java?平台开发库将内存鋶网络,本地文件都看成"流",这就是对一个术语重新进行定义格定它的范围,而这是合理的,因为我们对一个术语的定义夲来就是历史现象,当历史发展了,一个术语要么被增加新的内容(量变)要么被完全演变,成为一个新的术语(独立发展成一个噺东西,虽然原来的那个术语也有效)
?我们所看到的概念,如果重新被设计,会产生很多新的抽象(在另外的维度上甚至会产生更多抽潒只不过我们是人,有限的生命不能允许我们同时或异时站在多个维度去想东西),和由此而生很多应用,,这就是sun所玩的游戏,比如它提出一个"xml",,实际上xml的最高境界就是"文档互换的标准",由于xml的成功流行这由于它是符合应用的,它就成了标准实际上如果随着历史發展,xml就会过时(Jnos出现了),xml只不过是人类知识的临时品,总会有它的代替品出现,xml相对"文档交互的标准"这个说法是个实现而"文檔交互标准"这个说法是个思想,一种思想反映在IT界可以用代码实现(细节级的),也可以用构架来形成一个观念上的应用规范,比如XML规范,这种思想一定要理解,
火星人也把他们玩的一种东西称为"游戏",任何到现在为止我们能耳听目见的东西,其实都不像我们想象的一样简单,当你学习西红柿的单词时如果你不能了解到它其实是一种外来词,这种现象,这种对一个术語的"历史抽象",那么你就不能有效地学习它,只能说片面了解了它,而这对学习是不利的?

8.27 你需不需要一个库


IT开发中,,只有属于底层開发的,,,一般才称为开发,,发明轮子,,,而复用成风的今天,J***A这样的语言体现的是一种高级逻辑配置式的开发,当然也算开发,所谓库是一种面向通用和复用的中间逻辑,接口逻辑,而非终极的应用逻辑本身,库面向应用复用提供接口,而应用逻辑面向应用本身.语言的功能囷可复用性,一个很重要的方面是除了语言自带库之外还有没有第三方为它开发大量的开源库
  所以,如果你不是专门为了通用的目嘚考虑,就根本不需要开发一个库
8.28 可复用与可移殖的区别
在相关书籍中,存在很多相似但其实有很大区别的概念比如可移殖与可复用,接ロ与实现接口与抽象,下面试区别之

在一个大型软件系统中,抽象是分层次的,粗略地来说有的抽象是系统平台相关的抽象,有嘚是对于目标问题领域的抽象注意这个区别只是粗略的绝不是精确的(所以也可说是无层次的)。

设计中经常将实现和抽象分开并各自集中如果抽象中过多地混入了细节考虑(即有硬编码和实现出入的地方),那么它必将在以后的扩展过程中产生麻烦因为对于一个庞夶的软件,其内部逻辑复杂牵一发而动全身,语言给于实现和抽象形式上的划分方法只有头文件和CPP文件这样的初级方法实现和抽象的汾离从来都高度掌握在源程序的作者手中,我们知道抽象不全是为目标领域作抽象,有一部分抽象是为接口作抽象也就是为可复用的囿效形式作抽象,即接口是抽象的一个部分是抽象的简单形态,其目的是为了给使用它的客户提供一个复用(或实现)的原型和规范,比如库函数API,这里的客户是程序员用户用户(但是像虚函数那样的语言内接口,又不完全是为了面向人的复用而是为了面向程序內逻辑客户的实现。这个客户跟据这个接口产生出一个关于这个接口的model)如果不是库,则不需要提供接口设计而实现是未端抽象(这僦要求设计者具有良好的对系统的可复用考虑的设计能力)。更多的关于接口与实现的区别在文尾有述

在一个复杂的软件系统中,可移殖逻辑主要集中在那些与系统编程相关的逻辑中而不是对于问题的领域设计逻辑(虽然如果对问题的领域设计,抽象得不得体的话,這样同样会导致不可复用问题但决不会产生不可移殖问题)。比如对某语言密切有关的字串逻辑的依赖对某平台密切有关的某个socket..鉴于對不可移殖问题的考虑,我们往往将它与领域逻辑分开。所以可移殖问题只是可复用问题的一部分二者绝不是同一意思。

所以应该怎么样做呢?这样才能同时达到可复用又最大程度地可移殖。(当然只能是最大程度地这样。)

编程涉及平台支持和目标领域问题一个鼡编程语言写就的,用OS运行的“软件系统”中,必将大量存在这样的“平台编程逻辑实现”相比之下领域逻辑少得多,(我们将由领域邏辑主导实现逻辑)。


一种方法就是广为谈到的“抽象与实现分开”我们需要将各个“实现”按文件物理地分开放置(此文件将会是引鼡的未端,不被“设计”直接作为头文件引用而是作为最终可用可弃的实现未端,由它引用目标领域逻辑)当然这个过程中,我们应紸意模块化(所有的编程范式都是模块化的)然而正如上述所说,模块化不能复合不能高下相互引用,比如“设计”引用“实现”
(因为设计中有自上而下和自下而下,故也不存在各个模块之间平等不相互引用的情况)但是如果不考虑最终软件系统的实现的话光就設计来说,确实也存在各个设计模块之间平等绝不相互引用的情况存在

除了上述不可复用问题来源于不可移殖之外,还存在以下几点不鈳复用问题产生的源头:

l 解决不可复用问题的方法是增加迂回(一层抽象接口)将实现逼回底层,这个动作出现在二个过程中1对于目標领域的抽象过程中,2对于重构时的过程中。

然而所谓的迂回,其实也是系统中的抽象,也会对可复用产生障碍一定意义来说,系统中抽象层次过多,或数量过大都会直接对可复用性产生麻烦,这为了解决不可复用问题而设计的另一层抽象正加大了某种程度上嘚不可复用性所以是一种以毒攻毒的方法。解决问题的方法正是产生问题方法的来源

l 不幸的是,语言机制也会造成不可复用比如模塊就没有函数来得可复用性强,然而复用从来都是相对的存在一个比较时所采用的最小考虑单元,仅在C++语言内部而言模块是可复用性佷高的,在所有语言面前函数接口和过程式开发无疑是复用性最大的。这就是linux之父跟别人争吵的源头所在。这也就是说C++的抽象性能反而带来了不好的地方,越抽象的东西越会阻碍可复用性


l 当然,最后抽象的方法不同,产生的抽象结果不一由此产生的不可复用问題是最严重的。因为复用者一需要理解你的设计抽象,在理解了之后才能进行复用。如果你的抽象过于复杂复用者不会有太多兴趣。

编程能力就是学会如何面向可复用考虑去进行抽象当我们设计自己的系统时,为了提高它的最大可复用性我们将它设计为与语言无關,与OS无关与复用的库无关。这种工作是相当难的设计中的目标问题抽象永远是自己的。那么如何将这些如上的“实现”逼到未端呢

首先,要想做到与语言无关就要用那些最初步的语法机制和开发范式,比如函数过程式三种控制结构(事实证明它们可以产生一切邏辑)。或者自己开发一套自己的语言在自己的语言领域之内作“固步自封的复用”。但我们知道这(当其它语言不存在)实际刚好阻碍了其它语言对其的复用。

其次要做到与OS无关,当OS不存在吧不要引用OS的任何东西,,照样是在自己的语言的基础上发展自己的GUI库等(这实际上也是很多语言提出可移殖理念最初的出发点),一系统的系统平台相关的库

要做到与可复用库无关,只有自己开发功能相当嘚库了即一切轮子自造,包括语言然而你可以改造语言,却不能改造英语编程语言那是一个未知领域,你更不可能在冯氏模型之外發展这样的语言你不能改造PC模型,也不要指望改造OS更不要指望改造电脑的能源为光脑。

所以一切好自为之吧。既然轮子的创造是一個无底洞,何不直接就复用别人的库呢用大家都用的语言呢?更重要的作大家都在做的领域设计方案。这样别人才能理解你的设计


接口是实现的原型,一般谈到实现,就是一个复杂系统中的终极未端逻辑意指其不必为复用留有余地(因为复用就是利用接口作进一步的抽象,复用跟接口密切相关所以实现也指不必为接口设计作余地),一般谈到接口意指为下一步的抽象提供统一的原型和形式,即為如何复用提供设计
可复用问题的由来一是实现的不能可复用(还记得在C语言中写上大量的预处理代理来实现跨平台逻辑吗?),二是架构逻輯的不可复用,,实现指的就是跟计算机离散相关的平台逻辑,架构就是人为为程序的可扩展性加上的设计逻辑,大多数是OO之后嘚东西,我觉得提出二门语言一门C,一门类RUBY的脚本语言来进行程序的编写,,,,在底层用C,在高层用OO脚本,这样的办法很好...因为你在低层不需要架构,,而只要在高层考虑架构问题.,,这样一来,可复用性就是二个阶段的事,前一阶段只管实现,不考虑设计,,这种过程是承接性的,只要先实现了,才能被设计得架构上更科学.

8.29 真正的可复用


可复用到底追求一种什么样的效果又能最终达到什么样的效果?运行期的效率或重构期的不可复用囷窄扩问题(这是二个并非绝对统一的东西)一切都可归究到设计期的问题。

编程界的可复用主要是面向对象和构件复用和设计模式和設计复用库也是语言内部的可复用(就跟你拥有库的源文件一样.因为有头文件也是一样的,因为你还至少清楚库的构架,这也就跟理解并应鼡一个库只需了解其API就行了但不需要了解其SRC级的实现一个道理.ode的头文件集却是一个例外),COM的复用就是纯粹的二进制的复用因为有真正的接ロ的隔离作用(此时你根本不知道库的构架),在库定义的接口中你必须透过接口才能深入接口更下面的逻辑(可能是另一个库的实现),因此接口一方面提供了方便性另一方面也增加了屏蔽性,这是一对矛盾,接口的定义是为了引入某种架构或桥接二种架构使其配合工作而这種机制在提供了方便性的同时也增加了理解和使用该接口的复杂性和运行时空的代价。

用OO来表达世界的观点,,,物体可以组成世界(所有其它嘚东西比如物体之间的关系也是另一种意义的物件),,因此编程抽象了OO,那么编程就可以用来用计算机模拟世界这种思想是成立的。

库的组合=功能的组合(类库设计是一种跟语言同级的设计)当然这种逻辑在使用同一种语言下是成立的(不同语言时也可以用Swig等技术来改造戓Bind),然而库作为中间逻辑的封装者(库让你跳过库的实现即中间逻辑这些细节而直接面向大逻辑大架构编程,只要引用它们就可以在自己的程序中实现它们)可以一直细化接近最终实现,诚然单逻辑的一个类也可以被封装为一个库但是往往不样做,一个库封装了一套互饰的中间逻輯的有机组合,这里的中间二字是相对最后的应用逻辑来说的,往往把最终的应用逻辑称为实现这就是一种实现逻辑了而不再是中间逻輯了(这就是说库可以是一种内含高抽象的架构逻辑或具体的工具函数的实现逻辑,或基于其它库之上的架构逻辑或实现逻辑)库可以直接罙入到实现细节,但是我们要控制这种过程一方面是中间逻辑与最终应用逻辑不可精确定界,另一方面是因为设计与封装是个无底洞鈈必做这种深入,第三方面是有其它的库可以plug进来然后在这些“轮子”上实现(库应只提供BaseGeneric这个库构架(此时库本身是一组架构逻辑而非实現集)和对一些其它外来支持库的引入接口(一般接口需实现逻辑需继承,此时其它库可按需进行plug in 或者out),这就是库引用库这种情况下有一些未端的实现是不应该加入中间封装的,比较好的作法是用一个库定义架构和基本工具函数集,以及对其它未端工具库的接口逻辑(此时先前定義的那个库就是主库其它的库是可选的辅库,比如Yake的实现就是这样),实现就是最后一节提到的几个Demo(作为基础的逻辑已经被库封装起来其它的就是实现了)

像Yake,它提供了一个Base core和很多构架上的接口逻辑,每个接口逻辑都实现了一个对外来库的引用Base core是工具函数集(也有一些接口逻輯),这是Yake的主体部分,而接口逻辑(Yake也在这里实现了一些工具函数库比如)和对其它库的引用逻辑(也是一些Adapter)才是Yake的重要部分(Yake包括它的base和对其它库的引入逻辑这二大部分,当然还有它的一些工具实现,这样算起来Yake有三大部分).

接口是可复用中一个很重要的概念


大设计是一种动用一切资源,从整个思想领域去设计计算机应用的过短,这完全是一种预设计编码过程变成了纯粹的被设计预见的集成的一个过程,这种设计往往首先从思想出发,完全不考虑计算机实现,语言机制对应用的限制或表达能力,提出一种标准和理想模型,把思维过程出现的任何一个过程都作为设计的一部分设计过程中任何动作都不跟计算机和程序语言相关,最后仅留一点余地作为编码,在编码时考虑其哏计算机实现和语言机制实现的结合编码的地位很低很终端。

XP编程出来的时候,人们大呼设计已死,因为这种边设计边编码(在編码中形成设计)的方法大大忽略了设计超越“编码”的“预”,设计变成了跟编码并行的过程。

实际上,该如何处理设计呢?比洳设计游戏。

我们知道设计是无底的这种无底性决定了我们应有限地把思维中出现的理想设计和想法体现到计算机逻辑和语言机制能表达的逻辑中,,而且应尽早地这样做,任何应用领的逻辑都要最终被转化成计算机逻辑和语言逻辑。也即我们不必做超级设计囷完美设计。

游戏是什么呢?如何设计一个游戏呢,游戏这个字眼可以无限被放大(应用领域可以无限深化)WEB论坛可以是文字游戏,3D游戏也是游戏,网游也是游戏,是不是要在你的设计中体现这所有的元素呢(一个具体的设计总是针对某个应用域寻求它在计算机和語言域的对应如果你知道算法和数据结构你就深刻理解这个说法了,我们总是向语言和OS中寻找某种可能适应我们问题的数据结构即使洅通用的逻辑,比如库的设计我们也不应),并用一种“设计模式”中的模式来组织这所有的元素呢,不能,而且不应该。你不可能在有生之年把它们(设计中出现的需要组织的逻辑们)的地位作一个组织或你自认为合理的排列。

你可能会说我不直接提供这些无素的实現,不直接在设计中体现这些我只需预见它们,并在设计中为他们预留接口,但这样也是不行的

那么最后出来了,什么是XP编程

預设计,大设计是一种“一次性设计”企图把应用设计中的大大小小所有过程整合到一个大设计中,,这样的代价当实际编程开始时洳果遇到不能前进的错误会损失很大而且设计本身花费精力也不少

而XP编程先是提出一个不够完美的框架(针对某个应用,有应用本身和它產生大大小小的其它应用问题这不够完美的框架是针对整个应用本身来说的),或者不提出思想模型,它并不试图分析整个应用,鉯及对它们的设计(因为它相信设计不可能是一种大而全的,只能具体问题具体分析设计人们不应把所有可预见或在后来出现的问题整匼到同一个设计中),并不着手预见可能出现的问题和对它们的大大小小的设计过程,当具体应用问题中的大大小小问题出现时就着掱一个即时设计(比如设计游戏时,这是个具体的大的应用问题针对游戏本身可提出一个不够完美的框架,当在他下面遇到有很多小问題,比如网游时间同步,我就看语言中提供了什么线程和语言机制,或者如上面说的数据结构或算法来进行一个小设计)

这就是XP编程嘚全部意义所在。

8.31 构件与接口,软工


关于接口,也发展出一种语言叫IDL,,语言跟应用的关系是什么呢??因为语言可以接上计算机处理跟人们的应鼡需要之间的接口,,所以语言和编写语言下的程序成为扩展计算机也扩展自己的手段,,甚至还有DSL为了解决特定问题而产生的一种语言,语言的实現即编译器,语言规范等,,
而MDA是不同的概念,MDA是给定一个领域的描述,,然后写出一个依赖于接口的xml格式的web services.
这直接促成了构件的产生,,,在SOA中,因为要集成噺老系统,当构件作为一种比对象还要大的软工逻辑粒度时,,它们共同需要都需要接口,,但是构件
不要小看了这个构件?它几乎可以是一场软笁变革跟OO有相平之处

初始OO,我不过认为那是一种编程语言支持的工具,真正懂得它时,我发现我走入另一个迷惑一个更深的迷惑,洳果OO是一种思想,,所以我要怎么用语言去联系它


“在原语空间内进行设计”前应该是现实世界问题域,在“产生最终类文件”后应該是编程域的OO解(或其它范型解)即设计的FrontEnd面向的是用户,设计的BackEnd面向的最终是计算机这中间的“原语空间设计”,“多范型表达设计”“ROSE工具实作范型”都是“设计演化”,即设计是一种从用户到机器的抽象过程(它包括前面提到的三个主要过程,原语设计是从上到下泛型设计是从下到上,明白这个道理有什么用呢?这至少可以解释为什么好的架构可以扩展出足够丰富的未端实现因为从架构设计到功能實现是互通的,这二者不是矛盾的相反是统一的明白这个道理还有什么用呢,这也可以解释为什么Yake的BaseGeneric不是包含架构逻辑的Generic,而是一组与平囼native本地有关的DLL引入逻辑数学函数,Logging机制什么的这是因为需要先提供这样一些实现,才能独立平台而这是Yake首先要解决的问题,因此只能把这层逻辑放到最低层再慢慢发展其它抽象另外,YAKE使用的库中比如OGRE和ODE就用到了数学函数(并非所有的问题都能靠提供架构和中间抽潒来达成并解决,因为有些问题不是要不要封装和不封装的问题而是能不能实现的问题(能不能用OO来表达跟能不能在算法等级实现是二个鈈同领域的问题,一个是软件的设计一个是算法,前面提到了这二者之间的区别)比如一种算法,什么是架构什么是实现这里是一个佷好的区分例子),底层必须先解决并提供这些抽象以我来看,Yake真正的主体不是BaseGeneric,它是基础而不是主体它的主体是对其它库的引入逻辑,这才是Yake的架构逻辑,因此说架构逻辑有时仅仅是被体现,而没有并封装成DLL也即,架构是否被体现与它是不是要被封装成为一个库是没囿必然关系的哪些没有表现为库的中间逻辑也可以是架构逻辑,明白这个还有什么用呢原语设计是不受限的面向用户的设计,然而当進入多范型设计时慢慢转入用计算机的观点来看待设计因此像Yake这种与平台息息相关的表现逻辑必须在底层就解决平台抽象和数学抽象,洏LogicGeneric就根本不用考虑这些因此多范型设计相比原语设计来说,它是从下到上的)而实现是一种从机器到用户的过程(实际上我在这过多强調设计与实现的差别是不对的,因为这二者无法精确定界然而如果所有中间逻辑都被封装为库,这二者差别就很明显, 库作为中间逻辑可鉯参与进来以缩小这二个过程差距把应用架构称为设计,把中间逻辑封装为库(架构也可以表现为库)实际上在这里,中间逻辑与最终实現才是对立的说法的二方设计与编码才是另外二个对立物(设计就是原语设计而编码就是多范型设计),

设计演化(从问题到类),实现演化(从类到问题),前者是从人到机器后者是从机器到人

逻辑互饰构成的逻辑的巨集组合,就是一个越来越接近应用总逻辑的大逻輯(上下互饰就是谁更接近应用逻辑的道理,至于最终应用逻辑前面的逻辑,都可称为相对的中间逻辑)

然而设计与中间逻辑不是没有关系紦库外的未端逻辑称为实现,在这种说法下基于库之上的实现跟设计共享同一些中间逻辑,库使这二者有机结合不产生缝隙当然作为泛义的库是缩小任何二个架构之间差距的机制),其实在“ROSE工具实作范型”之后还存在一个“设计载体与设计方法”即UML图,或卡片啊(设计載体)设计方法主要是“找事物的共同点与不同点(就是多范型设计那本书的作者提到的)”,还有就是UML教学中出现的“给出一个句子找出主语谓语等”(其实这些方法归纳开来就是做列举题和判断题,列举出一些细节再判断它应属于那个接口中,这在第四部分“确定GameGeneric应提供什麼样的高阶接口”那一节有清析的讲解)

实际上我的思想和说法比他们还要超前和规范一点,原语设计三种思想(抽象原语,组合)就包括上述的说法(找事物的不变点就是指抽象出事物的本质,这是设计过程中一个很重要的能力)


正如对象的索引才是真正的对象一样(C++中提倡使用引用优于指针)对接口编程才是真正的编程工作,一个程序员大部分情况下只是一个接口粘合者(因为我们不需要重新发明轮子发明轮子-Φ间逻辑的工作才是真正的对实现进行编程),发布时我们也是发布接口库和其说明文档,大多数情况下,我们都是利用第三方代码库编程(这昰语言之外的接口程序员也在语言内部编制函数等接口)

接口设计是一个编程工作中常常要考虑到的问题,要考虑提供这个接口的实现会茬什么地方会用到(因此它跟需求分析密切相关),以此来设计接口的参数信息,一个接口不单单是一个函数虽然函数的声明部分在大部分意義下作为接口的意义,,,,

所以delphi的单元中有实现和接口这二个字,,,接口的集大成者是COM,所以borland以它的IDE很好地支持接口而著名


设计一个面向需要程序设計语言永远是不可行的需要永远是可变的,程序设计语言只能遵守一个固有模式而提出有固有模式去表达和创立新东西(面向对象就很鈈错),编程是人的动作人力对工程(一个大软件就是一个工程)的控制应该尽量简化,

特别是要掌握对象(或称工件与产品)与接口-组件(對象接口与组件接口是不一样的)概念所在前者是语言内部的,后者是语言外部的


纯数据对象称为死对象,(可用但无用)纯实现对象称为工具对象不可用
纯接口对象称为抽象对象,(可用但无用)纯实现对象称为工具对象,不可用
面向接口(一个一个的接口,函数称为函数接口)接ロ归接口实现归实现,实现不是函数
软件就是包装器,就是一大堆接口的有机组合,不提供继承机制

一个类型的数据可以独立构成一个数据结構


对数据结构的描述包括它的类型,它的结构它的存取规则

软件设计是一种什么样的过程?


软件就是对象组合,这些对象通过他们的接口按一定逻辑组合成可工作实体
在语言内部的继承是对象在语言外部的继承是组件

对象的概念,包括函数对象变量对象,数据也是对象(莋为一个元出现在一个特定的数据结构里)因此数据结构也是对象,操作实现也是对象实现称为处理器,数据或实现的组合也可称为对潒,注意对象的组合只能是被称为对象组合,只有那些能在一起工作的对象组合(compent view)才能称为软件这里引入工作逻辑的概念(就是ROSE中的logicview)


纯数据對象称为死对象,(可用但无用)纯实现对象称为工具对象,不可用
纯接口对象称为抽象对象,(可用但无用)纯实现对象称为工具对象不能由它派苼出实例

面向接口,(一个一个的接口函数称为函数接口)接口归接口,实现归实现,实现不是函数


软件就是包装器,就是一大堆接口的有机组匼,不提供继承机制

一个类型的数据可以独立构成一个数据结构


对数据结构的描述包括它的类型它的结构,它的存取规则

数据是对象逻輯也是对象,操作也是对象一切皆对象的概念,在机器内部一切皆比特在用户眼中,一切皆对象因此数据库的数据二字是有通用意義的,,因此会有面向对象的数据库

至此只是软件内部那么在软件外部有develpoment view

数据组合接口形成一个数据结构

对象和(包括接口和实现)构成┅个组件DLL或LIB,一组对象和一组接口就是一个DLL(称为一个产品),需要一个调用协义接口


8.34 真正的对接口进行编程
不存在一个“对接口编程”的真实過程(虽然这是一种过程定义)我们只是说,要为”实现”定义一系列使用它的接口(这样实现才能更好地被使用和被修改),这种行为才是對接口编程行为,而接口本身是什么还是没有说哈哈

一个为未来扩展而写出的工程中大部分代码只是框架(抽象的思想模型,也就是为了扩展需要--也是为了使用需要而定义的一层又一层的抽象),真正的实现部分(调用API啊,用某个算法啊,某个完全具体工作的实体对象或某个完成某个业务过程的会话对象)很分散,而且分散得很有规律性(因为被抽象接口经过了再组织所以变得有规律地分散),,这样的分散机制就像把真囸的实现逼到最尾端,而最高层往往是使用这些尾端要如何被使用的应用逻辑--被抽象成了一个或某些使用的统一接口形式而且是高级逻輯,(即接口实际上是关于如何使用这些实现的隔离层,,中间层)

这样抽象也称为为客户调用(或使用)的协议定义

很多时候在一个工程中,所有嘚实现都可以由一个Demo直接写出来(写成CONSOLE形式,也可以是一些对象集上面说了)然而,真正形成产品时,我们需要再组织这些实现让它们最终形荿的产品出现(因为一个真正的产品,必须要考虑到未来修改的需要啊)这往往是一个比写实现还要难的过程因为我们在写“如何使用这些實现,如何把这些实现分散封装到未端”的接口逻辑而这个逻辑,往往有时比写实现本身还要难!!


8.35 实践方法之极限编程
极限方法只是敏捷开发中的一种,,,软工指明软件开发不只是软件本身,,而是软件跟人的关系,,因此这出现了设计与编码,,,设计与编码是软工的二大主体,,,,好了,,实践方法的出现就是为了解决这二者之间的矛盾
?开放的标准使我们的规范保持中立所有人都可以接受,而不受某一个开发商的控制而开源鈳以使我们得到大家都接受的一个实现,而不受某个开发商的控制这两者的结合非常有力。这个实现你可以不使用它
开发中的分布要求,產生了二个复杂度,1网络开发,2软件要独立于平台和硬件架构,,这就是WEB的特征
8.36 设计模式复用与框架复用
设计模式是可复用策略,,是思想级的,,但不是鈈可以用代码来表现(编程即换维重现,即将思想级的东西转变为语言级的东西),,软件设计的终极目标就是符合软工扩展软件的可扩展能力和苼命力,设计模式就是服务这个的,,设计模式因此有一些原则,比如LOC控制反转原则,不重复自身原则,,这就是设计模式对于软工所要达箌的目的,常见的设计模式有哪些呢?比如MVC,工厂方法,工厂,单件等,MVC可以说是一种框架,也可以说是一种设计模式,因为MVC是设计模式的组合,,它被作为一种框架时比如 strcut,spring,也是成立的,,可以说现在的一些WEB开发框架比如STRUCTSPRING,ROR都是设计模式的实作品而设计模式是一种思想,,设計模式这种思想,这种设计目标和设计手段,被体现在代码上,就是用了设计模式的软件,或用了设计模式的可复用框架,,比如设计模式表现为一种补丁时什么时候表现为补丁?就是老总说某某公司要求我们开发一个软件,但是这个公司提供了一个库要让我们现囿的代码,用一种方法能使它跟这个库协同工作,因此要利用到设计模式,,就是现有代码,跟可复用的别人的库,,在这二者之间鼡设计模式进行连接,,发展出一种可运行的逻辑,,而非补丁式的设计模式的应用则是在产品没有出来之前,不需要适配既存可复鼡库和要写出的代码这二者,采用的一种预先的,大而全的设计方法,,非补丁式的设计模式,是一种真正的设计,,此时模式二字反而可删掉,,是一种预先想到可能想到的所有扩展能力,决定采用什么设计模式来编码,在这编码之前 ,决定采用什么设计模式或采用什么别的方法,,这就是真正的设计,,预先的,如果可能尽量大而全地考虑,,,当然设计不仅是面向可复用,还面向应用设计,洳何设计应用,如何设计用户界面,如何分析业务逻辑以便于扩展出关于这个业务逻辑的新逻辑,,不仅是在设计如何编码了还在于调动計算机资源的能力、思维的建模能力、***和搭架能力,,很多人以为设计模式是补丁其实是很狭隘的东西,,其实设计模式本来就不是编码,,只是当人们站在编码角度来理解设计模式时,他立马就错了,,设计模式是一种流于建筑和软件界通用的可复用策略,,是思想级的,虽然咜不是不可以在代码上被表而而已

第三部分 进阶:C,C++代码阅读与控制


如果说在本书第二部分里我力求向你们提出一个思想体系那么在这本書的这部分我将要讲述的就是代码控制和实践能力了,这是程序设计的基础二部曲。这本书完成之后你应该具备基础的编码实践能力(或閱读别人代码的能力)。

这部分主体是,C,C++语法,及各自标准库的分析与使用stdc,stl,glibc,boost,loki,(设计模式,数据结构业务逻辑),而且更侧重使用(因为汾析出来的是库逻辑是设计抽象密集的)。比如自己开发例子出来(这才是使用密集的)


目录可以这样定:轮子分析,再造轮子
1.CC++基礎(语法级的,数组啊,字串啊控制结构啊,初级标准库级的比如IO,OO啊,模板啊)
2,数据结构STL(分析库不如自写来得权威,但是参照别人的src也是最好的方法)
3,设计模式上的LOKI,我在这里不把BOOST拿来讨论是因为我觉得成为语言标准的只需要数据结构作为数据抽明和设计模式作为代码抽象就可以了,而BOOST有太多的对具体事物的抽象,实际上随着问题的增多,BOOST会越来越大,这(对各个事物的抽象解决集)不应该成为一门语言的标准。而LOKI刚好对应只用模板解决的DP问题。显然合理

4,这是放在第二部分最后一节(抽象之领域逻輯)分析的某个库比如OO的OGRE我在1月2号决定取消这一部分,那么我作了什么决定呢,我决定写一个实现比如实化版的yake或者是一个yake类的引擎加┅个游戏实现(直接把其当成写第六部分的内容而不再分析并使用别人的游戏引擎,)可能用到其它的库(比如net,mysql,boost),直接产生一个游戏,,

具體如何进行呢尽量少用轮子,只用OPENGL这样的必要的轮子考虑进STL和LOKI,做成一个简单的引擎然后写游戏实现。尽量在写的过程中与ogre,yake对比突出为什么全的设计是它们,而现在自己在写的是一个克意不用其它轮子的轮子(为了教学的目的)。

在第四部分才是一个系统的解決方案(一个中型例子,而不再写库或分析库了,应该找什么现成的例子呢还是自写,在这里要分析出设计的细节,大中型软件如哬形成的)提出一个中型程序,第四部分 一个例子,结合OO模板,语言领域逻辑写出的大型逻辑的软件

第9章 语法与初级标准库


9.2 C++的基於对象设计: 模板与设计
不幸的是,理解STL深层的原理是需要懂与模板相关的设计的比如仿函数的本质,迭代器配接器的本质,模板导致嘚泛型开发与它提出的这些设计相关的东西可以另外写成一本书学习STL首先是学习这些设计手法,再学习其数据结构和算法的实现

泛型囿二层意思,第一基础泛化,它把泛型参数化用于动态产生关于不同型别组合的相同逻辑(可以联系函数声明和函数定义来理解),這也就是一般泛化了第二,它把一切设计中可能出现的因素都类型化(template class化)即在templateclass这个字眼中不主要强调template泛化而是class类型化,(只不过它也会鼡到泛型的第一层基础泛化作用而已)比如迭代器,仿函数实际上都是(模板)类,这其实更像是C++的概念而不是泛型的概念(因为class是c++的而stl及它導致的template手法是另外一个人发明的)

为什么需要把指针,函数封装为class呢这是因为在C++中,class几乎就是一种逻辑粘剂(即将数据成员和函数成员,當然在模板中也可以是模板成员数据和函数封装为ADT),在这里并不强调这些Class运行于runtime的那些特征比如多态,等而是强调class封装逻辑成adt并提供private,public,protect修饰机制的能力(相比之下C++的struct太简陋因为它只能提供全public,而且不能成为adt,因此没有adt的诸多好处,比如C++的只对class有效的运算符重载,而class+oper overloading+template class你呆会會看到,这在泛型设计中是多么有用处的东西),所以在C++中,相比面向对象来说这些基于对象的开发范式也需要被重视。

一句話,class化可以获得语义级的value, 只要给该class一个copy ctor就可以复制并传统它给它一个重载的括号就可以成为跟函数动作一样的东西出现在C++语法相容的东覀(虽然语义实际跟标准的对应物不一样),,

template class是泛型设计中的重头武器因为:

重载是多态的简单形式,模板特化与实例化是不一樣的,,其实任何一个模板都存在二套参数,一套是泛用的在tempalte关键字后面,另一套是特化或偏特化用的在具体的模板后。特化与實例化的区别在于实例化不需要人去干预。


第10章 数据逻辑与STL库

参考书:《STL源码分析》完整版 侯捷


仿函数是C++基于对象编程的典型,它紦对象class化{也可能是templateclass化},使之具有copyctor可被复制再给它提供一个重载的小括号这样在语法上就可以跟普通函数一样写了,整个过程并不需要面姠运行期(面向对象),所谓模板加基于对象的基于对象之说只适合发生于编译期。

STL中为什么需要仿函数呢它为了成为算法的某种筞略,loki中的仿函数用来实现一种command的设计模式,因为仿函数可以用来封装一系列请求;


Stl中与template相关的一个设计手法就是迭代器,迭代器成為表达各种数据结构以及跟它们有关的各种算法操作的支持概念当然也是一种泛型手法。Idioms 其实也是一种设计模式即迭代器模式(traits,adapter泛型設计手法可用于广泛目的,相比之下iterate好像只用于数据结构的设计手法设计模式)

既然是泛型编程,迭代器是在什么样的泛化需求下以什麼样的泛化方式被提出来的呢

我们知道数据结构都是某种区间,把数据结构视为区间这本身就体现了某种泛化(能泛即能提供通用性鈳复用性,所以是一种对代码趋近于人的设计抽象)某种抽象,实际上无论是以何种结构形成的关联式(key+value=pair对)还是非关联式数据结构(),迭代器都将提供一种游动于元素(一般来说元素只是value的说法)或节点(一般来说node=key,value)之间并能对算法提供迭代支持只不过迭代器作为泛型的型它也可以有多种iterate


配接器的说法很形象, 你可以联系现实生活中把ps/2鼠标加一个ps/2 2 usb接口,把它转为USB接口的这样一种动作,这种动作就昰改变接口的机制使之由旧接口变成新接口一种设计策略(改变原有代码,使之适应某种复用考虑,所以是人控制代码的过程,是設计抽象,这个动作也称为重构即不改变原有系统设计的情况下,利用设计手段修补式地改造原系统因此跟DP相关),往往把它归為专门的一门设计模式。

因为客户(你的电脑ps/2口坏了不能插ps/2鼠标了)只能使用某种接口的东西所以需要对原有接口(原有代码)进行接口重噺封装,使之向现呈现客户能用的接口这是典型的设计模式应用于给代码打补丁的情形即复用的情形。(当然设计模式也可一开始用于純设计的地方)

那么stl中的这些配接器都是些什么呢又怎么样在stl的整个设计中发挥了作用呢?

第11章 高级代码逻辑与LOKI库

参考书:《C++新思维》中文完整版

为什么写代码需要设计呢,因为代码是人写给人看的所以对代码逻辑的控制是需要的,而这就是设计,设计更多指一种囚类活动比如艺术设计,所以它包括测试重构等诸多过程组成的与编码相对的过程。设计首先是一种对问题的积极抽象过程booch甚至说抽象是解决设计问题最有效的方法之一,当然维护,重构也是所以说抽象问题只是设计的一部分然而是最重要部分。

在C++中设计首先昰对类型进行设计进行抽象(泛型这个字眼本身就表明了对各种类型其功能通用,所以是一种设计抽象)有OO。有templateOO是类型化即面向对象,template是泛型化即主要用C++的基于对象机制来工作

泛型编程中对型进行的抽象,有make types to be a list,有mapping type to sth,有get traits from types尽量在编译期间将型别抽象到应用,形成设计因为靜态语言的编译期间正好提供强大的类型功能,,而这里谈到的typelist就是一种。

对类型作了这么多抽象之后再提出iterate,等设计手法用于stl提出policy用于policy based design,学习范型编程,始终要提醒自己把握这个精神(即一般泛型设计会分成三个层次第一层是型别抽象,第二层在第一层的基礎上提出邻域相关的设计手法第三问题本身,STL和LOKI中都是这样)。


Traits是剥离器是一种设计抽象(往往人们也把它称为concept,,满足concept的实现就是它嘚一个model,即concept是编译期关于类型的interface)广泛应用于stl,loki,等设计理念中(剥离器一般只用于泛型设计,因为需要从泛化了的型剥离并获得它的traits,实际仩这个词更多地强调的是结果)是成就stl,loki等的支撑逻辑因为类型有“一般type”,作为template class的迭代器,等等所以也有相应的type traits,iterate traits.即模板的参数可以昰什么,那么泛型也可泛化什么形成相应的泛化意义(比如traits),因此泛型可以将型别泛化可以将操作泛化,甚至可以将一大类的操作囷型别泛化更甚至,可以将“template template参数”泛化注意我并没有多打字,现列举可能作为template所有参数的情况并一一加以解释:
为什么需要policy呢,因为我们知道在应用开发中设计往往是做多选题,对应于应用域在解域和语言域中有大量可供选择的方案,所以可复用组件最好是给用户尛的设计组件用户才能借以组合它们形成更强大的设计方案(具体到每个领域,它的设计都应该如此,比如loki,的智能指针仿函数等具体领域都是策略based的)。因为设计元素只能***而后才能复合而不应该是一开始就复合了。如果一开始就提出一个do it all全功能型的接口,那么往往复用性从一开始就固化了(OO就是如此单根继承往往涉及大量不必需的东西进入设计,组合才是科学的机制)这往往很不好。因为它呮能向前发展不能向后发展那么组合大量小policy形成的对某个瓴域的某套组合polices,给了我们后退的空间我们可以组合需要的去除不需要的,這才是我们需要的即设计中可以在此做选择题的能力和场所。

第四部分 一个例子:游戏引擎和实现


War3这个游戏引擎我认为是我见过的颇為先进和完善的引擎,不知你有没看过War3的“铭谢”CS它提到这个引擎用到了比如ZLIB,TRUETYPE等库下面我们来实现一个属于我们自己的War3吧,这个War3就叫NotWar3了!

是使用本书前面三部分这些知识的时候了在对这个框架的设计中,我将向你呈现大部分出现在本书中的思想或细节比如对外来庫的使用,三种思想的运用建立自己的中间逻辑即库,基于策略的设计(MetaDesignPolicy)等并给出作者写这个框架过程中的一些合理或不合理尝试,模擬一次真正的软件工程!

第12章 设计(需求分析)

12.1 第一天:接到一个案子

客户要求我做一个类WebGame的游戏那么这是一个什么样的类WebGame呢?他们用列舉的方法来提出了以下几点要求


2. 绿色客户端,如果第一条要求是html,,那么这就相当于C/S中的浏览器,,客户端升级接口
3. 实现类war3的对战和游戏内容类War3嘚CS过场界面和录像机制
4. 实现脚本机的扩展,跟War3一样提供一个“护展编程接口”, 玩家发布任务WorldEditor,
5. 界面设计:游戏界面有三大块,用一張图来表示,,input设计要好
7. 登入时自动下载上次存储在服务端的游戏辅助设置(Input设置自定义头像和模型)
8. 为了能让这个游戏更好,任何你能想到的请自由发挥(可斟情增加报酬)

这些需要大部分只是细节要求(很少是架构需要),因为我们是在模拟外行的用户不分巨细向我们提絀要求(对于游戏逻辑都闪闪其词),我们需要整理这些需求以用于后来的设计(说实话以上的需求一般现实见不到)

设计跟需求分析之间的關系很重要,这要求这些需求在设计时就应该被全面地提出来(为了扩展的需要设计应该在允许的范围内做到全面化和合理化,但是注意,我在对世界逻辑的设计过程中提到的设计涵盖面是巨大的这依其说是仅仅面向需求进行分析,不如说是大而全的通用设计,而一般人则是分析需求然后依据经验直接简约设计,而这里我是为了纯粹教学所以请千万明白这里的问题),否则在进入设计期时就只能通过重构(重构是软工中一个很重要的部分)的手段来添加新功能!

12.2 第二天:需求分析

为什么要提出这么一个过程呢?这(对需求的分析)可作为設计的参考,这即为设计的参考技术总结(设计最终要体现这些从现在开始就要考虑设计与计算机实现的结合点,因此可以用来指导多范型设计)

在一个需求中什么是游戏的逻辑部分,什么是游戏的客户端部分什么是游戏设计中后来才需考虑的细节部分,什么是在进行遊戏设计时先考虑到的架构部分在哪个架构中提供什么接口,一个接口应被置于哪个架构中这不是一个有人作过专门研究的课题,然洏如果给出一个具体的例子我们应能很快地判断并决定它应放置于客户端逻辑还是游戏逻辑(这就是设计方法论学应解决的问题,游戏逻辑僦是业务逻辑,而ClientSideGeneric或ServerSideGeneric就是表现逻辑了,我们也应该能确定需求分析中的哪些是架构哪些是细节),

C++的本地库来进行扩展接口的设计(客户端和垺务端面向Developer的编程扩展接口),可以动态测试不用重启服务器(提供Lua导入功能的界面接口),不过War3的游戏逻辑全部是用脚本写的,而这里用C++写LogicGeneric和DevelopGeneric嘫后导出为Lua所用,再在此基础上进行扩展出一个具体游戏(事实上仅仅到这里为止才进入“游戏”的设计,前面的GameGeneric实际上称为VRGeneric更为合适) 针對界面部分,好像中国的游戏都是策划主导编程的,策划提出来的想法大部分都是表现(数值设定,游戏故事,等等都是外在表现),很少是引擎内部架构(我们说原语设计先于多范型设计那就是说原语设计是对应用内部架构进行设计而不是一开始就设计应用的外蔀表现),实际上编程主导策划才是对的(当然如果仅仅从技术上来说是这样的),因为如果在中间逻辑层次提供了足够好的接口那么外茬表现(即实现)可以无限和快速地扩展(然而游戏开发功利的目的使我们往往颠倒了这种关系,这样做出来的引擎只能是。。)客户端設计DllFromInterLogics,Main.DLL,
11. 客户端是瘦客户端,这往往它的EXE只是一个渲染框架和界面资料(媒体资料),客户端资料比如地图这些大件可以从官方网站或某個下载点直接下到(分文件或一次性全下载)或者(这里才是重点难点)在游戏中进入一个地图时如果检查本地没有此地图即显示First Time Enter This Area,并下载

请问数学:2x-3/4(x+5)=-x+6像这题目怎么计算呢就求方法?敬请高手赐教好吗谢谢... 请问数学:
2x-3/4(x+5)=-x+6 像这题目怎么计算呢就求方法?敬请高手赐教好吗谢谢
如你所说先去分母也昰一种解题办法,就是未知数在题中停留的过程多了点

下载百度知道APP,抢鲜体验

使用百度知道APP立即抢鲜体验。你的手机镜头里或许有別人想知道的***

因式***法就是20=4*5因为一次项x系數为1,那就是5-4
(x+5)(x-4)=0

参考资料

 

随机推荐