实施UML九项注意

UML的符号比较多(可能太多)而且足够灵活能适应大范围项目的需求。为了成功使用UML,在使用的过程中必须流程化。不同的项目需要不同的内容。项目中使用UML符号的哪些具体元素取决于项目的本质(使用关系数据库客户端/服务器端或实时嵌入式)及要使用的开发语言。使用JAVA或Smalltalk时一些详细的C++设计组件将不会被使用;如果使用VB,你可能想避免使用更多的泛化和继承。有时,纯粹的建模组件可能太庞大了,尤其对那些刚开始接触面向对象分析和设计的学生来说。但是,好消息是几乎任何事情都可以使用UML来建模来实现。有很多建模组件可供使用。

You Still Need a Process过程仍然需要

UML本身仅仅是一种符号,为了创建有效的模型,仍然需要一个建模过程。使用UML有很多种建模方法;建模语言本身并不描述过程。在UML产生的几年前,我们一直把作了微小变化的Objectory过程(从Ivar Jacobson的 《面向对象软件工程:一个用例驱动方法》而来,Addison-Wesley, 1992)作为Booch/Rumbaugh/Jacobson的综合来授课,并取得了成功。我们的方法将重点放在了区分更高层次的静态模型(域模型),同时也产生用例。然后我们精炼出静态模型,在开发用例和动态模型时反复精练。

或者你更倾向于使用Objectory,对象模型方法,我们的ICONIX统一对象模型过程,或其他一些方法。在从事建模工作之前,理解UML不是一个过程是重要的。让项目组处于同一个开发阶段尤其重要。让项目组对UML有统一的理解使建模成功的保证。UML的规模(文档符号的庞大相对于过程而言)很容易陷入“分析麻痹”。关注项目组通过UML符号对过程的统一理解,能让建模更容易。

Legacy Methods Are Important 过去的方法依然重要

我的大部分学生会问我理解Booch, Jacobson, and Rumbaugh过去的方法是否仍然很重要。我的答案是非常重要。就像知道电流设计并没有排除知道电路理论一样,虽然UML符号而不排除理解对象建模理论的必要性。自从UML代表了Jacobson, Booch, and Rumbaugh三人方法的综合,但早期的方法是信息的来源。

Keep It Simple保持简单

让一个项目组有效的使用UML是有难度的。项目组成员对于面向对象分析和设计以及UML的理解层次各自不同。开始之前统一培训是不错的方法,培训需要认真考虑项目组每个成员的背景及项目的特殊要求。最重要的决定在于课程表的明智选择和指导老师在工作期间的调整。

在学习UML中需要记住的一点是我们并不需要使用每一个存在的组件。让过程尽量简单化。流程化一个项目的文档和建模方法对项目的进行有非凡的作用。

用UML建模和有时和座在一大堆事物面前很相似,开始吃之前就有不能吃完盘子里面的所有食物的想法可能毁了你的食欲。同样的现象可能发生在UML建模过程中。用完全详细的动态模型描述系统的每一个用例,而不得不创建一系列完整的时序图、协作图、状态图、部署图,用例和类图的想法可能会让一个团队完全脱离面向对象分析和设计。

在一个给定的建模方法中决定使用哪一个组件简单同样是要考虑的。举例来说,在一个用例图上同时使用USES 和EXTENDS真的有必要吗?或者我们只需要使用USES?我的经验是流程化的东西越多,建模成功的可能性越大。

Write the User Manual Before You Design the Classes设计类之前写使用手册

写程序的一条老的规矩是在写代码之前写使用手册。在我学习的时候我认为这是一条好的建议,并且到今天为止我仍然认为是好的建议。在面向过程的年代和面向对象方法的早期,这条规矩很少被遵从。在用例驱动建模方法中,Jacobson把这个规律编写成一系列的步骤,通过这些步骤可以为对象服务并且能用UML描述。每一个步骤建立在上一个步骤的基础之上,形成一个可以跟踪的方法,直道最后,管理能加强这个方法把它作为一个设计范例并且确认在分析和设计的过程中能被遵守。

基础层次的人理解Objectory和用例驱动对象建模的本质的简单方法是:在设计类之前写使用手册。大脑里一直有这个想法将会帮助你在UML的迷宫里穿越静态和动态的建模符号。每一个用例代表着用户手册的一部分,并且应该按着“用例分析的目的是产生对象模型”的方式写。

Organize Use Cases into Packages用例打包

