《面向对象分析与设计》读书笔记

        1、复杂系统不仅仅是层次化的,而且这种层次化也代表了不同的抽象级别,一层构建于另一层之上,每一层都可以分开理解。在每一层都可以发现一组设备,相互协作,为更高的抽象层提供服务。

        2、同一层抽象中的所有部分之间,以某种定义良好的方式进行交互。在不同抽象层的不同部分之间,存在着清晰的关注点分离。

        3、复杂系统存在着5个共同属性:1)层次结构:许多复杂系统都有几乎可分解的层次结构,所有系统都有子系统,所有系统都是更大系统的组成部分;2)相对本原;3)关注点分离:组件内的联系通常比组件间的联系更强,这一事实实际上将组件中高频率的动作(涉及组件的内部结构)和低频率的动作(涉及组件间的相互作用)分离开来,组件内部作用和组件间作用的差异,让我们在系统的不同部分之间实现“关注点分离”,让我们能够以相对隔离的方式来研究每个部分;4)共同模式:层次式结构通常只是由少数不同类型的子系统,按照不同的组合和安排方式构成,换而言之,复杂 系统具有共同的模式,这些模式可能涉及小组件的复用;5)稳定的中间件形式:复杂的系统趋向于随时间而演变,准确的说,如果存在稳定的中间形式,从简单系统到复杂系统的演变将更快。随着系统的演变,曾经认为是复杂的对象就变成了基础对象,在这些基础对象上构建更为复杂的系统。而且永远也不能够第一次就正确打造出这些基础对象,必须在上下文环境中使用它们,然后随着时间推移不断改进他们,因为我们对系统的真是行为了解的越来越多。

        4、控制复杂性的技巧——分而治之。在设计一个复杂系统时,重要的是将它分解为一些小而又小的部分,然后可以独立地处理每个部分。通过这种方式,我们适应了人类认知时的渠道能力局限:要理解某一层次的系统,只需要一次理解几个部分(而非所有部分)。通过分割系统的状态空间,聪明的分解直接解决软件系统内在的复杂性。分解方式包括:算法分解、面向对象的分解。

        5、面向对象分析的底层概念是设计者应该将系统建模为一组协作的对象,将单个对象作为类的实例,而类之间具有层次关系。·面向对象分解通过复用共同的机制,得到一些较小的系统,从而提供了重要的表达经济性。面向对象系统在应对变化时也更有弹性,从而更能随着时间演变,因为它们的设计是基于稳定的中间状态的。实际上,面向对象分解极大地降低了构建复杂软件系统的风险,因为它们的思路是从我们有信心的、较小的系统开始增量式地演进。而且,通过帮助我们明智地决定对巨大的状态空间进行关注点分离,面向对象的分解直接关注了软件的内在复杂性。

        6、抽象的作用:抽象是人类处理复杂性的基本方式,抽象来自对真实世界中特定对象、场景或者处理的相似性的认知,并决定关注这些相似性而忽略不同之处如果不能够全面掌握一个复杂的对象,我们就选择忽略非本质的细节,转而处理这个对象的一般化的、理想化的模型。虽然我们受到同时可以理解的事物数量的限制,但是通过抽象,我们利用了信息的分块和不断增大的语义内容。采用面向对象的观点来看世界时,尤其是这样,因为对象作为真实世界中实体的抽象,代表了特定的一块密集而内聚的信息。

        7、另一种增加单块信息的语义内容的方法,是在复杂的软件系统中显示地组织类和对象层次结构。对象结构很重要,因为它展示了不同的对象之间如何通过一些交互模式进行协作,我们把这些交互模式称为“机制”。类结构也很重要,因为它强调了系统中的公共结构行为。虽然我们把一类对象的每个实例作为不同的实体,但是我们可以假定同类对象的所有其他实例都具有同样的行为,通过将对象分成具有相关抽象的组,我们明确地区分了不同对象的共同属性和特有属性,这又进一步帮助我们掌握它们内内在的复杂性。每个对象都可能拥有大量复杂的行为,但是当我们整理出这些层次结构之后,复杂系统的结构以及我们对它的理解都得到了极大的简化。

         8、对于非常复杂的系统,我们发现类、对象和模块提供了基本的抽象手段,但这不够。幸运的是,对象模型在规模上可以扩展。大型系统中,一组抽象可以构建在另一组抽象之上。在任何一个抽象层上,都可以找到某些有意义的对象,它们可以协作实现更高层的行为

        9、当且仅当一种语言满足下列需求时,它才是面向对象的:1)它支持对象,这些对象是具有命名的操作接口和隐藏的内部状态的数据抽象;2)对象有相关的类型(类);3)类型可以从超类中继承属性。

        10、面向对象设计导致了面向对象分解,面向对象设计使用不同的表示法,来表达系统逻辑设计(类和对象结构)和物理设计(模块和处理架构)的不同模型,以及系统的静态和动态特征。

        11、面向对象分析是一种分析方法,这种分析方法利用从问题域的词汇表中找到的类和对象来分析需求。基本上,面向对象分析的结果可以作为开始面向对象设计的模型,面向对象设计的结果可以作为蓝图,利用面向对象编程方法最终实现一个系统。

        12、对象模型的4个主要要素:抽象、封装、模块化和层次结构。

        13、抽象的定义:抽象描述了一个对象的基本特征,可以将这个对象与所有其他类型的对象区分开来,因此提供了清晰定义的概念边界,它与观察者的视角有关。抽象关注一个对象的外部视图,所以可以用来分离对象的基本行为和它的实现。对象的接口只提供它的基本行为,此外别无其他。抽象捕捉了某个对象的全部行为,不多也不少,并且不提供对象之外的惊奇效果或副作用。抽象的核心是不变性的概念。对象的抽象应该优先于它的实现决定。当选择了一种实现之后,它就应该作为这种抽象后面的秘密,对绝大多数客户隐藏

        14、从那些准确地为问题域实体建模的对象到那些实际上没有什么理由存在的对象,存着一些列的抽象。按照最有用到最没用的次序,这些抽象分别为:1)实体抽象,一个对象代表了问题或解决方案域实体的一个有用的模型;2)动作抽象:一个对象,提供了一组通用的操作,所有这些操作都执行同类的功能;3)虚拟机抽象:一个对象,集中了某种高层控制要用到的所有操作,或者这些操作将利用某种更低层的操作集;3)偶然抽象:一个对象,封装了一组相互间没有关系的操作。我们追求的是构建实体抽象,因为它们直接对应着给定问题域的词汇。

        15、所有的抽象都有静态和动态的属性。动态属性和对象的生命周期有关。我们可以有意义地执行一个对象上的哪些操作以及该对象如何反应,构成了这个对象的全部行为。

        16、没有对象是孤立的,每个对象都与其他对象协作,实现某些行为。这些对象之间如何协作的设计决策,定义了每种抽象的边界,从而也定义了每个对象的职责和协议。对象的抽象应该优先于它的实现决定。当选择了一种实现之后,它就应该作为这种抽象后面的秘密,对绝大多数客户隐藏。

        17、抽象和封装是互补的概念:抽象关注的是对象可以观察到的行为,而封装关注这种行为的实现。封装通常是通过信息隐藏(不只是数据隐藏)来实现的。信息隐藏是将那些不涉及对象本质特征的秘密都隐藏起来的过程。通常,对象的结构是隐藏的,其实现方法也是隐藏的。“复杂系统的每一部分都不应该依赖于其他部分的内部细节”。“抽象帮助人们思考他们做什么”,而封装“让程序员可以借助最少的工作进行可靠的修改”。封装在不同的抽象之间提供了明确地边界,因此导致了清晰的关注点分离。封装的定义如下:封装是一个过程,它分隔构成抽象的结构和行为的元素,封装的作用是分离抽象的概念接口及其实现

        18、要让抽象能工作,必须将实现封装起来。在实践中,这意味每个类必须有两个部分:一个接口和一个实现。类的接口描述了它的外部视图,包含了这个类所有实例的共同行为的抽象。类的实现包括了抽象的表示以及实现期望行为的机制。通过类的接口,我们可能知道客户可以对这个类的所有实例做出哪些假定。实现封装了细节,客户不能对这些细节做出任何假定。抽象让我们既能改变表示方法,同时又不影响客户(使用类的程序员),这就是封装的根本好处

        19、模块化是一个系统的属性,这个系统被分解为一组高内聚、低耦合的模块。因此抽象、封装和模块化的原则是相辅相成的。一个对象围绕单一的抽象提供了一个明确的边界,封装和模块化都围绕着这种抽象提供了屏障。模块之间的联系是模块相互之间所做出的决定。模块作为一种容器,我们在其中神明逻辑设计中的类和对象。我们需要努力创造出高内聚(将逻辑上相关的抽象放在一起)、低耦合(减少模块之间的依赖关系)的模块

        20、发现正确的类和对象,然后将它们放到不同的模块中,这基本上是独立的设计决定。类和对象的确定是系统逻辑设计的一部分,而模块的设计系统物理设计的一部分。我们不能在物理设计之前完成所有逻辑设计,反之亦然,设计决策事宜一种迭代的方式进行的。

        21、通过隐藏抽象的内部视图,封装有助于管理系统的复杂性,但是这还不够。一组抽象常常构成一个层次结构,通过在设计中确定这些层次结构,可极大地简化对系统的理解。层次结构是抽象的一种分级或者排序。复杂系统中,最重要的两种层次结构是它的类结构(“是一种”层次结构)和对象结构("组成部分"层次结构")。当发展继承层次结构时,不同类中共同的结构和行为会被迁移到共同的超类中,这就是常把继承称为一般/特殊层次结构的原因。超类代表了一般化的抽象,子类代表了特殊的抽象,会添加、修改甚至隐藏来自超类的属性和方法,通过这种方式,继承让我们以一种经济的方式表达我们的抽象。实际上,忽略“是一种”层次结构将会导致膨胀的、不优雅的设计。

        22、在抽象、封装和层次关系之间存在一种健康的压力。“数据抽象试图提供一个透明的边界,在这个边界之后,方法和状态是隐藏的。继承要求将这个接口开放到一定程度,允许不通过抽象来访问状态和方法”。对于某一个类,通常有两种客户:调用该类实例的方法以及从这个类 继承的子类。对于“是一种”层次结构,高层的抽象是一般的,底层的抽象是具体的。对于“组成部分”层次结构,一个类相对于组成它的实现的类来说,处于更高的层次。类型是关于一个对象的类的强制规定,这样一来,不同类型的对象不能够互换使用,或者至少它们的互换使用收到非常严格的限制。强类型使得可以利用编程语言来执行某些设计决策,这样当我们的系统复杂度增长时,仍能保持特定的关联。

        23、类型的静态与动态指的是名字与类型绑定的时间。静态类型(也被称为静态绑定或者早早起绑定)意味着所有变量和表达式的类型在编译时就固定了,动态类型也被成为迟后绑定,意味着所有变量和表达式的值直到运行时刻才知道。多态是动态类型和继承相互作用时出现的一种情况。多态代表了类型理论中一个概念,即一个名字(如一个变量声明)可以代表许多不同类型的对象,这些类具有某个共同的超类,这个名字代表的对因此可以响应一组共同的操作。

        24、并发是一种属性,它区分了主动对象和非主动对象。持久是对象的一种属性,利用这种属性,对象跨越时间和空间而存在

        25、封装是一个过程,它被分隔构成抽象的结构和行为的元素,封装的作用是分离抽象的概念接口极其实现。

        26、一个对象反映了某一部分的真实存在,因此它是在时间和空间中存在的某种东西。一个对象代表了单个可识别的项、单元或者实体,它可以是真实的,也可以是抽象的,在问题领域中承担定义良好的角色。结构和行为类似的对象定义在它们共同的类中。对象的状态包括这个对象的所有属性(通常是静态的)以及每个属性当前的值(通常是动态的)。属性通常是静态的,因为这样的特征是不可更改的,是对象的根本本质。说“通常是静态的”是因为在某些情况下,对象的属性会改变。对象是“有存在时间的、可以变化的、有状态的、可以实例化的的、可以被创建、销毁和共享的”。系统中所有的对象都封装了某种状态,系统中所有的状态都由对象所封装。封装一个对象的状态只是开始,这并不足以让我们刻画出在开发过程中发现的这种抽象的全部含义。

        27、行为是对象在状态改变和消息传递方面的动作和反映的方式。一个操作是某种动作,一个对象对另一个对象执行这个操作,目的是获得反应。一般来说,一个消息就是一个对象执行了另一个对象的操作,虽然底层的分发机制是不一样的。消息传递只是定义对象行为的一个方面,对象的行为还会受其状态的影响。一个对象的行为是它的状态以及施加在它上面的操作的函数。一个对象的状态代表了它的行为的累积效果

        28、一个对象的所有方法共同构成了它的协议。因此一个对象的协议定义了对象允许的行为的封装,构成了这个对象完整的静态视图和动态视图。对于大多数有用的抽象来说,将这个较大的协议分成逻辑上的行为分组是有意义的。对象中存在状态,这意味这操作调用的次序非常重要。从而导致了这样一种思想:即每个对象就像一个微小的、独立的自动机。主动对象有自己的控制线程,而被动对象则没有。主动对象通常是自动地,这意味着它们不需要由其他对象操作就能表现出一些行为。而对于被动对象来说,只有当显示地操作它时,才会发生状态变化。从这个角度来看,我们系统中的主动对象是控制的中心。如果系统包含多个控制线程,通常会有多个主动对象。

        29、一个对象本身是无趣的,对象通过与其他对象协作,为系统的行为做出贡献。当一个对象通过链接向另一个对象发送一条消息时,这两个对象就称为同步了。在完全串行的应用中,这种同步通常是通过简单的方法调用来完成的。但是存在多线程控制的情况下,对象需要更复杂的消息传递机制来处理并发系统中可能会出现的互斥问题。链接表明了一种端到端的关系或者客户/服务提供者的关系,而聚合则表明了一种整体/部分层次结构,提供了从整体导航到它的部分的能力。

        30、对象是存在于空间和时间中的具体实体,而类仅代表一种抽象 ,即一个对象的“本质”。类是一组对象,它们拥有共同的结构、共同的行为和共同的语义。一个对象就是一个类的实例。需要注意的是,类对于分解是必要的但不是充分的。某些抽象非常复杂,所以不能够利用单个类定义的方式很好的表达。相反,最好是将这些抽象表示为一组类,这些类的实例相互协作,提供我们所期望的结构和功能。编程在很大程度上是一种“制定契约”:一个较大问题的不同功能通过子契约被分配给不同的设计元素,从而被分解成较小的问题。

        31、一个单独的对象是一个具体的实体,在整个系统中扮演某个角色,而类则记录了所有相关对象的共同结构和行为。因此,类起到的作用是在一种抽象和它所有的客户之间建立起协议。编程即契约的观点可以区分一个类的外部视图和内部视图。一个类的接口提供了它的外部视图,因此强调了抽象、隐藏了它的结构和行为的秘密。这个接口主要由所有的操作声明构成,这些操作适用于这个类的所有对象。与接口不同,类的实现是它的内部视图,它包含类行为的秘密。一个类的实现主要由类接口中定义的所有操作的实现构成。与对象一样,类也不是孤立存在的。对于一个特定的问题域,一些关键的抽象通常与各种有趣的方式联系在一起,形成了我们设计的类结构。

        32、存在三种基本类型的类关系:1)一般/特殊关系,表示“是一种”关系;2)整体/部分,表示“组成部分”关系;3)关联关系,表示某种语义上的依赖关系,如果没有这层关系,这些类就毫无关系了。关联关系是最常见也是语义上最弱的。确定类之间的关联通常是分析和早期设计的活动。随着继续设计和实现,我们通常会细化这些较弱的关联,将它们变成某种更具体的类关系。抽象类在编写时就会预期它的子类会添加结构和行为,通常是完成它未完成的方法实现。

        33、多态是类型理论中的一个概念,即一个名字可能代表许多不同类的实例,只要它们都有共同的超类。于是由这个名字所代表的对象就能够以不同的方式对同一组操作做出反应。利用多态,一个操作可以被层次结构中的类似不同的方式实现。通过这种方式,子类可以扩展超类的能力或者覆写父类的操作。多态和延迟绑定是分不开的,再出现多态时,方法和名字的绑定要在执行时确定。在C++中,开发者可以控制成员函数使用早期绑定或者延迟绑定。具体来说,如果方法被声明为virtual的,那就是用延迟绑定,这个函数就会被认为是多态的;如果没有声明为Virtual,那么这个函数就使用早期绑定,可以在编译时解析

        34、在分析和设计的早期阶段,开发者有两项主要任务:1)从问题域的词汇表中确定出类;2)创建一些结构,让多组对象一起工作,提供满足问题需求的行为。我们将这样的类和对象统称为问题的“关键抽象”,把这些协作结构称为实现的“机制”。系统应该利用一组最少的不会变化的部分进行构建,这些部分应该尽可能地通用,系统的所有部分应该被放入一个统一的框架。对于面向对象开发来说,这些部分就是构成系统关键抽象的类和对象,这个框架由系统的机制来提供。

        35、如果模块与其他模块高度相关,他就难以独立地被理解、变化或者修正。通过系统设计,使模块间的耦合将至最弱,可以降低复杂性。然而,在耦合和继承的概念之间存在着矛盾关系,因为继承引入了严重的耦合。一方面我们希望类之间的弱耦合,另一方面,继承(超类和子类之间的强耦合)又能帮助我们处理抽象之间的共性

        36、最不希望出现的内聚就是偶然性内聚,即将完全无关的抽象塞进同一个类或者模块中。最希望出现的内聚就是功能性内聚,即一个类或模式的各个元素一同工作,提供某种清晰界定的行为。与耦合和内聚的概念相关,一个类或模块应该是充分的、完整的、简单的。所谓充分,指的是类或者模块应该记录某个抽象足够多的特征,从而允许有意义的、有效的交互,否则将使该组件无用。所谓完整,指的是类或者模块的接口记录了某个抽象全部有意义的特征。充分性意味着最小的接口,但是一个完整的接口就意味着该接口包含了某个抽象的所有方向。因此完整的类或模块是足够通用的,可以被任何客户使用。打造类或模块的接口是艰苦的工作。通常我们先尝试设计类,然后,当我们和其他人创建客户时,我们发现需要扩展、修改并进一步精化这个接口。最后,我们可能发现一些操作的模式或抽象的模式,导致我们创建一些新的类或重新组织已有类之间的关系。

        37、在面向对象开发中,通常会整体设计一个类的所有方法,因为这些方法共同构成了这个抽象的完整协议。

        38、只有当B的每个实例都可以被看做是A的实例时,才适合继承。当B的每个实例只是具有A的一个或者多个属性时,适合使用客户关系。从另一个角度来看,如果对象的行为超过了它的部分之和,在相关的类之间创建聚合关系而不是继承关系可能更好。

        39、对象的状态包括对象的所有属性(通常是静态的)加上这些属性当前的值(通常是动态的)。行为是对象在状态改变和消息传递方面的动作和反应

        40、通过发现,我们逐渐从问题域的词汇表中识别出关键抽象和机制。通过发明,我们设计出泛华的抽象和一些新的机制,规定对象协作的方式。归根到底,发现和发明都是分类问题,而分类基本上是发现共性的问题。当进行分类时,我们寻找具有共同结构或表现出共同行为的一组事物。分类可以帮助我们确定类之间的泛华、特化、聚合等层次结构通过识别对象交互中的共同模式,我们逐渐发明出一些机制,成为实现的核心

        41、分组是组织知识的手段。在面向对象设计中,认识到事物间的相似性让我们能够将共性放在关键抽象机制中,最终导致更小的应用和更简单的架构。在设计复杂软件系统时,分类的增量式、迭代式本质直接影响了类和对象的层次结构。

        42、经典分类法利用相关的属性作为对象间相似性的判据。具体来说,人们可以根据某一属性是否存在将对象划分到没有交集的集合中。最有用的属性集合是其成员没有太多相互影响的集合。一般来说,属性可以不只表示可以测量的特征,也可以包含观察到的行为。

        43、分析和设计之间的边界是模糊的,但是每种活动关注的重点是不同的。在分析时,关注的重点是分析面临的问题域,从问题域的词汇表中发现类和对象,实现对真实世界的建模。在设计时,我们在模型中发明一些抽象和机制,为要构建的解决方案提供设计

        44、职责代表的是对象维护的知识和可以执行的动作,其意义在于表达一个对象的目的以及它在系统中的位置。对象的职责是针对它支持的所有契约而提供的全部服务。在这种方式中我们将具有共同职责的事物划分为一组,让超类包含一般的职责,让子类包含特殊的行为,从而构成类的层次结构。

        45、领域分析试图确定在某个领域中所有应用都通用的类和对象。如果在设计中对于已存在的关键抽象有点疑惑,领域分析师可以提供帮助,指出这些关键抽象在其他系统中已证明有用。领域分析效果挺好,因为除了极特殊的情况外,软件系统很少有真正独特的需求。领域分析被定义为“确定对象、操作和关系的尝试,领域专家认为这些对象、操作和关系对这个领域很重要”。领域分析的步骤如下:1)咨询领域专家,构建一个通用的模型草稿;2)检查领域中原有的系统,以一种通用的格式展示出这方面的理解;3)咨询领域专家,确定系统间的相似和差异;4)细化通用模型,以包含原有的系统。通常领域专家就是一个用户,领域专家通常不会是一名软件开发者,更常见的情况是,他只是非常熟悉某个问题的方方面面。

        46、简单来说,我们可以在需求分析时就应用用例分析。此时,最终用户、其他领域专家和开发团队列出系统操作的基本场景(不要在一开始就细化这些场景,只要列出它们就行了)。这些场景共同描述了这个应用的系统功能。分析随后研究每个场景,可能使用与影视行业做法类似的故事板技术。分析团队分析每个场景时,必须确定参与该场景的对象、每个对象的职责以及这些对象与其他对象协作的方式,即每个对象调用其他对象的操作。通过这种方式,分析团队被迫在所有抽象之间形成清晰的关注点分离

        47、关键抽象是一个类或对象,它是问题域词汇表的一部分。确定这样的抽象的主要价值在于,它们给出了问题的边界,突出了系统中的事物(这些事物与设计相关),同时排除了系统之外的事物(这些事物是不必要的)。 确定关键抽象包含两个过程:发现和发明。通过发现过程,我们意识到领域专家所使用的抽象(如果领域专家提及他,那么这个抽象通常很重要);通过发明过程,我们创造了新的类和对象,它们不一定是问题域的组成部分,但在设计或实现中也很重要。

        48、关键抽象反映了问题域的抽象,而机制是设计的灵魂。在设计过程中,开发者不仅必须考虑单个类的设计,还需要考虑这些类的实例如何一起工作。机制是对象协作提供某些高层行为的方式。当开发者决定采用某种协作模式之后,工作会被分解到许多对象上,即在相应的类上定义适当的方法。归根到底,单个类的协议包含了实现所有行为以及实现与其实例相关的所有机制所需要的全部操作。机制实际上是我们在构造良好的软件系统中发现的各种模式,机制代表了一种层次的复用,它高于单个类的复用。同时,机制也代表了战略上的决策,考虑的是许多不同类型的对象的协作活动

        49、系统的复杂性既来自于系统中元素的数量和组织(即结构),也来自于这些元素协作完成其功能的方式(即行为)。

        50、概念模型记录了系统中存在(或者即将存在)的领域实体以及它们与系统其他领域实体的关系。概念层的建模是利用业务领域的术语完成的,应当是技术无关的。系统的逻辑视图利用了概念模型中创造的概念,建立起关键抽象和机制的意义,并确定系统的架构和整体设计。系统的物理模型描述了系统实现的具体软件和硬件构成,显然,物理模式是技术相关的。对于某个项目而言,随着时间推移,系统的设计将从概念成熟发展到逻辑成熟,最后到物理成熟。

        51、依赖关系显示了一个元素依赖于另一个元素来实现它在系统中的职责,依赖关系是使用一个虚线的开放箭头来表示的。箭头尾部位于使用者,头部位于依赖的提供者。关联关系体现了“组成部分”关系,它是一般的关联关系的一种约束形式其他三个基本类关系(泛化、聚合和组合)是对一般关联图标的精化。实际上在开发过程中,这正是关系演变的一种趋势。我们先断定两个类之间存在语义上的联系,然后随着具体地确定它们之间联系的实质,常常会将关联精华为泛化、聚合和组合关系。泛化图标表示一种泛化/特化关系(即“是一种”关系),表现为带有封闭箭头的关联。箭头指向超类,关联的另一端是子类。聚合图标表明一种整体/部分层次结构,也意味着能够从聚合体导航到它的部分。聚合关系表现为一个空心菱形的关联,菱形所在一端是聚合体(整体),另一端代表它的实例构成了聚合对象的部分,但这种整体/部分的层次关系并不意味着物理上的包容(即生命周期不一致)。组合图标表示一种包容关系,表现为一个带有实心菱形的关联,菱形所在一端是整体。组合关系中,部分在整体之外没有意义,整体拥有部分,部分的生命周期与整体是一样的

        52、类属性的可见性:1)公有可见性(+) 对能看到这个类的任何元素都可见;2)保护可见性(#) 对这个类及其子类的其他元素可见;3)私有可见性(-) 对这个类的其他元素可见;3)包可见性(~) 对同一个包中的其他元素可见。

        53、同步消息(通常是一次调用操作)显示为一条带实心箭头的实现,异步消息是一条带开放箭头的实线。返回消息是一条带开放箭头的虚线。

        54、组件代表了一块可复用的软件,它提供了某种有意义的功能集。从最低的层面上来说,组件是一组类,它们本身是内聚的,与其他类的耦合相对比较松散。系统中的每个类要么处于一个组件中,要么处于系统的顶层。组件也可以包含其他组件。组件是一种结构化的分类器,组件间的协作和内部结构可以利用组件图来表示。组件与组件之间通过定义良好的接口进行协作,从而提供系统的功能。组件图可以分层地结构一个系统并表示它的逻辑架构。

        55、节点是一种计算资源,通常包含存储和处理能力,工件部署在它上面执行。节点可以包含其他节点,以表示复杂的执行能力。节点之间会通过消息和信号进行通信。

        56、用例代表了执行者希望系统为他们做什么,用例是通过某部分功能来使用系统的一种具体方式,因此用例是相关事务的一个具体序列,执行者和系统以对话的方式执行这些事务,从用户的观点来看,每个用例都是系统中一个完整序列的事件。用例图是建模系统行为(功能)的建模工具,表现了一组用例、参与者以及他们之间关系的图从用户的角度来看,用例图表达了参与者使用系统的一种方式,从系统设计的角度来看,一个用例图规约了系统可以执行的一个动作序列,即一个用例图捕获了参与交互的各方关于其行为的一个约定任意一个系统均有其内部的事物和外部的事物,用例图就是用来划分系统内部事物和系统外部事物的一种图

        57、用例图描述了待建系统的上下文环境和系统提供的功能,用例图描述了谁(或什么)与系统进行交互,它们展示了外部世界希望系统做些什么。活动图提供了活动流程的可视化,可以从系统、业务、工作流或者其他过程的角度进行描述。序列图跟踪了场景的执行,与对象图的上下文背景是一样的。很大程度上,序列图就是对象图的另一种表示。

        58、软件密集系统架构描述的推荐实践将架构定义为“系统的基本组织结构,包括它的组件、组件之间的相互关系、环境以及设计和演进的指导原则”。在某种程度上,系统的架构基本上与系统的最终用户无关。但是对于构建可理解、可扩展、可重新组织、可维护和可测试的系统来说,拥有“清晰的内部结构”是很关键的。只有对系统的架构有清晰的感觉,才可能发现共同的抽象和机制。研究这种共性最终使得系统的构建变得更简单,从而使系统更小、更可靠。好的软件架构通常具有一些以下特性:1)它们有定义良好的抽象层构成,每个层代表了一种内聚的抽象,提供了定义良好的、受控的接口,并且建立在同样定义良好的、受控的低层抽象设施之上;2)在每一个的接口和实现之间有清晰的分离关注,让我们能够改变一个低层的实现而不会破坏它的客户对它的假定;3)架构很简单:共同的行为是通过共同的抽象和共同的机制来实现的。

        59、宏观过程是总体的软件开发生命周期,它是微观过程的控制框架,代表了整个开发团队的活动。宏观过程的目的是知道系统的整体开发,最终得到产品系统,宏观过程的范围从确定想法开始,直到实现该想法的第一个软件系统版本为止。宏观过程包括下列科目,按照相对次序来执行:1)需求,对于系统该做什么,建立并保持与客户和其他涉众的一致意见,定义系统的边界(划定界限);2)分析与设计:将需求转化为系统设计,设计将作为在特定实现环境中进行实现的规格说明,这包括逐渐形成尔一个健壮的系统架构,建立起系统不同元素必须用到的共同机制;3)实现,实现、单元测试以及对设计进行集成,得到一个可执行的系统;4)测试,对实现进行测试,确保它实现了需求(即需求得到了正确地实现),通过具体的展示来验证软件产品是否像设计的那样工作;5)部署,确保软件产品(包括已测试的实现)能被它的最终用户使用。

        60、微观过程——分析与设计过程,分析与设计过程是在整体软件开发过程的背景下进行的,宏观过程驱动了微观过程的范围,为微观过程提供了输入,并利用了微观过程的输出。具体来说,微观过程使用了宏观过程提供的需求(以及前面微观过程迭代得到的分析和设计规格说明),产生了设计规格说明(最显著的是架构),然后在宏观过程中实现、测试并部署。

        61、在微观过程中,传统的分析阶段和设计阶段被有意地模糊了,取而代之的是进行不同层次的抽象。分析利用系统需求作为输入,得到能够具体实现的规格说明。如果分析准确的展现了需求并且是一致的,能够很好的作为设计基础,那么我们就认为分析已经完成了。如果设计已经足够详细,能够就行实现和测试,那么我们就认为设计已经完成了。分析的目的是提供对问题的描述,这种描述必须完整、一致、可读,并可以让不同的感兴趣的团体进行复查,可以针对实现进行测试。

        61、分析关注的是行为而不是形式。在分析时尝试对世界进行建模,从问题域的词汇表来确定元素并描述它们的角色、责任和协作,在分析过程中,追求表示或者实现问题是不恰当的。分析必须说明系统做什么而不是系统如何做。只有出于暴露系统的行为的目的,而不是作为可测试的设计需求,在系统分析时有意说明“如何做”才是有用的,分析就是要更好的理解待解决的问题

        62、在开发架构时需要理解分离关注,同时在分析和设计时理解单个的组件。架构主要考虑的是系统各个部分(即组件)之间的关系,以及它们的责任、接口和协作。相反,系统组件的分析和设计关注的是这些组件的内部以及它们如何满足需求,这些需求是架构的分析和设计要求组件实现的在整个开发生命周期,分析与设计是在不同的抽象层次上完成的,抽象层次的数目不能够事先确定,这主要依赖于系统的规模。

        63、微观过程针对一个具体的范围和一个具体层次的抽象来执行,它包括以下活动:1)确定元素,发现(或发明)要处理的元素,确定面向对象的分解;2)确定元素间的协作,描述已确定的元素之间如何协作已提供系统的行为需求;3)确定元素间的关系,以支持系统的协作;4)确定元素的语义,建立已确定的元素的行为和属性,为下一层次的抽象准备元素。虽然这些活动看起来是顺序执行的,但实际上它们却是并行执行的。

        64、在对系统进行面向对象分解时,识别元素是一项关键活动,这些元素将在特定的抽象层次上描述解决方案。这项活动实际上是元素从一个抽象层向另一个抽象层的演化,在一个抽象层次上确定元素也包括了对前一个层次进行修改,这种修改将导致产生新的元素和不同的元素。在一个层次上识别的元素将作为主要输入,用于确定下一个抽象层次上的元素。在执行这项活动时,重要的是在确定元素和细化语义之间保持一种微妙的平衡,确定元素应该只关注于确定元素,并在较高层次上对它们进行描述(简要的描述),后续的微观过程活动逐渐细化已确定的元素的语义。

        65、对于所有抽象层来说,识别元素的方法总体上是一样的,不同的是从哪里开始(已经有了哪些抽象),关注的焦点是什么(具有架构重要性的元素或者其他元素)以及要走多远(是否需要深入某个设计元素,确定它由哪些元素组成)。识别元素重复递归地进行,目的是发明更多的细粒度的抽象来构造比较高层的抽象并发现已有抽象之间的共性,可利用这些共性来简化系统架构。在识别元素时,粒度最大的设计元素通常最先被识别出来,因为它们确定了系统的核心逻辑结构,而这些元素又由较小粒度的元素组成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值