A Class Model defines the overall static structure of a subsystem. The best way to think of it is that it is a skeleton on which one drapes the activities that one needs to resolve the functional requirements of the subsystem. While one does not have to etch a UML model in stone tablets, one should think about that static structure before beginning any other development on a subsystem. That static structure also provides a strong bridge to the customer's problem space, especially for OOA modeling. To the extent that the Class Model abstractions reflect the fundamental structure of the customer's environment, the application will have long-term stability.
The subject matter of the subsystem defines the primary problem space. One then abstracts the entities, relationships, and responsibilities from that problem space that are necessary to resolve the functionality of the subsystem. In the MBSE approach one tailors the abstractions to the subject matter in hand. Thus the abstractions will be unique to the subsystem and any reuse will be at the subsystem level. There are a couple of reasons for this:
(1) It simplifies the subsystem. One is limited only to the functional requirements that pertain to the subsystem. Subsystem interfaces (see Application Partitioning category) provide decoupling so that one does not have to think about other requirements. This will be eventually reflected in simplified dynamics as well.
(2) It narrows the focus. One can concentrate exclusively on the subject matter of the subsystem. This can have substantial benefits for larger applications because subsystems can be developed largely in parallel.
(3) Recognizing subject matter invariants is easier. This is a direct result of narrowed focus. Without the distraction of unrelated requirements and "boilerplate" one can recognize and abstract the fundamentals of the subject matter (see category on Invariants and Parametric Polymorphism). That can lead to greatly reduced code size, improved reliability, and long-term maintainability.
(4) It enables large scale reuse at the subsystem level. Since the subsystem resolves only one suite of functional requirements and is encapsulated behind an interface, it can be reused in any context where the subject matter is relevant. Since there is no bleeding of cohesion or context dependencies on other requirements, that ensures plug & play reuse.
The Class Model is place where OO abstraction is most prominent. That's because the Class Model is where one defines what the application abstractions are. It is also the place where we strive to make the application structure map as closely as possible to the customer's problem space. (Since customers introduce change in a manner that will cause minimal disruption of their existing infrastructure, it figures that if the software structure reflects the existing infrastructure faithfully such changes will also have minimal impact on the software.) This is particularly true at the OOA level where MBSE is practiced.
Before getting into the details of Class Modeling I need to provide some definitions:
Object. An object abstracts an identifiable entity in the subject matter space. The entity may be concrete or conceptual. An object is an abstraction because it only identifies the subset of properties of the entity that are relevant to the problem in hand and it tailors those properties. In OO development properties are defined solely in terms of responsibilities.
Instance. An instance is an object that is instantiated in software. This may seem a bit pedantic, but it is sometimes important to distinguish between to life cycle of an entity in the problem space and its life cycle in a software application.
Class. A class defines a set of entities that share exactly the same suite of knowledge and behavior responsibilities. Thus a class defines both a set of identifiable entities in the problem space and a set of properties that we abstract in the application space.
Relationship. A relationship defines a logical connection between members of one class and members of another class. In a Class Model the relationship only defines a limited set of characteristics about the static structure of the relationship. It does not define participation in the relationship by individual members of the sets. (Relationships are so important to OO development in general and MBSE in particular that I will discuss them in their own category.)
Responsibility. A responsibility is simply an abstract property of an object. In OO development an object can only have two sorts of properties: knowledge responsibilities, what the object is supposed to know; and behavior responsibilities, what the object is supposed to be able to do. Thus we cannot directly attribute responsibilities like Purpose or Saintliness to objects; any such characteristics the entity may have in the problem space must be cast in terms of things it must know or be able to do. This sort of casting is crucial to OO abstraction.
Implementation. It is important to recognize that defining a responsibility is quite different than defining the actual knowledge or behavior. Defining responsibilities is akin to defining requirements -- we define what the object must know or do but not how it knows or does things. The details of how an object knows or does things is known as its implementation specification and we do not deal with that specification in a Class Model. A major goal of OO development is to hide such implementation details behind an interface so that other objects cannot depend upon it.
Interface. To solve the subsystem's problem, we need to have objects collaborate across relationships in some disciplined fashion (i.e., a solution algorithm). To hide the implementation of responsibilities we need some way to access them during collaboration without exposing them. Interfaces provide a mechanism for decoupling the actual implementation from any collaborating objects. The collaborating objects only need to understand the interface. (The developer maps the interface to specific responsibility implementations "behind the scenes".)
[At the OOPL level interfaces are extremely important. The OOPLs do not use a class system base in set membership directly. Instead the OOPLs define a type system that essentially maps into an interface. That is, a type system defines how one accesses the properties of an object. While both class and type systems map with each other unambiguously because they both define a set of properties, they are quite different viewpoints. In OOA/D we are concerned with the class system view and interfaces appear as messages to which an object will respond during collaboration.]
Class Modeling is basically about defining object responsibilities, organizing them into classes, and then defining relationships and interfaces as a skeleton for detailed collaborations. All of these things are abstracted from the problem space(s) that define the subsystem in hand. Generally Class Modeling is the first thing one does when attacking a new subsystem. Typically the process progresses through the sequence: identify objects, identify responsibilities, and identify relationships. However, creating a class model is inherently an iterative process. (I describe some mechanical techniques in the category Processes.)
I will deal with some specialized topics for extracting objects from problem spaces in subsequent posts in this category. (They are specialized in the sense that one does not often see them explicitly in the literature.) However, Class Modeling is a very complex subject. Probably the most comprehensive book on Class Modeling is Leon Starr's "Executable UML: How to Build Class Models" -- and it only deals with OOA. I highly recommend that book.