一旦你准备为你的系统的每一个用例书写使用手册的时候,你将很快会意识到需要更高层次的把用例组装起来。UML允许你把用例打包。这些可以用文件标签代表。每一个包至少应该包括一个用例图,这个图可以作为一个上下文图,它可能把设计阶段每个用例的动态视图和用例描述联系起来。有一些项目从高层次的包分割开始。这些分割并不总是代表最终的分割,有时是很好的开始起点。

Use the Objectory Stereotypes使用Objectory模板

整个设计过程从用例中分离出来,表明注重描述它们是“正确“的方法。同时在需求分析和业务过程建模中用例作为一种备选方案正越来越受到欢迎。不同形式的用例建模有一些不同的向导,我遇到的大部分项目仍把用例作为得到对象模型的方法。

Jacobson的早期的OOSE/Objectory包括这样一个我们称之为健壮性分析的阶段。在健壮性分析中,用例描述被解释为粗略地分割一系列协作对象。在分析的过程中,Jacobson提出将对象进行分类,把它们分为接口对象,控制对象,和实体对象。

这个小又快的建模步骤产生令人惊讶的收益。它帮助人们写出正确的用例,较早地确认客户端/服务器端和MVC设计信息,很可能最重要的是快速的浏览所有用例能确认可重用的对象。同时也填补了需求分析和详细设计之间的空白。

不幸的是,由于某些原因,健壮性分析的一些符号(三个容易画的符号),在转变的过程中只有部分保留在UML中。符号仍然存在,但被分离到一个称为对象过程扩展的文档当中,并且工具支持也缺少。我把健壮性分析作为一个整体部分描述用例(图变成了文本的完全检查)时,发现学生已经很快适应了这个对象。

Important Questions重要的问题

你可以把整个领域的面向对象的分析和设计减少到两个简单的问题: 首先,系统中的对象是什么?其次,需要的系统行为如何在对象中分配?

已经明确要建立的正确的对象集,并且你已经为一个系统分配了合适的类集,你的项目将会进展顺利。最难的工作恐怕是我们听起来觉得很很顺耳的“分配行为是不错的工作”这句话,这也是有经验的面向对象分析者的生存之本。

Drive the Static Model from the Dynamic Models从动态模型中分离出静态模型

无论你打算在哪个过程使用UML,从动态模型中分离出静态模型(类图)是不错的实践方式,从较高层次的用例图开始,尤其是使用UML 时序图在类图中分配行为。 这个理论,是从Jacobson的OOSE/Objectory 过程中得来的,是1993年的时候一个关系好的Objectory咨询者解释给我听的。在过去的四年中我继续把它作为一种设计形式在教,它内在的智慧和广泛的应用让我已经越来越信服它了。

这个观点的本质在于: 通过遵从对象模型方法我们可以开始并且得到一个系统的粗略的对象集,这同通过问题描述来寻找名词得到“现实世界”或“问题领域”很相似。有时,我们可以做出聪明的猜测,一个特殊的类可能会是一个特殊操作的容器。但是,通常在面向对象的设计过程中,我们发现缺少用例开发来考虑静态模型是幼稚的。

以我的经验,面向对象分析与设计的实质在于真正好的方法解决类中分配行为的问题,把用例在更详细的(信息传递/方法)阶段。正规的或者非正规的,我所遇到的年长的的面向对象分析者大部分是这样设计的。当方法不正式时(不可见),设计者对怎样从一系列给定的领域对象和用例中得到一个明确的方法充满疑惑。通常,在使用一个系列像“多态、封装接口“这样的行话时这样的疑虑又会产生。这样能限制项目组成员完成有用的设计评估,让水平高的程序员更灵活地根据情况完成任务。

然而,在我看来,在UML(参看“UML模型如何匹配“,关注UML, SR4 页,时序图例子)中使用时序图设计方法才能更好的完成。时序图通过左侧的早先的(需求阶段,用户手册视图)父用例文本描述,图中间的实际的详细的动态行为(每一个方法和触发事件)描述来实现的。在一页纸上描述看出详细设计和需求阶段用例描述需要快速的浏览需求,可以证明至少你的用例设计符合需求。简单的重复系统中所有用例,将会得到一个可跟踪的设计。

画时序图的过程中,在设计中要确认具体的操作并把它分给具体的对象。虽然画动态(时序)图实际上也是在创建静态类模型。时序图是教我们如何从抽象的世界中找到对象模型的。

