Classes and interfaces
Use class diagrams to show important types and contracts, not every trivial implementation detail.
Class diagrams are the UML view most closely associated with object-oriented design. They are useful when you need to understand the static structure of a model: which classes exist, what roles they play, and how they depend on one another. They are less useful when the real question is about runtime flow or object state over time.
In an order-management domain, a class diagram can show whether Order, Payment, Shipment, and Notification are modeled as meaningful concepts or whether the system has collapsed into generic service types and data containers.
A class diagram is strongest when you need a structural map of the model. It can show which concepts deserve first-class representation and whether dependencies flow in a sensible direction.
For Java developers, class diagrams are especially useful during modeling and refactoring because they reveal whether the code structure matches the conceptual design. They can also expose over-centralized services, missing value objects, or interface placement problems.
The diagram should stay selective. If it tries to show every field and every type in the codebase, it stops being a design aid and becomes noise.
Use class diagrams to show important types and contracts, not every trivial implementation detail.
The value is often in the relationships: ownership, usage, composition, and direction.
A class diagram is not the right tool for understanding message order, retries, or state changes over time.
package org.javaomnibus.ecommerce.uml;
public final class Order {
private final OrderId orderId;
private final Customer customer;
private Payment payment;
private Shipment shipment;
public Order(OrderId orderId, Customer customer) {
this.orderId = orderId;
this.customer = customer;
}
public void attachPayment(Payment payment) {
this.payment = payment;
}
public void attachShipment(Shipment shipment) {
this.shipment = shipment;
}
}
public interface PaymentAuthorizer {
Payment authorize(Order order);
}
record OrderId(String value) {}
record Customer(String customerId) {}
record Payment(String paymentId) {}
record Shipment(String shipmentId) {}
Class diagrams can create false confidence if they look clean while runtime behavior is still chaotic. Use them for structure questions only.