Note: Head First OOA&D
介绍
元认知,metacognition,关于思考的思考,教育心理学上的专有名词。管理学习和认知的过程,提高学习的效率。
让你的大脑顺从你的方法
- 慢慢来,理解越多,需要强记的就越少。
- 勤做练习,写下心得。
- 认真阅读“常问的问题”单元。
- 将阅读本书作为睡前最后一件事,或者至少当作睡前最后一件具有挑战性的事。
- 喝水,多喝水。
- 谈论它,大声谈论它。
- 倾听大脑的声音。
- 用心感受!
- 设计某些东西!
良好应用程序的基石
伟大软件的意义
- 伟大软件必须让客户满意,做客户要它做的事。
- 伟大软件是设计良好的(well-designed)、编码良好的(well-coded)并且易于维护、重用及扩展。
伟大软件的三步骤
- 确认你的软件要做客户要它做的事。
- 运用基本的OO原则来增加软件的灵活性。
- 努力实现可维护、可重用的设计。
别为了解决旧问题而产生新问题。
为正在试图解决的问题用文字描述清楚,确保你的设计与应用程序想实现的功能一致。
对象类型(object type)
- 对象应该做其名称所指之事。
- 每个对象应该代表单一概念。
- 未使用的特性是无用的赠品。
封装(encapsulation)让你将应用程序分成一组一组合乎逻辑的部件。
任何时候看到重复程序代码,就找个地方进行封装!
委托:一个对象将操作转交给另一个对象的动作,第二个对象代表第一个对象执行该操作。
OOA&D
- 当应用程序正常工作,客户是满意的。
- 当应用程序持续正常工作,客户是满意的。
- 当应用程序能够升级,客户是满意的。
- 当应用程序能够被重复利用,程序设计师是满意的。
- 当应用程序具有灵活性,程序设计师是满意的。
要点
- 脆弱的应用程序是很容易出错的。
- 你能运用像封装与委托这样的OO原则建立灵活的应用程序。
- 封装将你的应用程序分解成逻辑部件。
- 委托将处理特定工作的责任转交给另外一个对象。
- 总是通过整理出客户要什么来启动你的项目。
- 一旦完成基本功能,就重新细化你的设计,让它更灵活。
- 又了符合功能并具有灵活性的设计,便能运用设计模式进一步改善你的设计,让应用程序更容易重用。
- 找出应用程序经常改变的部分,试着将它们与其他不改变的地方分开。
- 建立运作无误但设计不良的应用程序满足了你的客户,却给自己留下痛苦以及无数个修改问题的不眠之夜。
- 面向对象分析与设计(OOA&D)提供一种产生设计良好的应用程序的方法,同时满足客户与程序设计师。
收集需求
需求:需求是单一的需要,详细说明特定产品或服务应该做的事。最常用在系统工程或软件工程的正式用语中。
It's a specific thing your system has to do to work correctly.
取得好需求的最佳方式就是了解系统应该做什么。
A use case describes what your system does to accomplish a particular customer goal.
用例:用例是捕捉新系统或软件变更的潜在需求的技术。每个用例提供一个或多个场景(scenario),传达系统如何与终端用户(end user)或其他系统交互以实现特定目标。
一个好的用例有三个基本部分
- 清楚的价值:每个用例对于系统都必须有明确的价值(clear value)。假如用例无助于客户实现目标,这个用例便没有什么价值。
- 起点与终点:每个用例都必须有明确的起点(starting point)与终点(stopping point)。某件事开始此流程,然后要有条件(condition)指明此流程已完成。
- 外部启动者:每个用例由外部启动者(external initiator)开启。有时启动者是人,有时可能是系统外的任何事物。
你的系统必须在真实世界里运作,所以要为事情出错的情况进行规划与测试。
要点
- 需求是系统为了正确运作所必须要做的事。
- 最初的需求通常来自客户。
- 为了确保你有一组好需求,你应该开发出系统的用例。
- 用例详述系统应该做什么。
- 一个用例具有单一的目标,但内含多重路径以达到此目标。
- 好的用例具有起始与终止条件、外部启动者,并且对用户而言有明确的价值。
- 一个用例就是一个系统如何运作的故事。
- 对于系统要完成的每一个目标,你至少会有一个用例。
- 在用例完成后,你可通过它精炼并增加你的需求。
- 确保所有用例皆可行的需求列表是一组好的需求。
- 你的系统必须运作在真实世界里,而不只是在你预期的情况中。
- 当事情出错时,你必须有替换路径达到系统的目标。
需求变更
需求总是在变。然而,假如有很好的用例,你通常能快速地改变你的软件以适应这些新需求。
从第一步到最后一步通过用例的完整路径称为场景。大部分的用例有一些不同的场景,但总是有相同的用户目标。
任何时候你改变了用例,你就必须回头检查你的需求。
有时候,需求的变更揭露出关于系统你所不知道的问题。变更是经常的,随着你每次的实现,系统总是随之改善。
要点
- 需求总是随项目的进行而改变。
- 当需求变更时,你的系统必须随之演进以处理新需求。
- 当你的系统需要以新的或不同的方式运作时,就从更新你的用例开始。
- 一个场景是通过用例的单一路径,从开始到结束。
- 单一用例可以有多个场景,只要每个场景都有相同的客户目标。
- 替换路径可以是只发生在某些情况下的步骤,或者是提供完全不同路径通过用例的一部分的步骤。
- 假如步骤在系统中的运作方式是选择性的,或者是提供替换路径通过系统,就是用子编号,如3.1、4.1及5.1,或者2.1.1、2.2.1及2.3.1。
- 你应该总是试着避免重复的程序代码。那是维护工作的恶梦,而且指向系统设计中的问题。
需求
- 好的需求确保你的系统如客户预期的那样运作。
- 确认需求涵盖了系统的所有用例。
- 运用用例找出客户忘了告诉你的事。
- 用例将揭露任何不完整、遗漏的需求,你可能需要将它们加到你的系统中。
- 需求总是随着时间改变(及成长)。
分析
分析帮助你确保系统运作在真实世界的情境里。
以对客户、老板及自己合理的方式编写你的用例。分析及用例让你给客户、经理和其他开发者展示系统在真实世界的情境里如何运作。
委托保护你的对象免受软件中其他对象实现改变的干扰。
查看用例里的名词(与动词)以整理出类与方法的动作叫做文本分析(textual analysis)。
好的用例以容易理解的语言,清楚且准确地解释系统在做什么。有了良好、完整的用例,文本分析是整理出系统所需类的简单且快速的方式。
注意用例里的名词,即使它们不是系统里的类。想想你确实有的类如何支持用例所描述的行为。
从一个类到另一个类的实线称为关联(association),它表示一个类与另一个类相关,通过引用(reference)、扩展(extension)、继承(inheritance)等来实现。这条线从来源类(source class)通往目标类(target class)。数字是该关联的多重性(multiplicity),表示有多少个目标类型被存储在源类的属性里。
要点
- 分析帮你确保软件在真实世界的情境里能运作,而不只是在完美的环境里。
- 用例意图被你自己、你的经理、你的客户和其他程序设计师所理解。
- 你应该以任何对你与其他观看者最有用的格式编写用例。
- 好的用例准确地描述系统做的事,但并未指出系统怎样完成这些工作。
- 每个用例应该只聚焦于一个客户目标。假如有多个目标,你就需要编写多个用例。
- 类图以很粗略的系统概述给你一个简单的方式来展示你的系统以及它的程序代码构思。
- 类图里的属性通常对应到类的成员变量。
- 类图里的操作通常代表类的方法。
- 类图漏掉许多细节,如类的构造函数、某些类型信息以及类里操作的目的。
- 文本分析帮你将用例转换成程序代码层的类、属性与操作。用例里的名词是系统的类候选者,而动词时系统的类上的方法候选者。
良好的设计=灵活的软件
抽象类是实际的实现类的占位符(placeholder)。抽象类定义行为,而子类实现该行为。
每当你在两个或两个以上的地方找到共同行为时,小心地将该行为抽取到一个类里,然后以此共同类重用这项行为。
聚合以空心菱形实线表示,表明一个类实际上拥有但可能共有(own but may share)另一个类的对象,例如作者owns论文(而且可能只是共同作者)。而合成是比聚合还要强的关系,以实心菱形实线表示,表明另一个类的对象实际上是此类本身的一部分(a part of),并且通常不与系统其他部分共有,例如摘要与正文are parts of论文(论文是不会与别的论文共用正文和摘要的,如果论文被删除,摘要与正文也会被删除)。
要看看软件是否设计良好的最佳方式之一是试着改变它。
对接口编码,而不是对实现,让你的软件更容易被扩展。通过对接口编码,你的程序代码将使用该接口的所有子类,甚至是还没被创建的那些。
设计是反复进行的(iterative)……你必须愿意改变自己的设计以及你从其他程序设计师那里所继承的设计。
注意!自尊心扼杀良好的设计。别害怕查看自己的设计决策及改善它们,即使那意味着进度倒退。
当你有一组特性跨对象变化时,使用集合(collection),像Map,来动态存储那些特性。你将从你的类中移除许多方法,并且在新特性被加入应用程序时避免改变你的程序代码。
大多数的好设计都是通过分析坏设计而来的。不要害怕犯错及改变。
A cohesive class does one thing really well and does not try to do or be something else.
内聚力,cohesion。内聚力量度单一模块、类或对象内各元素之间的连接度(degree of connectivity)。软件的内聚力越高,应用程序中每个类的责任就定义得越好且越相关(well-detined and related)。每个类就具有特定一组紧密相关的动作要执行。
分析与设计
- 设计良好的软件容易改变与扩展。
- 使用像封装与继承这样的基本OO原则来确保你的软件有灵活性。
- 如果设计没有灵活性,就改变它!别与坏设计妥协,即使那是你自己的坏设计,要改就是要改。
- 确认你的每一个类都具有内聚性:每一个类都应该聚焦在把一件事情做得很好上。
- 随着软件的设计生命周期的展开,要持续努力提高内聚力。
解决大问题
用解决小问题的相同方式解决大问题。
你可以将大问题分解成许多功能片段,接着就单独解决每个片段。
看待大问题的最佳方式就是化整为零,将它视为许多单独的功能片段(pieces of functionality)。你可以将那些片段的每一个创建为要解决的单独的问题,并且运用你已经知道的每一件事。
从客户处取得功能(feature),接着整理出实现这些功能所需要的需求。
只要可以,就尽量把细节往后拖延。
使用功能或需求列表来捕捉系统需要做的“大事”。
绘制用例图来显示你的系统是什么,无需深入不必要的细节。
领域分析让你检查你的设计,并且是以客户所用的语言。
领域分析。识别、收集、组织及表示领域相关信息的流程,根据的是现有系统与其开发历程的研究、领域专家捕捉到的知识、潜在的理论以及领域里新兴的技术。
别忘了真正的客户是谁。
领域分析帮你避免构建不属于你的责任范围内的系统部分。
OOA&D的威力
- 聆听客户。
- 确认我们理解系统。
- 为我们构建的系统画出蓝图。
- 将大问题分解成较小的功能片段。
- 运用设计模式帮我们解决较小的问题。
要点
- 看待大问题的方式是将它视为一组较小问题的集合。
- 就像在较小的项目中那样,从收集功能与需求开始进行大项目。
- 功能通常是系统做的“大”事,而且能够与“需求”一词互换使用。
- 共同性与变化性给予你在新系统与已知事物之间相互比较的观点。
- 用例是面向细节的,用例图则是比较聚焦在整体轮廓上。
- 你的用例图应该顾及系统的所有功能。
- 领域分析以客户理解的语言表示系统。
- 参与者是与系统交互但不属于系统的一部分的任何事物。
解决大问题
- 聆听客户,找出他们要你构建什么。
- 用客户理解的语言组合功能列表。
- 确认你的功能是客户真正想要的东西。
- 运用用例图(以及用例)创建系统的蓝图。
- 将大系统分解成许多较小的部分。
- 将设计模式运用到系统中较小的部分。
- 运用基本的OOA&D原则为每一个较小的部分设计程序。
架构
Architecture is your design structure, and highlights the most important parts of your app, and the relationships between those parts.
架构。架构是系统的组织结构,包含分解开来的各个部件、它们的连通性、交互机制以及你在系统设计中使用的指导原则与决策。
应用程序中真正重要的事情是架构上重要的事(architecturally significant),你应该先把焦点置于其上。
架构三问
- 它是系统本质(essence)的一部分吗?
- 这他妈的(“到底”)是什么意思?
- 我他妈的(“到底”)该如何做?
系统的本质是指在最基本的层次上系统是什么。
一次把焦点放在一个功能上,减少项目的风险。不要为无助于减少风险的功能分心。
好的设计总是会减少风险。
有时候,编写伟大程序代码的最佳方式,是在允许的情况下将程序代码的编写往后顺延。
确定某项功能的意义及如何实现
1. 询问客户 -- 该功能的意义为何? --> 2. 共同性分析 -- 如何在我的系统中实现该功能? --> 3. 实现计划
客户不为伟大程序代码付给你钱,而是为伟大软件付给你钱。
要点
- 架构帮助你将所有的图形、谋划及功能列表转化成井然有序的(well-ordered)应用程序。
- 系统中对项目最重要的功能是在架构上重要的(architecturally significant)。
- 聚焦在那些表示系统的本质、你不确定其意义为何以及不清楚首先要怎么实现的功能上。
- 在项目架构阶段,你所做的每一件事都应该减少项目的风险。
- 假如你不需要用例的所有细节,编写详述软件能如何被运用的场景可帮你快速收集好需求。
- 当你不确定某项功能是什么时,你应该询问客户,然后试着把答案归纳出来,你会对该功能取得良好的理解。
- 运用共同分析来构建具有灵活性的软件解法。
- 客户对做他们想要之事及准时交付的软件,远比对你认为程序代码写得很酷的软件更感兴趣。
设计原则
模拟是避免做傻事的最佳方式。
设计原则是能被应用到设计或编写程序代码中的工具或技术,让程序代码更可维护、更具灵活性或者更易扩展。
使用已被证实的OO设计原则形成更可维护、更具灵活性以及更易扩展的软件。
开闭原则(OCP):类应该允许为扩展而开放(open for extension),禁止为修改而关闭(close for modification)。(对扩展开放,对修改关闭。)
OCP关系到灵活性,而不只是继承。
不自我重复原则(DRY):通过将共同之物抽取出来并置于单一地方来避免重复的程序代码。
DRY关系到让系统中每一个信息与行为的片段都保存在单一、合理的地方。
单一职责原则(SRP):系统里的每一个对象应该具有单一职责,所有对象的服务都应该聚焦在实现该职责上。
当你的每一个对象都只有一个改变的理由时,你已经正确地实现单一职责原则。
Liskov替换原则(LSP):子类型(subtype)必须能够替换其基类型(base type)。
LSP完全关系到设计良好的继承。当你从一个基类继承下来时,你必须能用你的子类替换该基类且不会把事情弄糟,否则你就错误地使用了继承。
Make it Stick
Liskov所提出的关于继承的原则——继承必须确保父类型所拥有的特质(属性与方法),对子类型仍然成立,也就是说,当子类型能替换其父类型时,才算具有正确合理的继关系。
委托(delegation)是将特定工作的责任委派给另一个类或方法。
假如你需要使用另一个类的功能性,但不想改变该功能性,考虑以委托代替继承。
组合(compositon)让你使用来自一组其他类的行为,并且可以在运行时切换该行为。
在组合中,由其他行为所组成的对象拥有(own)那些行为。当对象被摧毁时,其所有行为也被摧毁。组合中的行为不存在于组合本身以外。
聚合(aggregation)是当一个类被用作另一个类的一部分时,但仍然可以存在于该类之外。
假如你喜欢委托、组合与聚合胜过继承,你的软件通常会更灵活,更易维护、扩展与重用。
要点
- 通过让类允许为扩展而开放,禁止为修改而关闭,开闭原则(OCP)让你的软件可重用且具有灵活性。
- 通过单一职责原则(SRP)让类做单一之事,甚至让运用OCP到你的程序代码中变得更简单。
- 当你在试着决定某一个方法是否为某一个类的责任时,问问你自己,做此特定之事是此类的责任吗?如果不是的话,就将此方法移到其他类去。
- 当你几乎完成OO程序代码时,务必确认不自我重复。避免重复程序代码,确保程序代码中的每一个行为只出现在单一地方。
- DRY同时适用于需求以及你的程序代码:你应该让软件中的每一项功能和需求在单一地方被实现。
- 通过要求子类型能替换其基类型,Liskov替换原则确保你正确地使用继承。
- 假如你发现程序代码违反LSP,考虑利用委托、组合或聚合来使用来自其他类的行为而无需诉诸继承。
- 假如你需要来自其他类的行为,但不需改变或修改该行为,你可以简单地委托该类去使用想要的行为。
- 组合让你从一整群行为中选择行为,常常是通过接口的一些实现。
- 当你使用组合,组合对象(composing object)拥有(own)它所使用的行为,若组合对象停止存在,这些行为也会停止存在。
- 聚合让你使用来自其他类的行为,但没有限制这些行为的生命周期。
- 即使在局和对象(aggregating object)被摧毁之后,被聚合的行为仍继续存在。
OO原则
- 将变化之物封装起来。
- 对接口编码,而不是对实现。
- 应用程序中的每一个类只有一个改变的理由。
- 类是关于行为与功能的。
- 类应该允许为扩展而开放,禁止为修改而关闭(OCP)。
- 通过将共同之物抽取出来并置于单一地方来避免重复的程序代码(DRY原则)。
- 系统里的每一个对象都应该具有单一职责,所有对象的服务都应该聚焦在实现该职责上(SRP)。
- 子类型必须能够替换其基类型(LSP)。
迭代与测试
伟大软件的编写是迭代进行的。先针对整体轮廓操作,接着迭代应用程序的每个片段,直到完成。
功能驱动开发(Feature Driven Development)挑出应用程序的特定功能,并且规划、分析及开发该功能,直到完成。
用例驱动开发(Use Case Driven Development)挑出通过用例的场景(scenario),并且编写程序代码以支持通过该用例的完整场景。
两种迭代(iterating)方式皆由良好的需求(requirement)所驱动。因为需求源自客户,两种方式都是聚焦在交付客户要的东西上。
功能驱动开发比较细粒化(granular),用例驱动开发比较“整体化”(big picture)。
你应该为所有你能想到的可能的使用状况测试你的软件。要有想象力!也别忘了测试软件不正确使用的状况。你将在早期捕捉住错误,让你的客户高兴高兴。
测试驱动开发聚焦于让类的行为正确。
设计决策总是一种取舍(tradeoff)。
良好的软件是通过迭代造就而成。分析、设计、再一次迭代,一次一次完成应用程序更小更小的部分。每当你迭代时,重新评估你的设计决策,假如它对你的设计合理,就别害怕改变。
测试案例解析
- 每个测试案例应该有ID与名称。
- 每个测试案例应该有一件特定的事要测试。
- 每个测试案例应该有你提供的输入。
- 每个测试案例应该有你预期的输出。
- 大部分的测试案例具有起始状态。
当你按契约编程(program by contract)时,你与软件的用户正同意该软件以特定方式行动。
防御性编程假设最坏的状况,并试着保护它自己(跟你)免于误用或受到坏数据的侵扰。
当你采取契约式编程时,你正在与客户的程序代码合作,以对你将如何处理有问题的状况达成协议。
当你采取防御性编程时,你正在确保客户获得“安全的”响应,不管客户要什么。
要点
- 编写良好软件的第一步是确保你的应用程序像客户预期的或想要的那样运作。
- 客户通常不在乎图表与列表,他们想要看你的软件实际在做的事情。
- 用例驱动开发一次把焦点放在应用程序用例中的一个场景上。
- 在用例驱动开发中,你一次把焦点放在单一场景上,然而在移至其他用例中的其他场景之前,你通常为单一案例中的所有场景编码。
- 功能驱动开发让你在进行任何其他事情之前为完整的功能编码。
- 在功能驱动开发中,你所完成的功能可大可小,只要你一次处理一个功能即可。
- 软件开发总是迭代的,你看见整体轮廓,接着迭代深入较小的功能性片段。
- 在开发周期的每一个阶段,你必须进行分析与设计,包括当你开始完成新功能或用例时。
- 测试让你确保软件没有缺陷,让你向客户证明软件能运作。
- 好的测试案例只测试一个特定功能性片段。
- 测试案例可能只牵涉到单一类中的一个或一些方法,或者牵涉到多个类。
- 测试驱动开发的基本想法是:先编写你的测试,再开发你的软件,通过那些测试,结果是功能完整、有效运作的软件。
- 契约式编程假设协议双方了解什么动作会产生什么行为并且遵守该契约。
- 当错误发生在契约式编程环境时,方法通常会返回null或未检查异常(unchecked exception)。
- 防御性编程寻找会出错的事,广泛地测试以避免出错的状况。
- 在防御性编程的环境里,方法通常会返回“空”(empty)对象或者抛出已检查异常(checked exception)。
开发方式
- 用例驱动开发在进行应用程序的任何其他事之前先取出系统的单一用例,并且聚焦在实现整个用例的程序代码上,包含它所有的场景。
- 功能驱动开发在进行应用程序的任何其他事之前先把焦点放在单一功能上,并且为该功能的所有行为编码。
- 测试驱动开发在为功能编码之前先为功能性片段编写测试场景,接着编写软件以通过所有测试。
- 良好软件的开发通常在开发周期的不同阶段,结合所有这些开发模型。
编程实践
- 契约式编程为你与软件用户同意遵守的软件行为建立一个共同的协议。
- 防御性编程不信任其他软件,进行广泛的错误及数据检查以确保其他软件不会给你不良的或不安全的信息。
OOA&D生命周期
- 功能列表:从高层次找出应用程序应该做什么。
- 用例图:确认应用程序要执行的大流程,以及任何牵涉到的外部力量。
- 分解问题:将应用程序分解成功能性模块(modules of functionality),接着决定以什么样的次序处理每个模块。
- 需求:为每个功能模块想出各自的需求(requirement),并且确定它们符合整体轮廓(big picture)。
- 领域分析:想出你的用例如何对应到应用程序里的对象,确认你的客户跟你有相同的认知。
- 初步设计:加入关于对象的细节,定义对象之间的关系,并且运用原则与设计模式。
- 实现:编写程序代码,进行测试,确认它有效运作。为每个行为、每项功能、每个用例、每个问题,做这些事,知道你完成。
- 交付:完成了!发布你的软件,开发票,收钱!
你的功能列表完全关系到理解你的软件应该做什么。
用例图让你开始思考你的软件将如何被使用,而不需深入一堆不必要的细节。
系统的功能是系统所做的事,而且不是总直接反映在你的用例里,用例显示系统如何被使用。功能与用例一起工作,但它们不是相同的东西。
你的设计决策应该基于你的系统如何被使用以及良好的OO原则。
你应该只将客户需要与之交互的类暴露给客户。不与客户交互的类可以在对客户端程序代码影响最小的情况下被改变。
你的职责是在确认客户得到想要的功能性与确保程序代码具有灵活性且设计良好之间取得平衡。
有时候,特定问题的最佳程序代码已经被编写过了。假如某人已经拥有有效的解法,就别硬是要自己编写。
OOA&D关系到许多选择。绝对没有唯一正确的方式来解决问题,因此拥有的选择越多,就越有机会为每个问题找到好解法。
附录1
使用继承的时机是当一个对象的行为类似于另一个对象的行为时,而不只是因为IS-A关系成立。
反设计模式是设计模式的反面:它们是问题共同的“坏”解法。这些潜藏的危险应该被识别出来并且被避免。
CRC代表类(Class)、职责(Responsibility)与协作者(Collaborator)。
缺陷密度 = 程序代码中发现的缺陷 / (程序代码总行数 / 1000)
编写具有可读性的程序代码,让程序比较好维护及重用,对你与其他开发者都一样。
重构改变程序代码的内部结构,而不影响程序代码的行为。
附录2
继承让你基于其他类来构建类,避免重复及反复出现的程序代码。
封装保护程序代码里的信息免于被不正确地使用。
封装是将类的实现隐藏起来,好让它容易使用与改变。封装让类以黑盒(black box)的方式提供服务给它的用户,但不开放该程序代码让其他人改变或者以错误的方式使用它。封装是遵循开闭原则(OCP)的关键技术。
封装:将编程元素(programming elements)包含在较大、较抽象的实体内的过程,也被称为信息隐藏(information hiding)或关注点分离(separation of concerns)。
封装将数据与应用程序的行为分离开来。于是你可以掌控每一个部分如何被应用程序的其他部分使用。
要点
- UML代表Unified Modeling Lanaguage(统一建模语言)。
- UML帮你将应用程序的结构传给其他开发者、客户与经理。
- 类图给你类的概况,包含它的变量与方法。
- 继承是一个类扩展另一个类,以重用或依赖所继承的类的行为。
- 在继承里,被继承的类称为父类;继承的类称为子类。
- 子类自动取得父类的行为。
- 子类可以覆盖父类的行为以改变方法的运作方式。
- 多态是子类“代替”其父类。
- 多态让你的应用程序更有灵活性、更容易改变。
- 封装是将程序的一部分隐藏起来,与程序的其余部分分开来。
- 封装最简单的形式是让类的成员变成private,并且只通过类上的方法暴露该信息。
- 你也可以封装一群数据,甚至行为,控制它们如何被访问。
词汇
继承 inheritance
多态 polymorphism
封装 encapsulation
循环遍历 loop through
主要路径 main path
替换路径 alternate path
可选路径 optional path
聚合 aggregation
合成 composition
泛化 generalization
复原力 resilient
耦合度 coupling
低耦合 loosely coupled
内聚力 cohesion
内聚性 cohesive
高内聚 highly cohesive
同级评审 peer review
双封装 double-encapsulation
更容易变更 Ease-of-Change
交互依赖 interdependent
整体轮廓 big picture
共同性 commonality
变化性 variability
外挂包 add-on pack
用例图 use case diagram
蓝图 blueprint
领域分析 domain analysis
开闭原则 OCP, Open-Closed Principle
不自我重复原则 DRY, Don't Repeat Yourself Principle
单一职责原则 SRP, Single Responsibility Principle
Liskov替换原则 LSP, Liskov Substitution Principle
组合对象 composing/composite object
主要对象 main object
被组合对象 composed object
功能驱动开发 Feature Driven Development
用例驱动开发 Use Case Driven Development
分析瘫痪 analysis paralysis
原子性 atomic
初步设计 prelimiary design
现成可用的代码 ready-bake code
反设计模式 anti-pattern
度量 metrics
抽象化度量 abstraction metric
顺序图 sequence diagram
生命线 liftline
状态机图 state machine diagram
警戒表达式 guard expression