Summary
A junior developer’s initial implementation of a trivia game suffered from high cognitive complexity and tight coupling. The original code relied on manual index tracking (question_num-1), fragmented data structures (separate dictionaries for questions and lists for options), and a lack of modularity. This resulted in a “spaghetti” flow where state management was handled through global-scope variables and precarious manual increments, making the system fragile and difficult to extend.
Root Cause
The primary technical failures were:
- Parallel Array/List Anti-pattern: Storing questions in a dictionary but options in a separate list requires manual index synchronization. If one list is modified without the other, the entire application crashes or provides incorrect data.
- Manual State Management: Using
question_num += 1to track progress is error-prone. In production, this leads to off-by-one errors. - High Cyclomatic Complexity: The logic for printing, checking answers, and calculating scores was interleaved, preventing unit testing of individual components.
- Inefficient Data Lookup: Using a dictionary to iterate through questions while trying to map them to specific options via index is an O(n) complexity trap that should be solved with structured data.
Why This Happens in Real Systems
In large-scale production environments, this manifests as Distributed State Inconsistency.
- When different microservices hold different versions of “the truth” (e.g., a User Service thinks a user is active, but the Auth Service thinks they are suspended), it mirrors the “Parallel List” problem.
- Developers often write “procedural” scripts that work for a single run but fail when subjected to concurrency or unhandled edge cases.
- Technical Debt accumulates when developers prioritize “making it work” over “making it maintainable,” leading to systems that are impossible to refactor without a total rewrite.
Real-World Impact
- Maintenance Overhead: Every new question added requires updates in two or three different places, increasing the probability of human error.
- Scalability Bottlenecks: As the dataset grows, the lack of a unified data model makes it impossible to load questions from a database or API efficiently.
- Degraded Reliability: A single mismatch in the
optionslist length will trigger anIndexError, causing a complete system outage for the end-user.
Example or Code
from dataclasses import dataclass
from typing import List, Dict
@dataclass
class Question:
text: str
options: List[str]
correct_answer: str
class TriviaGame:
def __init__(self, questions: List[Question]):
self.questions = questions
self.user_guesses = []
self.score = 0
def run(self):
for q in self.questions:
print("-" * 40)
print(q.text)
for option in q.options:
print(option)
guess = input("Enter (A, B, C, or D): ").upper()
self.user_guesses.append(guess)
if guess == q.correct_answer:
print("CORRECT")
self.score += 1
else:
print(f"WRONG (Correct answer was {q.correct_answer})")
self.display_results()
def display_results(self):
print("-" * 40)
print("RESULT:")
print(f"Score: {(self.score / len(self.questions)) * 100:.2f}%")
print(f"Your guesses: {' '.join(self.user_guesses)}")
def main():
# Data is encapsulated in a single, reliable structure
data = [
Question("Who created Python?", ["A. Bjarne Stroustrup", "B. Guido van Rossum", "C. Alexander Coppel", "D. Blaise Pascal"], "B"),
Question("Where does the name 'Python' originate?", ["A. The snake", "B. His mother", "C. Monty Python", "D. None"], "C"),
]
game = TriviaGame(data)
game.run()
if __name__ == "__main__":
main()
How Senior Engineers Fix It
Senior engineers apply Data Modeling and Encapsulation to solve these issues:
- Single Source of Truth: We group related data into a single object (like a
dataclassor a JSON object). A question and its options should never exist separately. - Separation of Concerns: We decouple the Data (the questions), the Engine (the game logic), and the Interface (the print statements).
- Abstraction: Instead of manually incrementing counters, we use high-level iterators (
for question in questions) which are inherently safer. - Defensive Programming: We design the system so that it is “impossible” to enter an invalid state (e.g., a question without options).
Why Juniors Miss It
- Focus on Syntax over Architecture: Juniors often focus on “how to write a loop” rather than “how to structure the data the loop processes.”
- Linear Thinking: They tend to write code as a sequence of steps (Step 1, then Step 2, then Step 3) rather than a collection of interacting components.
- Lack of Edge Case Awareness: They assume the input (like the number of options) will always perfectly match the number of questions, failing to account for the entropy of real-world data.