Archyno
UMLDiagramy struktury

Příklady diagramů komponent

Pět diagramů komponent systémů, na jakých jste nejspíš dělali. Každý má rozhodnout jednu otázku: kdo smí koho volat, co by musela splnit náhrada a kde vede závislost opačně, než by měla.

9 min čteníUML 2.5.18 z 23

«use»«use»Web storefrontMobile app«interface»ICatalogCatalog service
Example one. Two clients, one contract, one provider - the dashed arrow with the hollow triangle means "I implement this", the plain dashed arrow means "I need this".

01How to read the five

Every diagram below uses the same three marks, and if you can read them you can read all five: a component is a box with the plug icon, an «interface» is a box naming a contract, and the arrows say which side of that contract each component is on. A dashed arrow with a hollow triangle means I implement this. A plain dashed arrow means I need this. The full set is in component diagram symbols, and the reasoning behind the notation is in the component diagram guide.

They are ordered by how often the shape turns up rather than by complexity. Each one names the question it settles, because a component diagram that settles nothing is the most common kind and the least useful: five boxes, five arrows, and no statement anybody could disagree with.

021. Two clients, one contract

The figure at the top of this article. A web storefront and a mobile app both need product data; one catalogue service provides it. The interface is drawn once, between them.

That single box is the entire point of the example. Before it existed, the two clients had two different ideas of what "the catalogue" returns, and the difference lived in whichever one was written second. Naming ICatalog forces the question of what the contract actually is, and once it is named, a change to it is visibly a change to two consumers rather than an edit to one service.

032. Ports and adapters

«use»«use»HTTP API«interface»IOrderingOrdering core«interface»IOrderStorePostgreSQL adapter
Example two. The core sits between two contracts and depends on neither implementation: the HTTP API calls in through IOrdering, and the database is reached through IOrderStore.

Read the arrows and notice what the Ordering core does not touch. It does not depend on HTTP and it does not depend on PostgreSQL. It realizes one contract and requires another, and both of those are boxes it could have been handed by anybody.

This is the shape people mean by hexagonal architecture, ports and adapters, or clean architecture, and a component diagram is the cheapest way to check whether a codebase actually has it. If the core box has an arrow pointing at a database component rather than at an interface, the pattern is aspirational: something in the middle imports the driver.

043. One contract, two implementations

«use»Order service«interface»IBillingMainframe billingBilling service v2
Example three. The migration diagram: both billing implementations realize IBilling, so the order service cannot tell which one it is talking to.

This is the diagram to draw before a replacement, not after. The claim it makes is precise and testable: everything the order service needs from billing is in IBilling, so a second implementation of that interface can be switched in without the order service changing.

It is also the fastest way to find out that the claim is false. If somebody says "the new service cannot do statement PDFs", then statement PDFs were part of the contract and are missing from the interface, and the diagram was wrong before the migration was. That conversation costs ten minutes at a whiteboard and three months in production.

Once the old implementation is gone, delete it from the diagram. A component diagram that still shows the mainframe two years after it was switched off is the reason people stop trusting the diagrams.

054. A plugin architecture

«use»Editor host«interface»IExporterPNG exporterMermaid exporterSparx .qea exporter
Example four. The same shape as example three, meaning something different: the host is not choosing one exporter, it is designed to accept any number of them.

Topologically this is example three with a third implementation added, and that similarity is worth sitting with: replaceability and extensibility are the same drawing. What differs is intent. In a migration the extra realization is temporary; in a plugin architecture it is the product.

The reading technique that pays here is to cover the right-hand column with your hand. What remains - the host and IExporter- is everything a fourth exporter author needs to know. If the answer to "can I write my own exporter?" requires reading the host's source, the interface is under-specified and the diagram has just told you so.

065. The one with a cycle

«use»«use»Orders service«interface»IShippingShipping service«interface»IOrders
Example five. Orders needs shipping, shipping needs orders. Neither can be deployed, tested or replaced without the other, and the diagram makes that visible in one glance.

Two services, each realizing a contract the other requires. Nothing here is illegal UML and nothing on the diagram is wrong - the drawing is an accurate picture of a system that is going to be difficult, which is precisely what you want a diagram to be able to say.

A cycle between components means neither can be understood alone: no independent deployment, no test in isolation without a stub of the other, and a replacement of either has to satisfy a contract the other one is simultaneously depending on. On a class diagram a cycle is a smell; between deployable units it is a schedule risk.

The usual fixes are visible on the same picture. Move what shipping needs from IOrders into an event the orders service publishes, so the arrow becomes one-way. Or extract the shared part into a third component both depend on, which turns the cycle into a fan-in and puts you back at example one.

In one line each

  1. 01Fan-in (example 1): one contract with several consumers - name it once, change it once.
  2. 02Chain (example 2): the core depends on interfaces at both ends, on implementations at neither.
  3. 03Two realizations (example 3): the migration claim, written down where it can be falsified.
  4. 04Many realizations (example 4): the same drawing as a migration, meant permanently.
  5. 05A cycle (example 5): an honest picture of a system that cannot be deployed or replaced piecemeal.
  6. 06If a diagram settles no argument, it is decoration - delete it rather than maintaining it.

To draw one of these against your own system, the step-by-step version is in how to draw a component diagram. For where these components run rather than what they promise each other, that is a deployment diagram.

07Časté dotazy

Jak vypadá dobrý příklad diagramu komponent?

Nejužitečnější příklad je ten nejmenší, který rozhodne spor: dvě nebo tři komponenty, rozhraní mezi nimi a nic dalšího. Diagram sdíleného katalogu, který používá web i mobilní aplikace, řekne víc než stěna čtyřiceti boxů - čtenář ho udrží v hlavě naráz a umí ho ověřit proti kódu.

Lze diagramem komponent zobrazit mikroslužby?

Ano a je to jedno z jeho lepších použití. Každá služba je komponenta a každé publikované API je rozhraní, takže diagram přesně říká, která služba smí volat kterou smlouvu. Nesmí ale ukazovat, kde ty služby běží - to je diagram nasazení a míchání obojího vyrobí obrázek, který nejde zkontrolovat.

Kolik komponent má být na jednom diagramu?

Tři až zhruba devět. Pod tři není co kreslit a nad devět či deset čtenář přestane sledovat šipky a začne jen přebíhat očima - tehdy se diagram mění v dekoraci. Velký systém se kreslí jako více diagramů, jeden na každou otázku.

Má se databáze kreslit jako komponenta?

Kreslete adaptér, ne databázi. Diagram je o smlouvě, na které váš kód závisí, takže komponenta PostgreSQL adaptér realizující rozhraní IOrderStore nese tu užitečnou informaci. Samotný databázový produkt je infrastruktura a patří do diagramu nasazení.

Všechny články