UML Diagrams for Program Decomposition

UML Diagrams for Program Decomposition

Introduction: From Words to Code - The Nouns and Verbs Approach

As a beginner programmer, you might think that the hardest part of programming is learning syntax and remembering method names. But experienced developers know the real challenge: identifying the key entities (things) and behaviors (actions) hidden in problem descriptions, then organizing them into working code.

UML (Unified Modeling Language) diagrams are like blueprints for software. Just as an architect draws plans before building a house, smart programmers sketch their class designs before writing code. This guide will walk you through using UML class diagrams to decompose the DiceyLab project step by step, using the powerful “nouns and verbs” technique.

Key Insight: Hand-drawn UML diagrams are thinking tools that help you discover the entities in your problem domain. Once you identify what “things” exist and what “actions” they can perform, the code structure becomes obvious.

Step 1: Entity Discovery - Finding the Nouns and Verbs

The first step in program design isn’t thinking about code—it’s thinking about the problem domain. We need to identify the key entities (nouns) and their behaviors (verbs) from the requirements.

The Nouns and Verbs Technique

When you read a problem description, mentally highlight:

  • Nouns → These become your entities (classes/structures) and attributes (instance variables)
  • Verbs → These become your methods (functions/behaviors)

Let’s apply this to the DiceyLab project requirements:

Analyzing the DiceyLab Problem Statement

Problem Description: “Create a dice simulation where multiple dice are thrown many times to track the distribution of results. The simulation should roll dice, count outcomes, and display statistical results.”

Nouns (Things/Entities):

  • Dice - The physical objects being simulated
  • Simulation - The experiment process itself
  • Results - The collection of outcomes
  • Distribution - The pattern of outcomes
  • Outcomes/Bins - Individual result categories

Verbs (Actions/Behaviors):

  • Roll/Toss - Generate random values
  • Track/Count - Record what happened
  • Display/Print - Show the results
  • Run/Execute - Perform the experiment

Entity Emergence Process

From this analysis, three key entities emerge:

  1. Dice Entity - Represents the dice being rolled
  2. Bins Entity - Represents the result tracking system
  3. Simulation Entity - Represents the experiment orchestrator

Why these entities? Each represents a distinct “thing” in our problem domain with its own:

  • State (what it knows/remembers)
  • Behavior (what it can do)
  • Responsibility (what it’s in charge of)

Example Usage Patterns

// Creating dice
dice = CREATE Dice(2)  // for craps
toss = CALL dice.tossAndSum()

// Tracking results
results = CREATE Bins(2, 12)  // for bins from 2..12
CALL results.incrementBin(10)
numberOfTens = CALL results.getBin(10)

// Running simulation
sim = CREATE Simulation(2, 10000)
CALL sim.runSimulation()
CALL sim.printResults()

Step 2: From Entities to UML - Mapping Nouns and Verbs

Now that we’ve identified our entities, let’s map them to UML class diagrams. In UML, each entity becomes a class with three sections:

  • Top section: Entity name (the main noun)
  • Middle section: Attributes (descriptive nouns - what the entity knows)
  • Bottom section: Methods (verbs - what the entity can do)

Entity 1: The Dice Entity

Nouns associated with Dice:

  • numberOfDice (how many dice in the set)
  • sides (implied - standard 6-sided)

Verbs associated with Dice:

  • roll/toss (generate random values)
  • sum (add up multiple dice)
  classDiagram
    class Dice {
        -int numberOfDice
        +Dice(int numberOfDice)
        +int tossAndSum()
    }

Entity Analysis:

  • What it knows: How many dice it represents
  • What it does: Generates random dice rolls and sums them
  • Why it exists: Encapsulates the concept of “a set of dice”

Entity 2: The Bins Entity

Nouns associated with Bins:

  • minValue, maxValue (the range of possible outcomes)
  • bins/counts (the collection of result tallies)
  • value (specific outcome being tracked)

Verbs associated with Bins:

  • increment (add to a count)
  • get (retrieve a count)
  • track (overall responsibility)
  classDiagram
    class Bins {
        -int minValue
        -int maxValue
        -int[] bins
        +Bins(int minValue, int maxValue)
        +void incrementBin(int value)
        +int getBin(int value)
    }

Entity Analysis:

  • What it knows: The range of values and current counts
  • What it does: Tracks frequency of different outcomes
  • Why it exists: Encapsulates the concept of “statistical collection”

