Inside the Object-Oriented Toolbox— Mapping between Design & Implementation
“Object-Oriented Programming” has become the most popular design paradigm in the software industry nowadays, due to its capabilities behind producing reusable, customisable and maintainable code. However once a large domain is divided into separate “class”es (a “class” is the “blueprint used to create an object” during runtime) the application code is often scattered across multiple “class”-based program code files; making it difficult to visualize the overall design of the software system.
One solution that the programmers use to visualize the overall design of an “Object-Oriented”-based software system is to draw a “design diagram” illustrating all of its “class”es and “different types of relationships” between them. “UML Class Diagram” is the most popular type of the “design diagram” used for this purpose (see Figure 1).
Although there exists a plethora of internet literature explaining about “Object-Oriented Programming”, “UML” (Unified Modelling Language) and “UML Class Diagrams”; there exists only little literature explaining “how to map a UML Class Diagram to the actual implementation code of a selected programming language”. The main focus of this article is to contribute towards fulfilling this missing “Design Mapping Literature” by using “java” as the selected implementation language.
Mapping a Single Class
Figure 2 illustrates how you could map a “design class” in a “UML class diagram” to a “java”-based “implementation class”. Note that our “class” in Figure 2 has the below characteristics.
- The name of the class is “Person”
- “name” is a “private attribute” of the “Person” class
- “getName()” and “setName()” are “public methods” of the “Person” class
- “populateJobDescription()” is a “protected method” of the “Person” class
UML Class Diagram Relationship Types
Now that we’ve covered how to map an isolated “class”, it’s time to discuss the different types of “relationship”s that could exist between 2 “class”es in a “UML class diagram”. Note that the below is a list of different relationship types that could exist between 2 classes, “ordered from the weakest to the strongest” in terms of the “strength of the relationship”.
- Dependency
- Association
- Aggregation
- Composition
- Generalization
In addition to the above 5 relationship types, “Realization” is a special relationship that exists between a “class” and an “interface”. Note that unlike a class, an “interface” contains “only the specification, but not the implementation”.
Dependency
Class “A” is “dependent” on another class “B” (note the direction of the arrow in Figure 3), if “A” is “using B inside A’s implementation” in one or more of the following cases.
- Case 1 — class “A” has at least a single method that returns class “B”
- Case 2 — class “A” has at least a single method that has class “B” in at least one of its method arguments
- Case 3 — class “A” has at least a single method that uses a “reference” of class “B” inside its method implementation
Association
When “class A has an association with class B” it is stronger than a dependency, since class “A” is able to;
- maintain “attributes” of class “B” inside class “A” AND
- directly invoke “methods of class B” inside “class A’s implementation”
Association relationships can appear inside UML class diagrams in many different flavours.
Uni-Directional Association
Association with Multiplicity
Bi-Directional Association
Reflexive Association
Aggregation
When “class A has an aggregation with class B” it is “stronger than an association”.
Class “A” has an “aggregation” relationship with class “B” if;
- “class A has an instance of class B” BUT
- still “an object made from B can exist on its own even after its corresponding A-based object is being disposed”
Our example in Figure 8 illustrates (“Class A” -> “Car” & “Class B” -> “StereoSystem”) one possible approach in which you could map an “aggregation” relationship modelled between 2 classes.
Note that the following are the possible business requirements behind bumping up the relationship between a Car and a StereoSystem from an association to an aggregation.
- A stereo system can be sold separately without a car (note the “default constructor” inside the “StereoSystem” class).
- A car can be sold separately without a stereo system (note the “default constructor” inside the “Car” class).
- If a car is bundled with a stereo system both need to be sold together.
- If a stereo system is broken after the purchase, the car can still be used.
- If the car is broken after the purchase, the stereo system can still be used.
Composition
When “class A has a composition with class B” it is “stronger than an aggregation”.
Class “A” has a “composition” relationship with class “B” if;
- “class A has an instance of class B” AND
- “an object made from B CANNOT exist on its own after its corresponding A-based object is being disposed”
Our example in Figure 9 illustrates (“Class A” -> “Engine” & “Class B” -> “Piston”) one possible approach in which you could map a “composition” relationship modelled between 2 classes.
Note that the following are the possible business requirements behind bumping up the relationship between an Engine and a Piston from an association/aggregation to a composition.
- Every Engine MUST have a Piston.
- We don’t sell pistons separately, we only sell engines. Thus there can’t be a piston separately sold without an engine.
- If an engine is broken due to some internal error (even other THAN in the PISTON), then customer has to buy (or exchange with) a NEW engine from us bundled with its own piston.
- If the piston is broken and can’t be repaired, the customer has to buy (or exchange) a NEW engine (having its own Piston) from us, since the engine won’t work without the piston.
If the business requirement related with determining the relationship between the Engine and the Piston were less constrained as below, we could have still modelled the Engine<->Piston relationship as a “less constrained aggregation”, instead of a composition.
- Our inventory sells pistons separately, thus a piston can exist without an engine.
Another popular example used to explain composition is Person and IdentityInformation (see Figure 10), since in most of the software systems;
- Each “person” MUST have his/her own “identity information”
- It is pointless to enter “identity information” to a system without a reference to a “person”
Note that some of the existing UML literature refers both “aggregation” and “composition” relationships as “HAS A” relationships.
Generalization
When “class B has a generalization relationship with class A” it is “stronger than a composition”, since “class B is a sub type of class A”. Generalization (also referred as the “IS A” relationship) is the strongest relationship that could exist between 2 classes in a UML class diagram and is related with “inheritance” in Object-Oriented literature.
Our example in Figure 11 illustrates (“Class A” -> “BaseClass” & “Class B” -> “ChildClass”) on how to map a “generalization” relationship modelled between 2 classes.
Unlike other relationships, a change in attributes or methods in the “BaseClass” directly affects the behaviour of the “ChildClass”.
Realization
When “class B has a realization relationship with interface A”, “class B is a sub type of the interface type A”. However unlike Generalization, class B needs to adhere to “only the specification” of interface A. “The implementation of class B can freely evolve on its own as long as it adhere’s the specification of interface type A”.
Our example in Figure 12 illustrates (“Class B” -> “GatewayServiceImpl” & “Interface A” -> “IGatewayService”) on how to map a “realization” relationship modelled between a class and an interface.
In most Object-Oriented programming languages, a class is usually allowed to extend only from one other class; whereas a class is allowed to implement any number of interface types.
UML Class Stereotypes
Once your UML class diagram has expanded up to 20–50 classes, it is often convenient to classify these classes into several “meaningful categories”. In the “UML class diagram” terminology these “meaningful categories” are called “stereotype”s. Some of the most popular UML class stereotypes (see Figure 13) are;
- Entity — UML classes those represent information those are usually persisted in the system (e.g. OrderConfirmation, Invoice, Payment Request)
- Controller — UML classes those contain control logic mostly related to the business logic of the system (e.g. OrderHandler, PaymentScheduler)
- Boundary — UML classes those interact with end users, integration points of the system (e.g. PaymentRequestUI)
Note that Figure 13 is “NOT a UML class diagram”, but an illustration drawn to explain the nature of different UML class stereotypes.
In an actual UML class diagram, stereotypes are indicated in a UML class “above the class name” as illustrated in Figure 14.
It is not a rule of thumb, but in practice, most of the classes “stereotype”d as Entity, Controller and Boundary; respectively map with Data, Logic and Presentation Tiers of the conventional 3-tier architecture (see Figure 15).
Some UML literature use “interface” as a class stereotype in order to identify an interface unambiguously from classes within a UML class diagram (see Figure 16).
Conclusion
The knowledge behind “mapping a UML class diagram to implementation code” aids programmers at least during 2 of their routine encounters as illustrated in Figure 17.
- During “Forward Engineering” — Multiple programmers can work on developing different parts of a newly built software system based on a pre-agreed “UML class diagram”
- During “Reverse Engineering” — Upon receiving the implementation code of a software system with lots of “class”es and carrying no design documentation, programmers can work on visualizing the overall design of the software system based on the program code they already have
Interested in taking that initial step in improving your business by designing and developing a value-driven IT system? Contact Us.