Defer Assigning Operations to Classes操作迟些分配给类

在项目分析阶段不要过多的去关注将操作放进哪个类中。除了大部分显而易见的情况外(有时连这些也会出错),很可能规划错误。经验告诉我,做这些行为分配决定的时候最好仔细,随着动态模型的开发一次一个。

要把这种分离一直记住(分析:什么是对象?设计:行为如何分配?)会帮助项目组定义分析和设计的界限。我们最先的统一对象建模过程方法在最初的分析阶段使用了对象建模方法符号,在设计阶段使用了Booch符号。在分析的过程中对象建模方法被使用,更详细的设计阶段的模型使用Booch方法。在UML中,这些符号被融合成单一的,对象模型方法。随着分析和设计符号的模糊不清,项目组经常要分清分析和设计的界限在哪儿会很困难。

即使我在教跌代和递增过程, 在某些逻辑点上,需求和设计评估是必须的。如果我在评估一个分析模型,我并不会很在意类的操作(在大多数场合,如果没有我会很高兴)。我在寻找一个好的域类集和可以理解的用例模型。而在设计评估时,所有的操作都需要考虑在内,在时序图中需求和设计必须可以跟踪。设计者必须能解释清楚为什么他会把一些操作放在特定的类中。

Simply Successful简单既成功

在项目中使用UML,需要时刻记住的是保持简单,先写用户手册(一次一个用例),同时让项目组对过程有统一的认识。记住,UML是一种符号,而不是过程。我所见到的最成功的项目都采用用例驱动,迭代,递增方法的。如果能把过程细化并且让项目组掌握技巧,UML项目已经离成功不远了。

 

英文原文:

In the last quarter of 1997, I taught object-oriented analysis and design with UML to a wide range of developers working on various projects. The projects spanned application domains including retail shelf space management, pharmaceutical clinical trials, cellular telephony, and more. Implementation languages included Visual Basic, C++, Java, DB2, and others. This article discusses several aspects of how well the UML notation, along with my company's use case-driven Unified Object Modeling process (also based on the methods of Booch, Jacobson, and Rumbaugh), met the demands of a diverse set of projects. It provides practical guidance for tailoring your use of UML for various projects.

The UML notation is big (maybe too big) and is flexible enough to accommodate the needs of a very wide range of projects. To succeed with UML, you must streamline how you use it. Different projects will need different pieces. Which specific elements of the UML notation you need for your project will depend on its nature (client/server with a mainframe RDBMS vs. real-time embedded, for example) and on the implementation language you will be using. Some detailed C++ design constructs are not needed if you're building in Java or Smalltalk, and you may want to avoid too much use of generalization or inheritance if you're building in Visual Basic. Sometimes, the sheer volume of modeling constructs can be overwhelming, especially to those students who are new to object-oriented analysis and design. However, the good news is that you can model almost anything using UML. There are plenty of modeling constructs to go around.

You Still Need a Process

