Welcome to the course! Given your extensive background in software engineering, you've likely navigated and built complex systems with frameworks like Laravel and Vue.js. This course is designed not to teach you how to code, but to formalize the fundamental computer science principles that underpin the tools and patterns you use every day. We'll start by building a shared visual language to discuss software architecture.
This first lesson focuses on reading and interpreting Unified Modeling Language (UML) class diagrams. Think of these as the architectural blueprints for object-oriented software. Mastering this visual language will provide a precise way to analyze, discuss, and design system structures, which will be invaluable as we move on to explore design principles and patterns.
What are UML Class Diagrams?
At its core, a UML class diagram is a static, structural diagram that describes the architecture of a system by showing its classes, their attributes, methods, and the relationships between them. For a developer, this is a powerful tool. It allows you to understand the structure of a complex system without reading thousands of lines of code, to spot potential design flaws early, and to communicate complex designs clearly to your team.
The Building Blocks: Classes, Attributes, and Operations
The fundamental component of a class diagram is the class itself, represented as a box. This box is typically divided into three compartments. To get a clear visual and conceptual overview of these components, please watch the first part of the following video from Lucid Software.
This video provides a clear and concise introduction to the basic components of a UML class diagram, including the structure of a class box, attributes, methods, and visibility notations.
Please watch the segment from the beginning. It will walk you through creating a simple class and explain the standard notation for its name, attributes (fields), and methods (operations), including the crucial concept of visibility.
As the video explained, the key elements within a class box are:
- Class Name: The name of the class, written at the top. If the name is in italics, it denotes an abstract class—a class that cannot be instantiated on its own and is meant to be inherited from.
- Attributes: These are the properties or data members of the class, listed in the middle compartment. The standard format is
visibility name: type. - Operations: These are the methods or behaviors of the class, listed in the bottom compartment. The format is
visibility name(parameters): returnType. - Visibility: This defines the access level of attributes and operations, indicated by symbols:
+: Public (accessible from any other class)
-: Private (accessible only within the class itself)
#: Protected (accessible within the class and by its subclasses)
Mapping Relationships: How Classes Interact
The real power of class diagrams comes from illustrating the relationships between classes. These connections define how objects will interact within your system. The most important relationships fall into two categories: "is-a" (inheritance/implementation) and "has-a" (composition/aggregation).
The following reading from a Kansas State University textbook provides an excellent and detailed breakdown of these relationships.
This material clearly defines and illustrates the essential relationships in UML class diagrams: realization, generalization, aggregation, and composition. The distinction between these concepts is fundamental to interpreting system design.
Please read the section titled "Associations". Start from the text Is-A Associations, which covers Realization (implementing an interface) and Generalization (inheritance). Then, continue with the part on Has-A Associations, which explains the crucial difference between Aggregation and Composition. Finally, read the brief section on Multiplicity, which explains how to denote the number of objects in a relationship (e.g., 1, , 1..).
To summarize the key relationship notations from the reading:
| Relationship | Type | Represents | Arrow Type |
|---|---|---|---|
| Generalization | "is-a" | Classical inheritance (a Dog is an Animal). |
Solid line with a hollow, triangular arrowhead pointing to the parent class. |
| Realization | "is-a" | Implementing an interface (a UserRepository implements RepositoryInterface). |
Dashed line with a hollow, triangular arrowhead pointing to the interface. |
| Composition | "has-a" | A strong "part-of" relationship where the part cannot exist without the whole (an Order has an OrderLineItem). Deleting the whole deletes the parts. |
Solid line with a filled diamond on the side of the whole/container. |
| Aggregation | "has-a" | A weaker "part-of" relationship where the part can exist independently (a Department has Employees). Deleting the department does not delete the employees. |
Solid line with a hollow diamond on the side of the whole/container. |
The distinction between aggregation and composition can be subtle. The key question to ask is about lifecycle dependency: if I delete the container object, is the contained object also deleted? If yes, it's composition. If no, it's aggregation. This is directly analogous to how some database relationships are configured with ON DELETE CASCADE.
Putting It All Together: Interpreting a Diagram
Now, let's apply this knowledge to interpret a complete diagram. Examine the following UML class diagram, which models a simple real-world domain.

Let's break down what this diagram tells us:
-
Classes and Interfaces:
Person,Phone,Address,Dog, andCatare concrete classes.Animalis an abstract class, indicated by its italicized name. This means you can't create a newAnimalobject directly; you must instantiate one of its concrete subclasses, likeDogorCat.Petis an interface, denoted by the<<interface>>stereotype. It defines a contract with a single operation:play().
-
Attributes and Operations:
- The
Personclass has attributes likenameandage, and an operationadoptPet(). - Notice the visibility markers. For example,
Person'snameattribute is private (-), while itsadoptPet()method is public (+).
- The
-
Relationships:
- Generalization (Inheritance): Both
DogandCathave a solid-line arrow with a hollow arrowhead pointing toAnimal. This meansDogis anAnimalandCatis anAnimal. They inherit the attributes (name,age) and operations (eat(),sleep()) fromAnimal. - Realization (Interface Implementation): Both
DogandCatalso have a dashed-line arrow pointing to thePetinterface. This means they both implement thePetinterface and must provide a concrete implementation for theplay()method. - Composition:
- There is a solid line with a filled diamond connecting
PersontoAddress. This signifies composition. APerson"has an"Address. The multiplicity1on thePersonside and*(many) on theAddressside indicates that one person can have multiple addresses, and the lifecycle of theAddressobject is tied to thePerson. - A similar composition relationship exists between
PersonandPhone.
- There is a solid line with a filled diamond connecting
- Association/Dependency: The curved, dashed arrow from
Person'sadoptPetmethod to thePetinterface indicates a dependency. TheadoptPetmethod uses or depends on thePetinterface as a parameter type.
- Generalization (Inheritance): Both
This single diagram provides a rich, language-agnostic blueprint of the system's structure. You could use this to build the corresponding classes in PHP, TypeScript, or any other object-oriented language.
As you progress in this course, you'll see how these diagrams are used to model complex design patterns. For instance, here is a diagram for the Decorator pattern, which you might implicitly recognize from systems that use middleware or stackable services.

Conclusion
In this lesson, we've unpacked the visual syntax of UML class diagrams, the "blueprints" of object-oriented design. You are now equipped to read these diagrams and understand the static structure of a software system.
The key takeaways are:
- Classes are represented by boxes with three compartments: name, attributes, and operations.
- Visibility (
+,-,#) controls access to attributes and operations. - Generalization (inheritance) uses a solid line with a hollow arrow.
- Realization (interface implementation) uses a dashed line with a hollow arrow.
- Composition (strong "has-a") uses a solid line with a filled diamond, implying lifecycle dependency.
- Aggregation (weak "has-a") uses a solid line with a hollow diamond.
Now that we have a common language to visualize and describe the structure of classes, our next lesson will introduce the SOLID principles. These are five fundamental principles of object-oriented design that guide you in creating systems that are more understandable, flexible, and maintainable.