TIP For those who are impatient . . . If you already understand objects, you don’t need convincing that UML is a great thing, and you just want to start learning the UML notation right away, skip ahead to Chapter 2.
IN UML, the L is for language, one of the definitions of which is “any means of communicating,” according to the Merriam-Webster Dictionary. That is the single overriding purpose of UML, or the Unified Modeling Language: to provide a comprehensive notation for communicating the requirements, architecture, implementation, deployment, and states of a system.
UML communicates these aspects from the particular perspective of Object Orientation (OO), in which everything is described in terms of objects: the actions that objects take, the relationships between the objects, the deployment of the objects, and the way the states of the objects change in response to external events.
The starting point in this chapter will be an overview of Object-Oriented Analysis and Design (OOAD), focusing in on the three most important concepts it encompasses—objects, analysis, design—because to understand UML, you first must understand these broader concepts. If you’ve programmed with any OO language, then you’re probably already familiar with a lot of these ideas, so I’ll keep this discussion brief. Besides, a full discussion of OOAD is beyond the scope of this book. If you want to explore OOAD further, you should read Booch’s Object-Oriented Analysis and Design with Applications.1
Next, I’ll discuss the results of the OOAD process, namely, a model. I’ll take a bit of a diversion to discuss the nature of models, how you use them, and why they’re important.
For the rest of the chapter, I’ll be focusing on UML, looking at what it is, and— perhaps more importantly—what it isn’t. But before I get started into the nitty gritty of all the different UML elements and diagrams and what the notation looks like (I’ll save that for the next chapter!), I’ll be showing you some UML diagrams from the case study that I’ll be developing in detail in the next part of the book. Now these diagrams aren’t there to scare you off: quite the contrary. When you start to look at some real-world UML, you’ll see how intuitive it is, and how you can understand much of it without any formal teaching.Objects
Many modern programming languages depend largely or exclusively on the concept of objects: a close syntactic binding of data to the operations that can be performed upon that data. In these Object-Oriented languages—C++, C#, Java, Eiffel, Smalltalk, Visual Basic .NET, Perl, and many others—programmers create classes, each of which defines the behavior and structure of a number of similar objects. Then they write code that creates and manipulates objects that are instances of those classes.
One reason why objects are a powerful programming technique—the reason most often touted in the early literature on Object-Oriented Programming— is that programmatic objects map naturally to real-world objects. Suppose, for example, that your company has to deal with orders. These orders would probably have an ID number and contain information on products. You could create Order objects, which would map to these real-world objects, and which would have properties such as ID and ProductList. You’d probably want to be able to add a product to the order and to submit the order, so you could write AddProduct and SubmitOrder methods. This mapping between objects in the real world and more abstract code objects encourages programmers to think in the problem domain, rather than in computer science terms. This benefit has perhaps been overstated, however; unless you’re building a simulator of a real-world process, such surrogate “real-world” objects form just the surface of your system. The complexity of your design lies underneath that surface, in code that reflects business rules, resource allocation, algorithms, and other computer science concerns. If you only use objects to reflect the real world, you leave yourself with a lot of work.
A more important benefit of classes and objects is that they form a nice syntactic mechanism for achieving some classic aspects of well-designed code:2
Encapsulation. The goal of encapsulation is to expose only enough of a module or subsystem to allow other modules to make use of it. Object-Oriented Programming allows you to specify the degree of visibility of elements of your code, so that client code is restricted in what it can access. Thus, you can syntactically seal off implementation details, leading to more flexibility and maintainability in your system.
Loose coupling. Coupling refers to the ways in which and degrees to which one part of the system relies on the details of another part. The tighter the coupling, the more changes in one part of the system will ripple throughout the system. With loose coupling, the interfaces between subsystems are well defined and restricted. What lies beyond those interfaces can change without any changes needed in the client sub systems. Object-Oriented Programming supports loose coupling by allowing you to define and publish a class’s methods without publishing how those methods are carried out. This principle goes even further in OO languages that support interfaces (described later in this section).
Strong cohesion. Cohesion refers to the degree in which elements within a subsystem form a single, unified concept, with no excess elements. Where there is high cohesion, there is easier comprehension and thus more reliable code. Object-Oriented Programming supports strong cohesion by allowing you to design classes in which the data and the functions that operate on them are tightly bound together.
Does OO force you to have these quality attributes in your code? I wish! No matter the language, you can write shoddy code with no encapsulation, pathological coupling, and no cohesion. Furthermore, some OO languages are less rigid than others in how much they require you to design around objects. But OO languages certainly support these quality attributes if you take the time to pursue them.
The key concepts in Object-Oriented Programming are these:
Classes. A class is the definition of the behavior and properties of one or more objects within your system. A class binds the data (attributes) of an object to the behavior (operations) that it can perform.
Attributes. An attribute is a data value or state that describes an object and helps you to tell one object from another of the same class. It seems that every new OO language author feels the need to distinguish their language by coming up with new terminology. In some OO languages, these data values are called properties or member variables or member data; but in UML, the proper term is attributes.
Operations. An operation is a behavior or function that an object can perform. Depending on the OO language, these might be called methods or member functions or even messages. The last term, messages, comes from Smalltalk, one of the earliest OO languages, in which all objects communicated by sending messages to each other. You’ll see a similar use of the term message when we study Sequence Diagrams.
Objects. An object is an instance or specific example of a class. If Dog is the class, then Betsy, Ladi, Patches, Jake, Radar, and Frosty are specific instances of the class found in my house. The attributes of the class have specific values within an object of that class; and the operations of a class operate on the attributes of individual objects.
Inheritance. This concept indicates that one class (the superclass) provides some common or general behavior inherited by one or more specific classes (the subclasses). The subclasses then provide more or different behavior beyond that defined in the superclass. For example, besides the Dogs, I have Cat objects and Horse objects that live on my property. Each class has unique behaviors: Dogs must be walked, Cats use the litter box, and Horses drop manure that must be scooped up and thrown in the manure pile. Yet all classes have some common behavior: they must be fed, and they must have vet visits. So I can define a superclass, Pet, and have my subclasses, Dog, Cat, and Horse, derive their shared behavior from the Pet class. In UML, this concept is known under the slightly different term of generalization, in which a superclass provides the generalized behavior of the subclasses. It’s really the same concept, but just looking at it the other way up.
Components. A component is a collection of related classes that together provide a larger set of services. Components in your system might include applications, libraries, ActiveX controls, JavaBeans, daemons, and services. In the .NET environment, most of your projects will require component development.
Interfaces. An interface is a definition of a set of services provided by a component or by a class. This allows further encapsulation: the author of a component can publish just the interfaces to the component, completely hiding any implementation details.
Each of these concepts will be explored in more detail as I discuss the UML diagrams that represent them.
blog comments powered by Disqus