Entity 3: The Simulation Entity

Nouns associated with Simulation:

  • numberOfDice, numberOfTosses (experiment parameters)
  • dice (the dice being used)
  • results (the bins collecting data)

Verbs associated with Simulation:

  • run (execute the experiment)
  • print (display results)
  • orchestrate (overall coordination)
  classDiagram
    class Simulation {
        -int numberOfDice
        -int numberOfTosses
        -Dice dice
        -Bins results
        +Simulation(int numberOfDice, int numberOfTosses)
        +void runSimulation()
        +void printResults()
    }

Entity Analysis:

  • What it knows: Experiment parameters and references to other entities
  • What it does: Coordinates the overall experiment
  • Why it exists: Encapsulates the concept of “the experiment process”

Step 3: Entity Relationships - How Things Interact

Now let’s discover how our entities relate to each other. In object-oriented design, entities don’t exist in isolation—they collaborate to solve the problem.

Relationship Discovery Through Verbs

Look at the verbs associated with each entity:

  • Simulation needs to use Dice (to get random values)
  • Simulation needs to use Bins (to record results)
  • Dice and Bins don’t directly interact with each other

This gives us our entity relationship diagram:

  classDiagram
    class Dice {
        -int numberOfDice
        +Dice(int numberOfDice)
        +int tossAndSum()
    }
    
    class Bins {
        -int minValue
        -int maxValue
        -int[] bins
        +Bins(int minValue, int maxValue)
        +void incrementBin(int value)
        +int getBin(int value)
    }
    
    class Simulation {
        -int numberOfDice
        -int numberOfTosses
        -Dice dice
        -Bins results
        +Simulation(int numberOfDice, int numberOfTosses)
        +void runSimulation()
        +void printResults()
    }
    
    Simulation --> Dice : uses
    Simulation --> Bins : uses

Key Entity Relationships:

  • Simulation uses Dice: The simulation entity creates and uses a Dice entity to generate random values
  • Simulation uses Bins: The simulation entity uses a Bins entity to track results
  • Composition pattern: Simulation “has-a” Dice and “has-a” Bins

Step 4: Refining Entities - Discovering Hidden Nouns and Verbs

As you think deeper about the implementation, you’ll discover additional nouns and verbs that weren’t obvious in the initial analysis. This is normal and shows your understanding is deepening.

Hidden Nouns (Additional Attributes)

  • rollSingleDie - the action of rolling one individual die
  • index - position within the bins array
  • toString - string representation of results

Hidden Verbs (Additional Methods)

  • calculateMinMax - determining the range of possible values
  • getIndex - converting values to array positions

Refined Entity Design

  classDiagram
    class Dice {
        -int numberOfDice
        +Dice(int numberOfDice)
        +int tossAndSum()
        -int rollSingleDie()
    }
    
    class Bins {
        -int minValue
        -int maxValue
        -int[] bins
        +Bins(int minValue, int maxValue)
        +void incrementBin(int value)
        +int getBin(int value)
        +String toString()
        -int getIndex(int value)
    }
    
    class Simulation {
        -int numberOfDice
        -int numberOfTosses
        -Dice dice
        -Bins results
        +Simulation(int numberOfDice, int numberOfTosses)
        +void runSimulation()
        +void printResults()
        -void calculateMinMax()
    }
    
    Simulation --> Dice : uses
    Simulation --> Bins : uses

Why These Additions Matter:

  • Private methods represent internal verbs - actions the entity does for itself
  • Helper methods break complex behaviors into simpler parts
  • This refinement shows how analysis evolves as understanding deepens

Step 5: Hand-Drawn Diagrams - Thinking Tools for Entity Discovery

Why Hand-Drawing Matters for Entity Analysis

Computer-generated diagrams are nice, but hand-drawn sketches are entity discovery tools. Here’s why:

  1. Speed: You can sketch entities as you discover them
  2. Flexibility: Easy to add new nouns and verbs as you find them
  3. Focus: Forces you to think about essential entities, not visual perfection
  4. Accessibility: Works anywhere - no computer needed for entity analysis
  5. Collaboration: Easy to share entity insights with teammates

Hand-Drawing Tips for Entity Modeling

Basic Entity Box (Noun → Attributes → Verbs):

