[ Team LiB ] Previous Section Next Section

Operations

Operations are the actions that a class knows to carry out. Operations most obviously correspond to the methods on a class. Normally, you don't show those operations that simply manipulate properties, because they can usually be inferred.

The full UML syntax for operations is:

visibility name (parameter-list) : return-type {property-string}
  • This visibility marker is public (+) or private (-); others on page 83.

  • The name is a string.

  • The parameter-list is the list of parameters for the operation.

  • The return-type is the type of the returned value, if there is one.

  • The property-string indicates property values that apply to the given operation.

The parameters in the parameter list are notated in a similar way to attributes. The form is:

direction name: type = default value
  • The name, type, and default value are the same as for attributes.

  • The direction indicates whether the parameter is input (in), output (out) or both (inout). If no direction is shown, it's assumed to be in.

An example operation on account might be:

+ balanceOn (date: Date) : Money

With conceptual models, you shouldn't use operations to specify the interface of a class. Instead, use them to indicate the principal responsibilities of that class, perhaps using a couple of words summarizing a CRC responsibility (page 65).

I often find it useful to distinguish between operations that change the state of the system and those that don't. UML defines a query as an operation that gets a value from a class without changing the system state梚n other words, without side effects.You can mark such an operation with the property string {query}. I refer to operations that do change state as modifiers, also called commands.

Strictly, the difference between query and modifiers is whether they change the observable state [Meyer]. The observable state is what can be perceived from the outside. An operation that updates a cache would alter the internal state but would have no effect that's observable from the outside.

I find it helpful to highlight queries, as you can change the order of execution of queries and not change the system behavior. A common convention is to try to write operations so that modifiers do not return a value; that way, you can rely on the fact that operations that return a value are queries. [Meyer] refers to this as the Command-Query separation principle. It's sometimes awkward to do this all the time, but you should do it as much as you can.

Other terms you sometimes see are getting methods and setting methods. A getting method returns a value from a field (and does nothing else). A setting method puts a value into a field (and does nothing else). From the outside, a client should not be able to tell whether a query is a getting method or a modifier is a setting method. Knowledge of getting and setting methods is entirely internal to the class.

Another distinction is between operation and method. An operation is something that is invoked on an object梩he procedure declaration梬hereas a method is the body of a procedure. The two are different when you have polymorphism. If you have a supertype with three subtypes, each of which overrides the supertype's getPrice operation, you have one operation and four methods that implement it.

People usually use the terms operation and method interchangeably, but there are times when it is useful to be precise about the difference.

    [ Team LiB ] Previous Section Next Section