6.5 Analysis model
6.5.1 The objects of the analysis model
We have seen that the requirements model aims to define the limitations of the system and to specify its behavior. When the requirements model has been developed and approved by the system users or orderers, we can start to develop the actual system.
我们已经看到需求模型的目标是规定IT系统的边界并能够明确说明系统的行为。当需求模型已经开发完毕并且被系统的用户或者订购者所认可, 我们可以开始研发最终的目标系统。
This starts with development of the analysis model. This model aims to structure the system independently of the actual implementation environment. This means that we focus on the logical structure of the system. It is here that we define the stable, robust and maintainable structure that is also extensible.
具体的系统设计工作是从开发分析模型开始的。设计分析模型的目标是保障系统的体系结构不依赖于任何具体的实施环境。这就意味着在分析模型阶段我们专注于系统的逻辑结构。在分析模型中,我们将定义一个稳定的,鲁棒的,可以维护的体系结构,同时这个体系结构要具有良好的扩展性。
It would have been possible to use the object model developed in the requirements model as a base for the actual construction of the system. In fact, many other object-oriented methods use such a model as the only input for construction. However, this does not result in the structure most robust to future changes. We will come back to the reasons for this. The analysis model represents, in our experience, a more stable and maintainable system structure that will be robust for the entire system life cycle. We will come back to this issue in more detail later.
有一种可行的设计方法是利用在需求模型中开发的对象模型作为真实系统开发的基础,直接进行集成设计。事实上,很多其他的面向对象的设计方法都是直接利用需求模型中的领域对象模型作为系统集成过程唯一的输入对象。 然而,使用这种设计方法很难以获得一个坚固耐用的结构,以便应对未来各种潜在的变化。后续,我们会回过头来说明相关的原因。根据OOSE的设计经验,分析模型代表了一个更加稳定和易于维护的体系结构, 这个体系结构将在应用系统的整个生命周期内保持稳定可靠。后面我们将回过头来更加详细的讨论这个问题。
Since many future changes will come from changes in the implementation environment, these changes will not affect this logical structuring. We shall see when discussing how to adapt to the actual implementation environment that we want as few changes as possible to this ideal, logical and stable structure.
因为未来很多关于IT系统的变更将来自具体的实施环境,而这些改变将不会影响分析模型所代表的逻辑结构。我们将来会看到当具体讨论如何将分析模型适配到确切的实施环境当中,我们希望尽可能少的改变这个理想的,逻辑的,稳定的体系结构。
In the information space for this model, our aim is to capture information, behavior and presentation (see Figure 6.13). The information dimension specifies the information held in the system, both short term and long term. Along this dimension, we describe the system's internal state. In the behavior dimension, we specify the behavior which the system will adopt. Here, we specify when and how the system will change state. The presentation dimension provides the details for presenting the system to the outside world.
在分析模型的信息空间information space中,我们的目标是能够捕获信息,行为和呈现.(见图6.13).其中信息维度定义了系统需要保持的信息结构,包括临时存在的和持久存在的信息结构.在这个维度上,我们要描述系统内部的状态.在行为维度, 我们说明系统将要采用的行为方式. 在这个维度上,我们要定义系统在什么时间,以及如何进行状态的改变.而呈现维度则详细提供了系统向外部世界所呈现界面的详细细节.
The analysis model is built by specifying objects in this information space. One possibility is that of having objects which only express one dimension. This is the case with function/data
methods, where functions are placed along the behavioral axis and data is placed along the information axis. If we design in this way, we will obtain a system which is sensitive to modification, as we must often modify some behavior when we modify the information structure. We do not want this situation to arise, so our objects should be able to contain both information and behavior, and even the presentation of this if required.
分析模型的构建方式是通过在问题领域的信息空间中定义对象的方式来实现.一种可能的设计方式是把所有的对象仅仅通过一种维度进行表达.
.这种情景就是功能/数据方法应用的模式, 其中功能被放置在行为轴,而数据则放置在信息轴.假如我们使用这种方式进行设计, 我们将获得一个对需求变更敏感的系统, 因为当我们对信息结构进行变更的时候,我们不许经常变更一些系统行为.我们的确不希望这种场景出现, 所以我们设计的对象应当能够同时包含信息结构和功能行为, 同时甚至能够在需要的时候拥有呈现的特性.
Many object-oriented analysis methods choose to have only one object type, which can be placed anywhere within this space. We have chosen to use three object types. The simple reason for this is to help us get a structure that will be more adaptable to changes. The object types used in the analysis model are entity objects, interface objects and control objects (see Figure 6.14). We will soon come back to the purposes of these object types. Each of these object types captures at least two of the three dimensions discussed above. However, each of them has a certain inclination towards one of the dimensions (see Figure 6.15).
很多面向对象的分析方法选择仅仅拥有一种类型的对象, 单一的对象类型可以在信息空间内部任意自由的放置.而在我们OOSE的设计方法中选择使用三种对象类型. 这样设计最简单的理由是这种方法能够帮助我们获得一种更加适应潜在变化的体系结构.在分析模型中应用的对象包括实体对象, 接口对象,和控制对象(参考图6.14). 我们很快会返回来讨论应用这三种类型对象的目的.每一种对象都捕获了在前面讨论的三种维度中至少二种信息维度.然而,其中任何一种类型的对象都拥有上述三种维度中确定一种维度的倾向性. (参考图6.15)
Hence we have different purposes for the three object types. The entity object models information in the system that should be held for a longer time, and should typically survive a use case. All behavior naturally coupled to this information should also be placed in the entity object. An example of an entity object is a person with his or her associated data and behavior. The interface object models behavior and information that is dependent on the interface to the system. Thus everything concerning any interface to the system is placed in an interface object. An example of an interface object is the user interface functionality for requesting information about a person. The control objects model functionality that is not naturally tied to any other object, for example, behavior that consists of operating on several different entity objects, doing some computations and then returning the result to an interface object. A typical example of a control object is calculating taxes using several different factors. This behavior could be placed on any of the other types of object (since they are also able to model behavior), but the actual behavior does not in fact belong to any specific entity object or interface object.
因此我们针对这三种类型的对象拥有不同的应用目标. 实体对象对系统内部的需要长时间保存的信息进行建模, 并且应当和一个用例模型直接匹配. 所有和这个信息天然联系的行为也应当放置在对应的实体模型中. 一个实体对象的例子是一个人,以及和他或者她关联的数据和行为.接口对象是针对那些依赖系统接口的行为和信息进行建模.这样所有和系统任何接口有关系的事物都要放置在一个接口对象中.一个关于接口对象的例子是是用于请求查询一个人的个人信息的用户接口功能.控制对象则是针对那些不和任何已知的对象自然绑定的功能进行建模, 这样的行为包括对几个不同的实体对象进行操作, 执行一些计算任务,并返回计算结果到一个接口对象.一个控制对象的例子是利用不同的要素来计算税费的多少.这个行为其实也能够放置在其他类型中的对象(因为其他的对象也能够对行为进行建模), 可是这个确切的行为在事实上不属于任何特定的实体对象或者接口对象.
Why do these three object types give us a stable system? The basic assumption is that all systems will change. Therefore stability will occur in the sense that all changes will be local, that is, affect (preferably) only one object in the system. Let us first consider what kinds of changes are common to a system. As we mentioned in Chapter 4, the most common changes to a system are to its functionality and its interface. Changes to the interface should typically affect only interface objects. Changes to functionality are more difficult. Functionality may be placed over all object types: so how do we achieve localization of these changes? If it is functionality that is coupled to information held by the system, for instance, how to calculate a person's age, such changes affect the entity object representing that information. Changes of functionality of an interface, for instance, how to receive and collect information about a person, should affect the corresponding interface object. Changes of interobject functionality, for instance, how to calculate taxes from several different criteria, should be local to a control object. Typically, functionality unique to one or a few use cases is placed in a control object.
为什么利用这三种类型的对象能够为我们提供一个稳定的系统呢?其中一个基本的假设前提是所有的系统在未来都会是改变的.所以只有在所有的系统功能改变都限制在局部范围的情况下,我们将获得系统结构的长期稳定性,换句话说系统的改变尽可能的仅仅影响系统中的一个对象。 让我们首先考虑一下那几种类型的改变对一个系统来说是非常常见的。正如我们在第4章中提到的, 对一个系统来说最常见的改变是系统的功能和他的接口。针对接口的变更通常应当仅仅对接口对象有影响.而要进行功能的改变则更加困难一些.系统的功能可能会被放置到多个对象类型中, 那么我们如何能够实现将对象的改变控制在局部的范围呢?假如需要改变的功能是和系统长期保持的信息结构有联系, 举个例子来说, 如何计算一个人的年龄, 这样的改变会影响代表信息结构的实体对象. 如果要改变一个接口的功能, 举个例子来说,如何接收和收集一个人的个人信息,应当仅仅影响对应的接口对象.而改变对象内部的功能, 举个例子来说,如何根据几个不同的要素来计算税率, 应当限制在控制对象的内部.通常来说, 针对仅仅和一个或者少量用例模型有关的功能被放置在一个控制对象中.
We do not believe that the best (most stable) systems are built by only using objects that correspond to real-life entities, something that many other object-oriented analysis and design techniques claim. When comparing a model developed with one of these techniques and an analysis model using OOSE, great similarities will be found between the entity objects in the analysis model and the objects yielded in other methods. Thus entity objects often represent a problem domain object, although this is not always necessarily so, as we shall see further on. However, behavior that we place in control objects will, in other methods, be distributed over several other objects, making it harder to change this behavior.
我们并不相信最好(最稳定)的系统是仅仅使用那些可以直接代表现实生活中实体的对象来建模 这是很多其他的面向对象的分析和设计技术所声称的一种设计思想. 当我们将使用其他面向对象的建模方法其中之一设计的对象模型和使用OOSE方法设计的分析模型进行比较, 我们会发现分析模型(OOSE方法)中的实体对象和其他方法中产生的对象有非常大的相似性.这样实体对象通常与问题领域有明确的对应关系, 虽然这种设计方式不是必须的,因为后续我们将看到有其他的设计选择.然而,被我们放置在控制对象中的行为特性, 在其他的方法中,将被放置在其他几个对象中, 这样一来对行为的改变将会变得很困难.
The reason that we model with these three object types is thus to have localization in changes to the system. Then how do we know that these are the 'right' object types? This is something you cannot draw any conclusions about until a system has been changed a number of times. Our experience comes from the block design technique mentioned earlier. That was an object-based technique where objects (there called blocks) typically had counterparts in the problem domain. The techniques were used in developing telephone exchanges and the experience was quite good; it was very modular and quite easy to introduce most kinds of modifications. However, certain modifications are unreasonably expensive to introduce. For example, in the system there was a block called Trunk representing data and behavior that should be tied to a trunk (a telephone line between exchanges). When the system had been in operation for more than ten years, and had undergone several changes, we investigated what had happened to this block. Of course, many changes had been made to it to adapt to the new requirements and these changes were local to the block. This also included many new operations that had been introduced to the block. What we found, however, was that 23 (!) operations had been added that were unique to only one specific use case. The operations were thus not generally reusable and when a new use case needed to be added, typically operations for that specific use case also needed to be added. Some operations could be reused in several use cases; these were typically designed with not just one use case in mind.
我们利用三种类型的对象进行分析模型设计的目的是尽量将系统变更控制在局部的范围. 那么我们如何能够知道这些是”正确的” 对象类型呢?这一点你很难做出任何结论,直到未来软件系统经过了多次变更以后才能得出结论. 我们的设计经验来自前面提到的模块设计技术. 模块化设计是一种以对象为基础的设计技术, 在模块设计技术中对象(在哪儿被称为模块blocks)通常和问题领域是的客观对象是非常匹配的.这种模块化的设计技术被用来开发程序控制电话交换系统axe10交换机,并且经过当时的开发过程收获了非常好的经验. Axe10交换机是非常模块化的结构,并且能够非常容易的引入绝大多数类型的功能更新. 然而,引入特定类型的更新是需要花费高昂的代价,这种高费用是没有理由的. 举个例子来说, 在系统中有一个功能块叫做中继线Trunk, 他代表了需要和一条中继绑定的数据和行为( 中继线是程控交换机之间的一条电话线).当AXE-10交换系统已经在线运行超过10年以后, 并且已经经过了多次的版本升级, 我们调查了这个模块的变动情况.当然, 这个模块已经经过了多次的改变来适应新的功能需求,并且这些改变都是控制在模块内部的范围; 同时这种改变也包含了在模块中引入了很多新的操作. 另外,我们还发现了有23个新添加的操作仅仅只对应一个特殊的用例模型的功能需求.这样一来这种操作通常就不是一个可以重用的操作, 同时当一个新的用例模型需要被添加, 通常和那个特殊用例模型相关的操作的也需要被添加. 有一些操作何以被多个用例模型进行重用, 这些操作通常在设计的时候需要考虑多个用例的需求.
Thus the actual problem here was that too much specific functionality had been incorporated in the block (entity object in OOSE). Instead we should model this specific functionality in the control object so that, firstly, the (operations of the) entity object will be more reusable in several different use cases and, secondly, the specific functionality should be local and not distributed so that it is easier to introduce changes in this functionality.
这样看来这里确切的问题是在TRUNK这个功能块( 在OOSE方法中的实体对象)已经引入了太多的特殊功能. 代替的做法是我们应该利用控制对象针对这些特殊的功能来建模, 这样的好处是在于, 首先关于实体对象的操作获得更好的复用特性, 能够支持多个用例模型; 第二, 这个特殊的功能应该被限制在局部的范围,而不是分布在多个对象中, 这样一来对这个特殊功能块引入变更会更加容易.
Similar observations of object-oriented structured systems are not very common since very few of these systems have undergone changes over several versions. Even so, the experience so far with an object-oriented structure is that, in general, it is more maintainable than a function/data structure. However, there are similar observations on system changes. One example is given by Scharenberg and Dunsmore (1991), where a system for inventory control was developed with a 'problem domain object' analysis method. The first observations were that these initial classes were only used as more complex data types and with a not-so-stable structure. The system was refined and further developed, leading to another class structure that was more stable. An 'artificial object domain' was reached which did not directly reflect the problem domain, but instead was more stable to changes and more robust. The 'artificial object domain' consisted of the three object types we use.
类似的关于面向对象方法构建的系统后评估并不常见, 因为很少有类似的系统能够长时间的运营并经过多次的版本升级.即便是这样, 迄今关于面向对象结构的经验是,面向对象构建的系统一般来说比一个基于功能/数据方法构建的系统具有更好的维护性. 当然目前也存在一些类似的关于系统变更的观察. 其中的一个案例是由Scharenberg and Dunsmore (1991)提供的, 他们观察的是一个存货管理系统, 这个系统是利用’问题领域对象’分析方法来设计的.首先的观察结论是这些最初设计的类是作为复杂的数据类型来使用,并且是一个不那么稳定的结构. 所以这个系统被重新优化设计,并进一步开发, 最终形成了另外的更加稳定可靠的类结构..一个’人造对象领域’被引入设计类结构中, 其中的对象不直接映射到问题领域, 然而这种设计方法的好处是在系统变更时更加稳定,所以能够更加稳健的运行.而这个’人造对象领域’就包含了我们OOSE方法中所应用的3种对象类型.
Another approach which may look similar to this approach is the Model, View, Control (MVC) paradigm used in Smalltalk. However, the MVC distinguishes the output presentation from the inputs whereas that is not the intention here. Another approach, which is more similar to ours, is the PAC model by Coutaz (1989). The PAC model distinguishes between Presentation, Abstraction (Application) and Control. These relate very well to the interface object, the entity objects and the control objects.
另外一种和OOSE方法类似的设计方法是在Smalltalk这种编程语言中应用的模型,视图,控制(MVC)设计规范.然而,MVC方法需要清楚的区分输出呈现和输入呈现,这样就不是这里的意图.另一种方法, 由Coutaz (1989)设计的PAC方法,和我们的方法更加类似. PAC方法区分呈现Presentation, 抽象Abstraction,和控制Control. 这种设计方法和接口对象, 实体对象,以及控制对象关联的很好.
A similar distinguishing of these three different categories can be found in Davis and Morgan (1993). Here these three different categories have split the system architecture into three layers, each of them implementing one of these three categories. The highest layer implements only interface functionality (interface objects), the middle layer implements the processes (control objects) and the lowest layer implements the business objects (entity objects).
关于这3种不同类别对象的类似区分可以在Davis and Morgan (1993)的论述中发现.在这里,3种不同的类别将系统的结构划分为3层, 其中每一层负责实现3种类别之一.其中最高层仅仅实现接口功能(接口对象), 而中间层实现逻辑处理功能(控制对象), 而最底层实现商业对象数据管理功能(实体对象).
Robust structures
鲁棒性结构
Object-orientation is often claimed to give more changeable and extensible software than traditional methods. Inheritance and encapsulation are then often claimed to be important parts of the solution. In Chapter 4 we discussed the problems with function/data methods and showed the object-oriented solutions. However, object-orientation by itself does not guarantee robust and extensible software. We will here look at an example of this. The example is an extension to previous examples discussed by the authors of the forewords to this book: Dave Thomas (1989) introduced the OO solution to the example, and Larry Constantine (1990) introduced the functional solution.
相比较于传统设计方法, 面向对象的设计方法通常被声明能够赋予软件系统提供更加容易变更和扩展性的特性. 继承和封装常常被声明为基于面向对象方法实现软件扩展性方案中最重要的部分. 在第四章中,我们讨论了基于功能/数据方法在系统设计过程中会带来的主要问题,并且显示了基于面向对象方法的解决方案.然而,面向对象技术本省并不能保证能够设计出稳健和具有扩展性的软件结构. 我们在这里将看到一个案例. 他来自前期为本书写序言作者提出案例的扩展分析, Dave Thomas为本案例提供了OO的分析解决方案, 而Larry Constantine为本书提供了功能/数据方法解决方案.
The example system must deal with a number of different types of account. Three account types are included in the example: passbook savings, checking and bonus savings. A number of different transactions are valid for each account type; for simplicity, only three are shown, but in a real application there may be many more. Figure 6.16 shows a structure chart based on a conventional function-structured decomposition (for example, structured analysis/design). Each transaction processing module must deal with distinct variations for each of the account types. There will, however, be portions in the modules that will be reused over several modules, such as database access, and portions that are unique, such as the processing of the bonus savings. In a good structured design, functions are decomposed so that common processing is located in subordinate modules that can be reused wherever needed without duplication of design and coding.
我们列举的案例系统必须能处理一系列不同类型的帐户. 本例子中包括3种帐户类型,分别是银行存折储蓄帐户, 支票帐户, 增息储蓄帐户. 一系列不同的交易操作针对每一种帐户类型都有效;然而出于简化分析的目的, 仅仅显示了3种不同的操作交易,然而在真实的应用系统中,会有很多种不同的交易.图6.16显示了一个基于常规功能结构方法(举个例子来说,结构化的分析/设计)分解的功能结构示意图. 每一个交易处理模块都区分每一种帐户类型的差别进行明确的处理. 这样一来,模块中的一部分将会在其他几个模块中进行重用,比如处理数据库接入的操作,而模块中的另外一部分则仅仅是在系统中独一无二的,比如处理增息储蓄帐户的功能逻辑. 在一个好的结构化设计当中, 功能必须进行分解,其中公共处理部分就需要被放置在下属的模块(subordinate modules)当中,下属的模块可以在需要的时候进行复用, 而不需要进行重复的设计和遍码.
A typical object-oriented solution to the same problem is shown in Figure 6.17. The various account types will now be modelled as descendants of the abstract class Account. The operations (Open, Deposit and Withdraw) are inherited. Possibly they need different implementations, but at least they have the same interface. The 'other objects' represent those objects that manipulate these objects in the various transactions. Most of these objects can be described as operating on Account using polymorphism since the object interfaces are common. However, the creation of objects at least must differ between the various account types.
针对同样问题的一个有代表性的面向对象的解决方案见图6.17所显示. 这些不同的帐户类型现在将被建模为一个抽象类’帐户’的后裔类. 这些操作(打开,存款,取款)将被继承自抽象类. 也有可能不同的后裔类需要有不同的实现,但是至少他们全部拥有相同的接口.而’其他的对象’则代表了那些在不同的交易过程中需要操控帐户对象的对象. 这些对象的绝大多数可以应用多态using polymorphism的方法被描述为对帐户类的操作, 因为对象的接口是公共的.然而, 对对象的创建则必须至少能够区分不同的帐户类型.
Now, which of these solutions is easier to change? Let us consider some typical changes. What if we want to add a new account type, such as a money market account? Adding a new account type to the function/data solution requires us to add a new module for each of the valid transactions on this account type as shown in Figure 6.18. These modules may of course use existing lower-level modules such as database access and so on. Additionally, we need to modify the modules that decide upon the account types, that is, all transaction modules. Typically in these modules the body is a CASE-statement deciding upon the specific type for the application. We thus need to add a new case for all applicable transactions. Hence, in this case the change for adding a new account will not be local, but spread all over the transactions in the application.
现在,我们看看哪一种解决方案更容易进行变更设计?让我们来考虑针对一些对银行帐户系统典型的改变方式. 假如我们想增加一种新的帐户类型,比如说货币市场帐户. 在功能/数据方法解决方案中增加一个新的帐户类型需要我们针对与新帐户有关联的每一个交易方法下添加一个新的模块.详细的方案见图6.18.这些新增加的模块当然可以使用已经存在的底层模块, 比如说数据库接入等等功能. 另外, 我们还需要更新那些负责判断帐户类型的模块, 也就是所有的交易模块.通常在这些模块中,程序体使用CASE-statement 的程序语句来判断实际应用的特定类型. 这样我们需要为所有的应用交易模块增加一个新的分支判断条件.所以, 假如是在增加一个新的帐户类型的情况下, 系统的改变将不会限制在局部, 而是分布到应用系统的所有交易模块中.
Adding a new account type to the object-oriented solution requires only the adding of one new descendant of the Account class. The interface will be the same, but probably we need to implement the variations in the operations. Additionally, we need to modify the objects that distinguish the various accounts, at least the creation of the money market account. This modification is shown in Figure 6.19. We can see that in the object-oriented solution the modification is much more local than in the function-oriented solution.
在面向对象的解决方案中增加一个新的帐户类型仅仅需要为帐户类增加一个新的后裔类. 对应的接口将是完全相同的, 但是有可能我们需要通过编程实现在对象操作中引入的变动. 此外, 我们需要修改那些需要区分不同帐户类型的对象, 至少包括负责创造货币市场帐户的对象.图6.19显示了系统变更的方案. 我们可以发现在面向对象的解决方案中, 系统变更被控制在更加局部的范围, 相比较于那些功能/数据方法.
The conclusion is that we would favor the object-oriented solution; one object added and one modified versus three modules added and three modified in the functional solution. However, the amount of new and changed code is probably around the same for both solutions. The difference is that of locality.
结论是我们将更加倾向于面向对象的解决方案; 增加一个对象和变更一个对象, 对比于功能数据方法中增加3个模块,更新3个模块.总而言之,两种方案中新添加和改变的代码数量可能是在相同的水平, 而差别在于修改的范围是否被有效的控制在局部.
Let us consider another enhancement to the application. The above example introduced a new account type. What if we introduce a new transacation type? Consider the transaction of producing a special report, for example a report for bank auditors to inspect any account.
让我们考虑另外一种对应用的增强需求.上面提到的案例引入了一种新的帐户类型.假如我们引入一种新的交易方法类型会发生什么情况? 考虑一种交易是负责产生一个特殊的报告,举例来说这个报告可以用于支持银行稽核员来审核任何帐户.
The changes needed in the function/data design are shown in Figure 6.20. The added modules are now localized under the Report module. We also need to modify the Transaction module to cope with this new transaction type. This change was thus quite easy to incorporate into the structured design.
关于功能/数据方法所需要执行的设计改变在图6.20中进行显示.新增加的模块现在被局部化限制在报告模块之下.我们同时需要变更交易模块来应对新的交易类型.这种改变可以非常容易的融合到结构化的设计当中.
What about the object-oriented solution? Following the traditional object-oriented approaches, which base the solutions only on domain objects (we sometimes call this naive object modeling), we would add a new operation for this report on every object type (see Figure 6.21). We see that this change will have a dramatic effect on the design. We would need to modify all existing account type objects as well as the initiation of the new report somewhere else.
那么面向对象的设计方案会发生什么样的情况呢?遵循传统的面向对象的方法, 这种基于领域对象的方法(我们有时候也称之为幼稚对象建模),我们需要为每个对象添加新的操作来实现生成报告的交易方法(见图6.21).我们将发现引入这种类型的改变将需要花费令人印象深刻的努力进行重新设计. 我们将需要改变所有已知的帐户类型对象,同时还需要在某个地方添加关于初始化制作报告的操作.
These two additions illustrate two typical kinds of changes, that is, adding a new data structure item and adding a new transaction type. An object-oriented structure is built around these data items, while a function-oriented structure is built around the transaction types. Of course, the ease of adding a new feature is very dependent on whether the system is structured around that type of feature. But usually changes comes in both of these 'dimensions'. In some extensions or modifications, one solution will have clear advantages
上面列举这两种系统功能增加解释了2种典型的系统变更,也就是说增加新的数据结构条目和增加新的交易类型. 一个面向对象的体系结构是基于这些数据结构条目而构建的, 然而一个面向功能的体系结构是围绕交易类型来构建的. 当然,添加一种新特性的难易程度和IT系统是围绕那一种类型的特征条目构建有很强的依赖性.但是通常系统的改变来需要同时在这两种维度进行.在某些系统功能扩展或者变更中,一种解决方案会有明显的优势.
and in others the other solution will fare better. Over a balanced suite of modifications including adding data structures and functions, neither solution will emerge with an overall advantage. No published empirical studies of the frequencies of these modification categories exist to our knowledge. A typical application will be exposed to both types of modification.
上面列举这两种系统功能增加解释了2种典型的系统变更,也就是说增加新的数据结构条目和增加新的交易类型. 一个面向对象的体系结构是基于这些数据结构条目而构建的, 然而一个面向功能的体系结构是围绕交易类型来构建的. 当然,添加一种新特性的难易程度和IT系统是围绕那一种类型的特征条目构建有很强的依赖性.但是通常系统的改变来需要同时在这两种维度进行.在某些系统功能扩展或者变更中,一种解决方案会有明显的优势,而在其他的情况下其他的解决方案则会有更多的优点. No published empirical studies of the frequencies of these modification categories exist to our knowledge.假如一个平衡的系统功能组合更新包括增加新的数据结构和新的功能,任何一种解决方案都不能显现出完全的优势.目前于我们的知识结构中还没有公开发表的关于IT系统在不同类别变更频度的经验研究存在. No published empirical studies of the frequencies of these modification categories exist to our knowledge.一个通常的应用系统需要包含两种类型的变更操作.
This is the problem we are trying to address with our categorization into three different object types. The entity objects should capture the data structure changes, the control objects should capture the functional changes and the interface objects should capture the interface-related changes.
这就是我们希望通过OOSE方法努力解决的问题, 将我们针对对象类别的分类方法扩展为3种不同对象类型.其中领域对象应当能够捕捉到数据结构的改变, 而控制对象能够捕捉到功能性改变,而接口对象将捕捉到和接口相关的改变.
Let us review the example to see what the solution would look like in OOSE. Surely the transaction types would map quite clearly to use cases. The analysis model would be as in Figure 6.22. The addition of the money market account would be done by adding a new descendant to the Account class. The descendant would basically support the Open, Withdraw and Deposit transactions (with the appropriate interface object) since these may be viewed as basic operations on the entity objects. Each of these transactions would also have an interface object supporting the specific use case. However, a specific control object would not be needed. The report use case, on
the other hand, would not be spread out over the entity objects. Instead we would add a new control object to support this use case. This control object would reuse the basic operations on the account objects, such as balance enquiries and so on. The report-specific issues would then be local to the control object Report. We see here the importance of arriving at the correct, reusable operations on the entity object. This is a critical factor of success for the changeability of the application.
让我们回顾一下这个案例来进一步分析在OOSE方法中的解决方案应该是什么样子呢?.很显然交易方法的类型应该和用例模型匹配的非常明确。相关的分析模型将会在图6.22中显示。添加一个新的货币市场账户类型将通过增加账号类的后裔类来实现。新的后裔类将非常基础的支持打开账户,存款和取款交易(利用合适的接口对象),因为这些操作将被看成是实体对象的基本操作。每一个交易类型也将拥有一个接口对象来支持特定的用例模型。然而。一个特殊的控制对象将不需要。
另外一方面,生成审计报告的特殊用例就不会扩散到实体对象当中。代替的做法是我们将增加一个新的控制对象来支持这个用例。这个控制对象将重用在账户对象上的基本操作,比如收支平衡查询,等这样一些基本操作。 关于特定报告功能分布的裁定将会限制在控制对象“报告’当中。在这里我们看到正确的设计可以重用的实体对象操作方法的重要性。这是为了保障应用系统的可变更性的一个非常重要的要素。
6.5.2 The requirements model is structured in the analysis model
6.5.2 需求模型将被构建成为分析模型
The analysis model is formed from the use case model. Each use case will be entirely divided into objects of the three types described in the previous section. In the requirements model we specify the entire functionality of the system. This functionality should now be structured to obtain a robust and extensible structure. In this way the use cases will be partitioned into analysis objects (see Figure 6.23). In
practice this means that the functionality specified in the use cases should be allocated to different objects. In this way, each use case will be offered by objects in the analysis model. An object can of course be common to several use cases. This is actually desirable since it gives objects that are reusable in several different use cases, which suggests that they will also be reusable in future changes of the system. This transformation from use cases into objects forms one of the most important parts of OOSE. It is now that we form the basis of the system architecture. We here only touch upon the principles of this transformation, which will be discussed in more detail in Chapter 7.
分析模型是根据用例模型来构建的。每一个用例将会被完整的划分为在前面章节中描述的这三种类型的对象。在需求模型中,我们定义了系统完整的功能。这个功能现在需要被构造设计以便获得一个稳健和具有扩展性的结构。在这种方式下,用例模型将被划分成为分析对象(见图6.23)。在实际的操作中,这种方式就意味着在用例模型中定义的功能将被分配到不同的对象当中。在这种方式下,每一个用例将由分析模型中的对象进行支持。一个对象也就理所当然的被多个用例所共同复用。这一点是非常令人满意,因为这种设计方式使得对象在不同的用例模型中具有了复用的特性;这一点也意味着这些对象在系统未来的改变中也能够具有复用特性。这种从用例模型到对象的转换过程构成了OOSE方法中最重要的部分。完成了这种转换工作,我们就构成了系统体系结构的基础。在这里我们仅仅开始接触了这种转换的基本原则,在第7章中还会进行深入的讨论。
Basically, we partition the use case according to the following principles:
Those use case functionalities which are directly dependent on the system's environment are placed in interface objects.
Those functionalities dealing with the storage and handling of information which are not naturally placed in any interface object are placed in the entity object.
Functionalities specific to one or a few use cases and not naturally placed in any of the other objects are placed in control objects.
基本上来说,我们根据如下的原则对用例模型进行划分。
那些直接依赖系统的应用环境的用例模型功能将被放置在接口对象中。
那些处理存储和处理信息结构的功能将很自然的不放置在任何接口对象中,并放置在实体对象中。
面向一个或者是小部分用例的功能定义将不会自然的放置在任何其他的对象中,而是放置在控制对象中。
By performing this division, we obtain a structure which helps us to understand the system from a logical view and also one which gives high localization of changes and thus less sensitivity to modifications. For instance, changes to an interface, a quite common modification as we have seen, affect only one object, the interface object that handles this interface. Changes of data format would affect only the entity object (structure and behavior) where the change should be introduced.
通过实施这样的用例划分,我们获得了一个结构,这个结构能够帮助我们从逻辑视图的角度来理解系统,同时他能够将系统变更高度局部化,这样一来对未来的变更也就更加稳定和不敏感。举个例子来说,改变一个接口,这是我们看到的一种很普通的改变,仅仅影响一个对象,负责处理接口的接口对象。改变数据结构将仅仅影响实体对象(数据结构和行为),当需要引入改变的时候。
The allocation is quite difficult in practice, and we shall discuss it much more in the analysis and construction chapters. It is when doing this partition of functionality that we decide upon the robustness and maintainability of the system. The basic underlying principle is to get localization of changes.
在实践中关于用例到对象的分配是非常困难的,所以我们将在分析和构建的章节对这个部分进行更多的讨论。只有在实施这种从用例到对象的划分工作,我们能够决定IT系统体系结构的稳定性和可维护性。最基本的基础系统设计原则就是将系统的改变控制在局部的水平。
Since it is often hard to draw clear borders between functionalities in a system, in practice the developers are forced to make many judgments about where to split functionality between objects. We have seen from real projects that the best developers often reason in terms of the potential changes to this system. How will these potential changes affect this structure? From this they develop a structure that is stable for the most likely changes. We have also seen that this 'speculation of potential changes' rapidly becomes a skill for an experienced developer. Giving developers the architecture of OOSE allows them to use their creativity to develop stable and robust systems.
因为针对系统的功能域进行边界划分通常是一个非常困难的工作,在实践中系统开发者常常要被迫做出很多决策,来决定如何划分对象之间的功能。我们已经从很多真实的项目中发现最佳的系统开发者总是能够针对系统潜在变更给出合理的对象功能划分,并且说明相关设计理由;以及这些潜在的系统改变如何影响这个系统结构。根据这种分析工作,他们能够开发出一个稳定的体系结构能够适应未来绝大多数潜在功能改变的场景。我们同时也发现这种“预见系统潜在变化“的能力很快成为一个有经验的IT系统开发者的重要技能。赋予程序设计者关于OOSE体系结构的设计思想将帮助他们充分发挥他们的创造性来研发一个可靠并且稳定的系统。
As the objects are identified and specified, we also describe how these objects are related through different types of association. We shall come back to this issue in Chapter 7.
随着对象被标识和定义,我们也同时利用不同类型的关联关系描述这些对象的相关性。在第七章中,我们将回过头来讨论这个问题。
The analysis model is now designed directly from the user's requirements, that is, the requirements model. This analysis model will form the basis of the specific system's architecture, and we see that no consideration has been made of the actual implementation factors. This provides an ideal and sound system architecture, as it is the problem which controls the architecture and not the factors of the actual implementation environment. During the design work, we shall take into consideration these points, but it will then only be a matter of adapting to these circumstances; the basic system structure, as far as possible, remains untouched.
现在分析模型现在将直接根据用户的需求进行设计的,用户的需求也就是OOSE方法中的需求模型。分析模型就成为特定系统体系结构的基础,同时我们看到分析模型的设计是没有考虑未来实施环境的要素,这是因为应当由问题领域(用户需求)来决定系统的体系结构,而不是由确切的软件系统实施环境来控制系统的体系结构。在设计工作期间,我们将考虑这些因素,然而这时要考虑的是在设计中适配这些环境因素;而那些基本的系统结构,则应该尽可能的保持不变化。