┌─────────────┐
│   Dice      │  ← Entity name (main noun)
├─────────────┤
│-numberOfDice│  ← Attributes (descriptive nouns)
│-sides       │  ← What the entity "knows"
├─────────────┤
│+tossAndSum()│  ← Methods (verbs)
│-rollSingle()│  ← What the entity "does"
└─────────────┘

Show Entity Relationships:

Simulation ───→ Dice    (Simulation uses Dice)
     │
     └───→ Bins         (Simulation uses Bins)

Annotate with Entity Questions:

┌─────────────┐
│ Simulation  │ ← What entity orchestrates?
├─────────────┤
│-numberOfDice│ ← What does it need to know?
│-tosses      │
│-dice        │ ← What entities does it use?
│-results     │
├─────────────┤
│+runSim()    │ ← What verbs make sense?
│+printRes()  │
└─────────────┘

The Entity Discovery Process

Step 1: Entity Identification

  • Read problem statement
  • Circle all nouns → potential entities/attributes
  • Underline all verbs → potential methods

Step 2: Entity Grouping

  • Group related nouns together
  • Each group becomes a potential entity
  • Ask: “Does this group represent a single concept?”

Step 3: Entity Validation

  • Can you describe what the entity “is”?
  • Can you list what it “knows”?
  • Can you list what it “does”?
  • Does it have a clear responsibility?

Step 6: From Entity Design to Implementation

Entity-Driven Implementation Order

Now that we understand our entities, we can implement them in logical order based on their dependencies:

Implementation Strategy:

  1. Start with entities that have no dependencies (Dice)
  2. Then entities that depend only on simple data (Bins)
  3. Finally, entities that orchestrate others (Simulation)

Implementing the Dice Entity

The Dice entity encapsulates the concept of “a set of rollable dice”:

FUNCTION create_dice(numberOfDice):
    dice = new object
    dice.numberOfDice = numberOfDice    // Entity attribute (noun)
    RETURN dice

FUNCTION toss_and_sum(dice):           // Entity behavior (verb)
    sum = 0
    current = 1
    
    WHILE current <= dice.numberOfDice:
        roll = CALL roll_single_die()   // Helper behavior (verb)
        sum = sum + roll
        current = current + 1
    
    RETURN sum

FUNCTION roll_single_die():            // Private entity behavior
    random_value = RANDOM_NUMBER_0_TO_1() * 6
    die_value = FLOOR(random_value) + 1
    RETURN die_value

Entity Analysis:

  • Main noun: dice (the thing we’re modeling)
  • Attributes: numberOfDice (what it knows about itself)
  • Primary verb: toss_and_sum (what others ask it to do)
  • Helper verb: roll_single_die (what it does internally)

Testing Entity Behavior

Before implementing the next entity, verify this entity works:

dice = CREATE Dice(2)
counter = 1

WHILE counter <= 10:
    result = CALL dice.tossAndSum()
    PRINT result
    counter = counter + 1

This test validates the entity’s core behavior (the main verb).

Implementing the Bins Entity

The Bins entity encapsulates the concept of “statistical result collection”:

FUNCTION create_bins(minValue, maxValue):
    bins = new object
    bins.minValue = minValue            // Entity attributes (nouns)
    bins.maxValue = maxValue
    bins.bins = CREATE_ARRAY(maxValue - minValue + 1)
    
    // Initialize all bins to 0
    index = 0
    WHILE index < LENGTH(bins.bins):
        bins.bins[index] = 0
        index = index + 1
    
    RETURN bins

FUNCTION increment_bin(bins, value):    // Entity behavior (verb)
    IF value >= bins.minValue AND value <= bins.maxValue:
        array_index = CALL get_index(bins, value)  // Helper verb
        bins.bins[array_index] = bins.bins[array_index] + 1

FUNCTION get_bin(bins, value):          // Entity behavior (verb)
    IF value >= bins.minValue AND value <= bins.maxValue:
        array_index = CALL get_index(bins, value)
        RETURN bins.bins[array_index]
    RETURN 0

FUNCTION get_index(bins, value):        // Private entity behavior
    RETURN value - bins.minValue

Entity Analysis:

  • Main noun: bins (the collection of result counts)
  • Attributes: minValue, maxValue, bins array (what it knows)
  • Primary verbs: increment_bin, get_bin (what others ask it to do)
  • Helper verb: get_index (internal calculation)