UML itself is only a notation; to build effective models, you still need a modeling process. There are many modeling approaches you can use with UML; the modeling language itself does not prescribe the process. My company has been successful teaching a slightly modified version of the Objectory process (derived from Ivar Jacobson's Object-Oriented Software Engineering: A Use Case Driven Approach, Addison-Wesley, 1992) that we developed as a synthesis of Booch/Rumbaugh/Jacobson several years prior to the advent of UML. Our approach places slightly more emphasis on identifying high-level static models (domain models) up front, in parallel with use cases. We then refine the static model iteratively and incrementally refine as we explore the use cases and dynamic models.

Whether you prefer using Objectory, Object Modeling Technique, our ICONIX Unified Object Modeling process, or some other approach, it's important to understand that UML is not a process, and that it is critically important to get your project team on the same page process-wise before undertaking a modeling effort. Once again, the size and bulk of UML (and the overwhelming weight of documentation on notation as opposed to process) can make it easy to slip into "analysis paralysis." Focusing the team on an understandable process that is supported by the UML notation can generally get the modeling effort underway.

Legacy Methods Are Important

Many of my students ask whether developing an understanding of Booch, Jacobson, and Rumbaugh's legacy methods is still important. My answer is an emphatic yes. Just as knowing the symbols used for electronic circuit design doesn't eliminate the need to know circuit theory, understanding the notational aspects of UML doesn't eliminate the need to understand object modeling theory. Since UML represents the synthesis of the works of Jacobson, Booch, and Rumbaugh, the original legacy methods are a rich source of this information.

Keep It Simple

Getting a project team to make effective use of UML is tricky. Team members will have varied experience with object-oriented analysis and design and UML. A training workshop is a good way to begin. The workshop needs to be tailored to the specific needs of each project, taking the backgrounds of the various team members into careful consideration. The most critical tailoring decisions will ultimately involve judicious choices of what gets left out of the course agenda, as well as the instructor's ability to adjust on-the-fly during the workshop.

One of the most important things to remember when learning UML is that you don't need to use every construct just because it's there. Keep the process as simple as possible. Streamlining a project's documentation set and modeling approach does wonders for generating forward momentum.

Modeling with UML is similar to sitting down to an huge plate of food-sometimes, the thought that you can't possibly eat everything on the plate just kills your appetite before you get started. A similar phenomenon can occur with UML modeling. The thought of having to produce a complete set of sequence, collaboration, state, deployment, use case, and class diagrams that comprehensively covers each and every use case of the system with a fully detailed dynamic model can intimidate a team right out of object-oriented analysis and design.

The same thought process holds true for determining which constructs are employed within a given modeling technique. For example: is it really necessary to employ both USES and EXTENDS on a use case diagram, or can we live with just USES? My experience has been that the more streamlining that gets done, the better the chances of the modeling effort being carried through.

Write the User Manual Before You Design the Classes

One of the old saws of programming is to write the user manual before you write the code. This was good advice when I learned it, and it's still good advice today. In the days of structured methods, and in the early days of object-oriented methods, it was seldom followed. In his use case-driven modeling approach, Jacobson codified this maxim into a series of steps that work for object orientation and can be described using UML. Each step builds upon the previous step in a traceable manner, so that ultimately, management can enforce this approach as a design paradigm and verify that it has been followed at each step in the analysis and design process.

The key to understanding the essence of Objectory and use case-driven object modeling at the fundamental level is simple: write the user manual before you design the classes. Keeping this idea in the front of your mind will help guide you as you travel through the maze of UML static and dynamic model notations. Each use case represents a portion of the user manual, and should be written that way if the goal of your use case analysis is to produce an object model.

Organize Use Cases into Packages

As you begin to write the user manual for your system one use case at a time, you will immediately run into the need for a high-level organization of use cases. UML lets you organize your use cases into packages. These are represented as tabbed-folder icons. Each package should consist of at least one use case diagram, which will serve as a context diagram under which you can link all the use case descriptions along with the design-level dynamic model views for each use case. Some projects start with a top-level breakdown of one package per top-level menu. While this breakdown does not always represent the final breakdown, it's sometimes a helpful starting place.

Use the Objectory Stereotypes

Since we're driving the entire design process from the use cases, it makes sense to focus strongly on describing them in the "right" way. While it's becoming increasingly popular to employ use cases as an alternative to requirements specifications and for business process modeling, and while these styles of use case modeling have somewhat different guidelines, most projects I've run across still view use cases as a way to get to an object model.

Jacobson's original OOSE/Objectory process included a phase called Robustness Analysis, wherein use case descriptions were analyzed to determine a rough first cut at a collaborating set of objects. While doing this analysis, Jacobson proposed classifying the objects identified into Interface Objects, Control Objects, and Entity Objects.

This small, quick modeling step produces an amazing set of benefits. It helps people write use cases correctly, identify client/server and model-view-controller design information early, and perhaps most important, identify reusable objects by enabling a quick breadth-first pass across all the use cases. It also fills the void between requirements analysis and detailed design.

Unfortunately, for some reason, the notation for Robustness Analysis (three easy-to-draw symbols), only partially survived the transition into UML. The notation still exists, but has been banished to a separate document called the Objectory Process Specific Extensions, and tool support is often lacking. I teach Robustness Analysis as an integral part of describing use cases (the diagram becomes a sanity check for the text), and have found that students readily adapt to this object shorthand.

Important Questions

You can reduce the entire domain of object-oriented analysis and design to two simple questions: First, what are the objects in the system? Second, how is the required system behavior distributed among these objects?

While this is somewhat of an over-simplification of a subject that has been the topic of thousands of pages of methodology textbooks, it fundamentally isn't too far off the mark. If you've identified the right set of objects to build, and if you've done a good job of allocating the desired system behavior to the most appropriate set of classes, your project should be in good shape. The tricky part is really the innocent-sounding phrase "done a good job of allocating behavior"; this is where experienced object-oriented designers earn their living.

Drive the Static Model from the Dynamic Models

No matter which process you decide to use with UML, it's good practice to drive the design of the static model (class diagrams) from the dynamic models, starting from use cases at the high level, and particularly leveraging the UML Sequence Diagram to allocate behavior among your classes. This philosophy, which has its roots in Jacobson's OOSE/Objectory process, was first explained to me around 1993 by a friendly Objectory consultant. As I've continued to teach it as a design style over the last four years, I've grown increasingly convinced of its wisdom and (thus far) universal applicability.

The essence of the idea is this: we can start out and get a rough approximation of the core set of objects in a system by following an Object Modeling Technique-like strategy of identifying "real-world" or "problem domain" objects using techniques such as looking for nouns in the problem statement. Sometimes, we can make intelligent guesses as to when a particular class might be an appropriate container for a specific operation; however, often in the process of object-oriented design, we find that the original guesses that we made when considering the static models in the absence of exploring the use cases were naive.

Based on my experience, the reality of object-oriented analysis and design is that the only really good way to approach the (difficult) problem of allocating behavior among a set of classes is to explore the use case at a detailed (message passing/method invocation) level. Whether formally or informally, most senior object-oriented designers I've met arrive at their designs this way. When the approach is informal (not visible), a cloud of mystery sometimes surrounds how a designer arrived at a specific solution from a given set of domain objects and use cases. Often, this cloud of mystery is deepened by oblique explanations using a litany of jargon such as "multiple polymorphic encapsulated interfaces." This tends to limit the amount of useful design review that can be accomplished by team members and leaves the intrepid programmer free to implement as he or she sees fit.

In my experience, however, this design approach is best accomplished using a sequence diagram in UML (see "How the UML Models Fit Together" Focus on UML, page SR4, for an example of a sequence diagram), with the original (requirement-level, user manual view) text of the parent use case shown along the left margin, and the actual detailed dynamic behavior, showing each method invocation and the message that invokes it, in the body of the diagram. Showing the detailed design and the requirement-level textual use case description on the same page provides a quick "eyeball" requirements trace, which verifies that, for at least this use case, your design matches the requirements. Simply repeat this for all the use cases of your system, and you have a traceable design.

While drawing the sequence diagrams, you'll identify specific operations and assign them to specific objects within your design. You're actually building the static class model, even though you're drawing dynamic model (sequence) diagrams at the same time. The sequence diagram is the vehicle that teaches us how much we don't know when we explore the object model in the abstract.

Defer Assigning Operations to Classes

Don't worry too much about specifying which operations go in which classes during the analysis phase of your project. You'll probably get the mapping wrong anyway, except in the most obvious cases (and sometimes even then). Experience teaches that these behavior allocation decisions are best made very carefully, one at a time, as the dynamic models are explored.

Keeping this separation in mind (Analysis: what are the objects? Design: how is the behavior allocated?) helps project teams define the boundary between analysis and design. Our original Unified Object Modeling process approach used the Object Modeling Technique notation at the analysis level, and the Booch notation for design. The Object Modeling Technique was applied during analysis using the Booch method for detailed, design-level models. With UML, these notations have been merged into a single, Object Modeling Technique-flavored class diagram. As the line between analysis and design notations has blurred, project teams often experience difficulty in understanding where the analysis and design boundary is.

Even though I teach an iterative and incremental process, a requirements review and a design review must be included at some logical point. If I'm reviewing an analysis model, I'm not particularly concerned whether or not the classes have operations showing (in most cases, I'm just as happy if they don't). I'm looking for a good set of domain classes and a comprehensive use case model. For a design review, however, all operations should be accounted for, and there must be visual traceability between the requirements and the design on the sequence diagrams. The designer must also be able to defend his or her decisions as to why any given operation was placed in a particular class.

Simply Successful

The most important things to keep in mind as you apply UML to your project are to keep it simple, write the user manual first (one use case at a time), and get your project team on the same page regarding process. Remember, UML specifies a notation, not a process. The most successful projects I've seen are adopting use case-driven, iterative, and incremental approaches. If you tailor your process to the individual parameters of your project and to the skill set of your team, your UML project will be marked for success.

posted on 2008-11-02 10:23  Jackey_Chen  阅读(472)  评论(1编辑  收藏  举报