This article was originally published on Medium.
Think of pizza. The imagined smell of saucy, cheesy, spicy pizza baking in the oven is smashing me. Sometimes you want new toppings, other times, you want a different base. Many different ingredients create it. Each of these ingredients is separate components, but they interact and complement one another. They all exist within the greater system, in this case, the pizza.
You got that straight. In this article, we will deal with UML’s Component Diagram.
Component diagrams are used to visualize how a system’s components interact (gee!) and what relationships they have among them. For the purpose of UML, the term “component” refers to a module of classes that represent independent systems with the ability to interface with the rest of the system. As we’re able to identify these interfaces, we’re able to find parts of the system that can be replaceable. In other words, we able to find plugin components.
Finding plugin components allow us to reuse these components in other projects. It also helps us structure our work by dividing that work off to a few developers or independently running sub-teams.
Back to the pizza, but now more specifically. Think about Hawaiian pizza on a restaurant menu. Probably, you will not find the pizza’s preparation and cooking methods. The menu just states the pizza ingredients, such as ham, pineapple, and bacon pieces over a red sauce (to be perfectly specific). By listing all of the ingredients, the customer can get a better idea of whether or not they’d enjoy the pizza. It is the same for the Component diagram. Unlike the other diagrams, the component ones are focused on high-level structure and not their methods and specific implementations. It’s a kind of a bird’s-eye view of your software system.
When you are building a Component diagram, the first step is to identify the basic components used in the system.
A component is a logical unit block of the system, a slightly higher abstraction than classes. It’s a subsystem if you wish. When subsystems are connected, it creates a single system.
Let’s assume we want to create a small family Pizzeria system. Our basic components will be:
- Pizzaiolo — a professional pizza maker, as climbed by Oxford.
- Customer — the actual pizza’s consumer (pizza eater, the same one that possibly will enjoy Hawaiian pizza).
- Waiter — is “The One Who Waits”. Never mind, I’m just playing associations.
In UML, a component is represented as another box with this puzzle symbol in the top right-hand corner.
Here you can see the basic components of our Pizzeria. Cool? Not really. This information is not enough to tell us what we really need to know. Each component has a particular relationship to the other component through the interface it provides. The existence of these interfaces is the most interesting part.
Let’s expand our diagram a little bit. We’ll add some adornments to our Customer component.
Take a look at a diagram. I’ll start by talking about the Order and Payment. When a customer comes to the pizzeria, first, he should select and order the pizza. Right? The pizza party is usually finished by paying the bill. In Component language, Order and Payment are interfaces that our Customer provides (realizes or implements). The purpose of a provided interface is to show that a component offers an interface for others to interact with. This kind of interface is represented by a solid line with a lollipop at the end and a name over it.
Now, to provide the specific payment, the customer needs to know how much he needs to pay. The half-circle (also called “socket”) at the end of the connecting line represents the required interface. The meaning of it is that our honest customer expects to receive a check, provided by some other component (Waiter!) to be able to achieve its responsibilities.
To summarize, the interface describes a group of operations used (required) or created (provided) by components.
Our basic components are defined. Next, identify all of the relevant libraries needed for your system.
Component diagrams do not purely focus on what you implement. All third-party implementation dependencies must also be identified and integrated into the diagram where relevant. I will expand on third-parties later.
Finally, come up with the connections found between all these components. See how components can plug together. This is exactly the rationale behind this design.
The components can be connected loosely or tightly, like a belt on trousers before (and after) eating pizza.
Let’s start by talking about how we can loosely connect different components together.
It’s the main connection type of Content diagram. This is where we can define our pluggable parts of the system. When one component provided interface matches another component’s required interface, it’s called an assembly relationship.
Here you can see Customer and Waiter are connected like a puzzle. The components are plugging together. But you can also unplug them easily. The connection between them is loose. You can popup the Waiter service and replace it with something else, such as Shift Supervisor, or maybe the Pizzaiolo in the flesh will take the order. This is a replaceable piece of our system.
The tight connection between components is represented by a solid line between two components. It indicates that it’s not going to be so easy to replace one of these components. They are tightly coupled together. Let’s think of our example, assume that the customer can select pizza only from the pizza menu. His order is tightly dependent on the Menu component.
A Customer can not provide the order without a Menu. Getting rid of one of them will probably, require some rework for implementing this replacement.
Now, let’s take a look at a kind of a completed though rather small, Component diagram.
You can see, the diagram has some new elements that we are not yet looked at. First of all, we have an outer component diagram here, called Pizzeria. It’s our whole system. The other components sitting inside of this box are parts that make up the Pizzeria. It consists of Pizzaiolo, Waiter, and Customer. The Customer is tightly connected to the pizzeria’s menu.
A couple of other things to look at is the interaction with the outside world from the Pizzeria. Notice small squares sitting on the bounds of the Pizzeria component. These squares are called ports, and they specify a separate interaction point between the component and the environment.
In the Pizzeria example, ports represent the third-parties, such as a Cashier Service, used by Waiter; a Grocery Store, that provides the groceries required by Pizzaiolo; Pizzerias Ranking Service, which depend on review, provided by satisfied (or not) Customer.
Since we don’t implement these services, it’s enough to show only the interaction point and the dependency direction (incoming or outgoing). Dependencies are represented by dashed lines linking one component (or element) to another.
That’s all. Ciao ciao!