Implementing the Simulation Entity

The Simulation entity encapsulates the concept of “experiment orchestration”:

FUNCTION create_simulation(numberOfDice, numberOfTosses):
    simulation = new object
    simulation.numberOfDice = numberOfDice      // Entity attributes
    simulation.numberOfTosses = numberOfTosses
    simulation.dice = CALL create_dice(numberOfDice)      // Entity relationships
    
    // Calculate min and max possible values (derived attributes)
    minValue = numberOfDice * 1  // all ones
    maxValue = numberOfDice * 6  // all sixes
    simulation.results = CALL create_bins(minValue, maxValue)
    
    RETURN simulation

FUNCTION run_simulation(simulation):            // Primary entity behavior
    toss_count = 1
    
    WHILE toss_count <= simulation.numberOfTosses:
        toss_result = CALL toss_and_sum(simulation.dice)     // Uses Dice entity
        CALL increment_bin(simulation.results, toss_result)   // Uses Bins entity
        toss_count = toss_count + 1

FUNCTION print_results(simulation):             // Entity behavior (verb)
    PRINT "Simulation of " + simulation.numberOfDice + 
          " dice tossed for " + simulation.numberOfTosses + " times."
    
    value = simulation.numberOfDice
    WHILE value <= simulation.numberOfDice * 6:
        count = CALL get_bin(simulation.results, value)      // Uses Bins entity
        percentage = count / simulation.numberOfTosses
        
        PRINT FORMAT_NUMBER(value, 2) + " : " + 
              FORMAT_NUMBER(count, 8) + ": " + 
              FORMAT_DECIMAL(percentage, 2)
        
        value = value + 1

Entity Analysis:

  • Main noun: simulation (the experiment process)
  • Attributes: numberOfDice, numberOfTosses (experiment parameters)
  • Relationships: dice, results (references to other entities)
  • Primary verbs: run_simulation, print_results (orchestration behaviors)

Step 7: Entity Validation and Design Reflection

Questions Your Entity Analysis Should Answer

  1. What real-world concepts does each entity represent? (Main nouns)
  2. What information does each entity need to remember? (Attribute nouns)
  3. What can other entities ask this entity to do? (Public verb methods)
  4. What does this entity do internally? (Private verb methods)
  5. How do entities collaborate to solve the problem? (Relationships)

Entity Design Quality Indicators

Good Entity Design:

  • Single Responsibility: Each entity models one clear concept
  • Meaningful Names: Entity and method names reflect real-world nouns and verbs
  • Clear Boundaries: It’s obvious what each entity is responsible for
  • Natural Interactions: Entity relationships make sense in the problem domain

Poor Entity Design:

  • God Entities: One entity that does everything
  • Anemic Entities: Entities with only data, no behavior
  • Confused Responsibilities: Can’t clearly explain what an entity represents

Common Entity Discovery Issues

Missing Entities: If you can’t implement a behavior with your current entities, you may be missing an important concept from the problem domain.

Wrong Abstraction Level: If your entities are too detailed (like “LeftDie” and “RightDie”) or too general (like “GameManager”), reconsider the natural concepts in your problem.

Circular Dependencies: If Entity A needs Entity B and Entity B needs Entity A, you may have incorrectly identified entity boundaries.

Step 8: Advanced Diagram Techniques

Adding Detail as Needed

Show Data Types:

┌─────────────────┐
│      Dice       │
├─────────────────┤
│-numberOfDice:int│
├─────────────────┤
│+tossAndSum():int│
└─────────────────┘

Show Function Parameters:

┌─────────────────────┐
│       Bins          │
├─────────────────────┤
│-bins: array of int  │
├─────────────────────┤
│+incrementBin(val:int)│
│+getBin(val:int):int │
└─────────────────────┘

Add Notes for Tricky Parts:

┌─────────────┐     ┌──────────────────────┐
│ Simulation  │────→│ Note: Calculate min/ │
└─────────────┘     │ max based on number  │
                    │ of dice (1*n to 6*n) │
                    └──────────────────────┘

The Power of Sketching: Real-World Benefits

For Beginner Programmers

