Build an Org Design Simulator
Instructions
Overview
In this lab, you will build an Org Design Simulator in Python that models engineering organizations using concepts from Module 3: Conway's Law, Team Topologies, span of control, cognitive load thresholds, and communication overhead. The tool will help an Engineering Manager analyze their organization's structure and receive data-driven recommendations.
Core Concepts
This lab applies the organizational design principles from Module 3:
- Conway's Law simulation — modeling how team structure maps to system architecture
- Team Topologies — classifying teams as stream-aligned, platform, enabling, or complicated-subsystem
- Span of control — validating that managers have 5-9 direct reports
- Communication overhead — calculating channels using the formula n*(n-1)/2
- Cognitive load — detecting when teams own too many services relative to their size
Requirements
Part 1: Team and Org Management
Create a function create_org(org_name) that:
- Creates and returns an org dictionary with the given name, an empty teams dictionary, and an empty managers dictionary
- The org dictionary must include keys:
name,teams,managers
Create a function add_team(org, team_name, team_type, members, services) that:
- Adds a team to the org's teams dictionary
team_typemust be one of: "stream_aligned", "platform", "enabling", "complicated_subsystem"membersis a list of member name stringsservicesis a list of service/component name strings the team owns- Raises
ValueErrorif the team name already exists or the team type is invalid
Create a function add_manager(org, manager_name, team_names) that:
- Adds a manager to the org's managers dictionary
team_namesis a list of team names this manager oversees- Raises
ValueErrorif the manager name already exists - Raises
KeyErrorif any team name does not exist in the org
Part 2: Communication Overhead Calculations
Create a function calculate_communication_channels(team_size) that:
- Returns the number of communication channels using the formula: n * (n - 1) / 2
- Returns an integer
- Raises
ValueErrorif team_size is less than 0
Create a function calculate_org_communication_overhead(org) that:
- Returns a dictionary where each key is a team name and the value is a dictionary containing:
team_size: number of membersinternal_channels: communication channels within the team (n*(n-1)/2)overhead_level: "low" if channels <= 10, "medium" if channels <= 28, "high" if channels > 28
Part 3: Span of Control Analysis
Create a function analyze_span_of_control(org) that:
- Returns a dictionary where each key is a manager name and the value is a dictionary containing:
direct_reports: total number of unique members across all teams the manager overseesteams_managed: number of teams managedstatus: "too_narrow" if direct_reports < 5, "optimal" if 5-9, "too_wide" if > 9recommendation: a string with actionable advice based on the status
Part 4: Cognitive Load and Team Split Recommendations
Create a function assess_cognitive_load(org) that:
- Evaluates each team's cognitive load based on services-per-member ratio
- Returns a list of dictionaries for teams that may be overloaded, each containing:
team_name: name of the teamteam_size: number of membersservices_owned: number of servicesservices_per_member: ratio rounded to 2 decimal placescognitive_load: "sustainable" if ratio <= 1.5, "elevated" if ratio <= 2.5, "overloaded" if ratio > 2.5recommendation: a string — if overloaded, recommend splitting; if elevated, recommend monitoring
- Returns all teams sorted by services_per_member descending (most loaded first)
Create a function recommend_team_split(org, team_name) that:
- Takes a team name and recommends how to split it
- Returns a dictionary with:
original_team: the team namecurrent_size: number of memberscurrent_services: list of servicesshould_split: True if the team has more than 8 members OR more than 2 services per memberrecommended_teams: if should_split is True, a list of 2 dictionaries, each withsuggested_name(string) andsuggested_services(list), splitting services roughly in half; if should_split is False, an empty list
- Raises
KeyErrorif the team does not exist
Part 5: Conway's Law Simulation
Create a function simulate_conway_mapping(org) that:
- Maps each team to the system components it would naturally produce (its services list), demonstrating Conway's Law
- Returns a dictionary with:
teams_to_components: a dictionary mapping team names to their list of servicescomponent_coupling: a list of dictionaries describing potential coupling between teams that share no services but are managed by the same manager, each containingteam_a,team_b, andshared_managerconway_warnings: a list of warning strings for potential architectural issues (e.g., a single team owning more than 4 services may produce a monolithic component)
Part 6: Org Chart Report Generation
Create a function generate_org_report(org) that:
- Returns a formatted string containing:
- A header with the organization name
- A Team Topologies summary showing counts of each team type
- A section for each manager showing their span of control status and the teams they manage
- A section for each team showing members, services, team type, and communication channels
- A cognitive load summary with recommendations
- A Conway's Law analysis section
- The output must be clean, readable, and well-structured
Example Usage
org = create_org("Acme Engineering")
# Add teams with topologies
add_team(org, "Payments", "stream_aligned",
["Alice", "Bob", "Carol", "Dave", "Eve"],
["payment-api", "billing-service", "invoice-generator"])
add_team(org, "Platform Infra", "platform",
["Frank", "Grace", "Heidi"],
["ci-cd-pipeline", "monitoring-stack", "dev-portal"])
add_team(org, "Search", "stream_aligned",
["Ivan", "Judy", "Karl", "Liam", "Mia", "Noah", "Olivia", "Pat", "Quinn", "Rosa"],
["search-api", "indexer", "ranking-engine", "autocomplete", "search-analytics"])
add_team(org, "ML Core", "complicated_subsystem",
["Sam", "Tina"],
["recommendation-engine", "fraud-detection", "nlp-pipeline"])
# Add managers
add_manager(org, "VP Alice", ["Payments", "Search"])
add_manager(org, "Director Bob", ["Platform Infra", "ML Core"])
# Analyze
channels = calculate_communication_channels(10)
print(f"Channels for 10 people: {channels}") # 45
span = analyze_span_of_control(org)
print(span)
load = assess_cognitive_load(org)
print(load)
report = generate_org_report(org)
print(report)
Expected Output Format
================================================================
ORG DESIGN REPORT: Acme Engineering
================================================================
TEAM TOPOLOGIES SUMMARY
----------------------------------------------------------------
Stream-aligned teams: 2
Platform teams: 1
Enabling teams: 0
Complicated subsystem teams: 1
Total teams: 4
Total engineers: 20
================================================================
MANAGER SPAN OF CONTROL
================================================================
VP Alice
Teams: Payments, Search
Direct reports: 15
Status: TOO WIDE
Recommendation: Consider splitting into two management roles.
Director Bob
Teams: Platform Infra, ML Core
Direct reports: 5
Status: OPTIMAL
Recommendation: Span of control is within the recommended 5-9 range.
================================================================
TEAM DETAILS
================================================================
Payments [stream_aligned]
Members (5): Alice, Bob, Carol, Dave, Eve
Services (3): payment-api, billing-service, invoice-generator
Communication channels: 10 (medium)
Services per member: 0.60
Platform Infra [platform]
Members (3): Frank, Grace, Heidi
Services (3): ci-cd-pipeline, monitoring-stack, dev-portal
Communication channels: 3 (low)
Services per member: 1.00
Search [stream_aligned]
Members (10): Ivan, Judy, Karl, Liam, Mia, Noah, Olivia, Pat, Quinn, Rosa
Services (5): search-api, indexer, ranking-engine, autocomplete, search-analytics
Communication channels: 45 (high)
Services per member: 0.50
ML Core [complicated_subsystem]
Members (2): Sam, Tina
Services (3): recommendation-engine, fraud-detection, nlp-pipeline
Communication channels: 1 (low)
Services per member: 1.50
================================================================
COGNITIVE LOAD ASSESSMENT
================================================================
1. ML Core — 1.50 services/member — ELEVATED
Monitor closely; consider adding team members or reducing scope.
2. Platform Infra — 1.00 services/member — SUSTAINABLE
Cognitive load is within healthy bounds.
3. Payments — 0.60 services/member — SUSTAINABLE
Cognitive load is within healthy bounds.
4. Search — 0.50 services/member — SUSTAINABLE
Cognitive load is within healthy bounds.
================================================================
CONWAY'S LAW ANALYSIS
================================================================
Team-to-Component Mapping:
Payments -> payment-api, billing-service, invoice-generator
Platform Infra -> ci-cd-pipeline, monitoring-stack, dev-portal
Search -> search-api, indexer, ranking-engine, autocomplete, search-analytics
ML Core -> recommendation-engine, fraud-detection, nlp-pipeline
Potential Coupling (shared manager):
Payments <-> Search (via VP Alice)
Platform Infra <-> ML Core (via Director Bob)
Warnings:
- Search owns 5 services — risk of producing a monolithic component.
Consider splitting into focused sub-teams.
================================================================