Entity-driven UML diagrams teach you to:

  1. Think in Terms of Real-World Concepts: Identify the “things” and “actions” in problem descriptions
  2. Break Down Problems Naturally: Use noun and verb analysis to discover entities
  3. See Entity Relationships: Understand how different concepts collaborate
  4. Catch Design Problems Early: Validate entities before implementing them
  5. Communicate Conceptually: Share your understanding of the problem domain

The Entity Discovery Workflow

The Noun-Verb-Entity Cycle:

  1. Analyze problem statement for nouns and verbs
  2. Group related concepts into potential entities
  3. Validate each entity’s purpose and responsibilities
  4. Design entity relationships and interactions
  5. Implement entities in dependency order
  6. Refine based on what you learn during implementation

Why Hand-Drawing Beats Digital Tools for Entity Discovery

For learning entity modeling, pencil and paper win because:

  • Natural thinking flow: Match the way your brain processes concepts
  • No tool constraints: Focus on concepts, not software features
  • Easy concept iteration: Quick to modify as understanding evolves
  • Collaborative discovery: Easy to share insights during group analysis
  • Portable analysis: Work anywhere, anytime for problem analysis

Common Beginner Mistakes and How Entity Analysis Helps

Mistake 1: Starting to Code Without Understanding Entities

Without Entity Analysis: Jump into coding without understanding what you’re modeling

With Entity Analysis: Spend time identifying the key concepts before writing any code

Mistake 2: Creating God Entities

Without Entity Analysis: One entity that represents everything in the problem

With Entity Analysis: Natural entity boundaries emerge from noun groupings

Mistake 3: Missing Core Entities

Without Entity Analysis: Realize halfway through that you’re missing a key concept

With Entity Analysis: Systematic noun analysis reveals all important entities upfront

Mistake 4: Confusing Entity Relationships

Without Entity Analysis: Unclear how different parts of your system should interact

With Entity Analysis: Verb analysis reveals natural collaboration patterns

Practice Exercise: Entity Discovery for New Features

Now that you understand entity analysis for DiceyLab, try discovering entities for these extensions:

Feature 1: Different Die Types

Problem Statement: “Support various die types including 4-sided, 8-sided, and 20-sided dice in the simulation.”

Entity Discovery Questions:

  • What new nouns appear? (die types, sides, shapes)
  • What new verbs appear? (configure, validate die types)
  • Should “die type” be an attribute or a separate entity?
  • How do existing entities need to change?

Feature 2: Detailed Statistics

Problem Statement: “Track advanced statistics including average roll, standard deviation, and comparison between theoretical and actual probabilities.”

Entity Discovery Questions:

  • What is the main new entity? (Statistics, Calculator, Analyzer?)
  • What would this entity know? (averages, deviations, expectations)
  • What would this entity do? (calculate, analyze, compare)
  • How would it relate to existing entities?

Feature 3: Multiple Output Formats

Problem Statement: “Generate results in multiple formats including console display, file output, and CSV export.”

Entity Discovery Questions:

  • Are “Console”, “File”, and “CSV” separate entities or one “OutputFormatter” entity?
  • What verbs are associated with output? (format, write, export, display)
  • How should output entities relate to the Simulation entity?
  • What attributes would each output entity need?

Final Advice: Make It a Habit

Start Every Programming Assignment with Entity Discovery

Before you write any code:

  1. Read the requirements carefully, highlighting nouns and verbs
  2. Group related nouns into potential entities
  3. Validate each entity’s purpose and responsibilities
  4. Sketch entity diagrams showing attributes and methods
  5. Map relationships between entities
  6. Implement entities in dependency order

Keep Your Entity Analysis

Your entity discovery work is valuable because it:

  • Shows your problem-understanding process
  • Helps you remember design decisions
  • Provides great reference material for similar problems
  • Demonstrates systematic thinking to instructors

Remember: Perfect Entities Aren’t the Goal

The goal is clear problem understanding. A rough entity analysis that helps you understand the problem domain is infinitely more valuable than a perfect diagram that doesn’t teach you anything about the real-world concepts you’re modeling.

Think of entity analysis as a lens for understanding problems - it helps you see the natural structure hidden in problem descriptions. Eventually, you’ll automatically think in terms of entities and their relationships, but you’ll still use this analysis process for complex domains.

The best programmers aren’t those who memorize syntax - they’re those who can discover the essential entities in any problem domain and understand how those entities should collaborate. UML diagrams with the nouns-and-verbs approach are powerful tools for developing this crucial skill.