How to Build an MVP Presenter View Mock in Python
A minimal MVP (Model-View-Presenter) mock showing a Presenter controlling a SlideDeck model with slide navigation and typed state via dataclasses.
Python code
57 linesfrom dataclasses import dataclass, field
from typing import List
@dataclass
class SlideDeck:
title: str
slides: List[str] = field(default_factory=list)
current_index: int = 0
def next_slide(self) -> str:
if self.current_index < len(self.slides) - 1:
self.current_index += 1
return self.current_slide()
def previous_slide(self) -> str:
if self.current_index > 0:
self.current_index -= 1
return self.current_slide()
def current_slide(self) -> str:
return self.slides[self.current_index]
def set_slide(self, index: int) -> str:
if 0 <= index < len(self.slides):
self.current_index = index
return self.current_slide()
@dataclass
class Presenter:
name: str
deck: SlideDeck
def present(self) -> str:
return f"{self.name} is showing: {self.deck.current_slide()}"
if __name__ == "__main__":
deck = SlideDeck(
title="MVP Demo",
slides=[
"Welcome: Intro to the app",
"Architecture: MVP pattern",
"Live demo: Feature walkthrough",
"Q&A and next steps"
]
)
presenter = Presenter("Alice", deck)
print(presenter.present())
print(presenter.deck.next_slide())
print(presenter.present())
print(presenter.deck.previous_slide())
presenter.deck.set_slide(3)
print(presenter.present())
print(f"Deck: {presenter.deck.title} | Position: {presenter.deck.current_index + 1}/{len(presenter.deck.slides)}")
Output
Alice is showing: Welcome: Intro to the app
Alice is showing: Architecture: MVP pattern
Alice is showing: Welcome: Intro to the app
Alice is showing: Q&A and next steps
Deck: MVP Demo | Position: 4/4
How it works
The code models the MVP pattern with SlideDeck as the Model (holds data + navigation state) and Presenter as the Presenter (mediates access and formatting). The @dataclass generates __init__, __repr__, and equality automatically, reducing boilerplate. field(default_factory=list) gives each instance its own list, avoiding the shared mutable-default trap. Navigation methods mutate current_index only within bounds and always return the current slide, making the UI/model contract predictable. The present() method formats a view-ready string, keeping the underlying state untouched.
Common mistakes
- Using a mutable default like `slides=[]` instead of `field(default_factory=list)`, which shares state across instances
- Forgetting bounds checks in `set_slide`, causing IndexError on invalid indices
- Mutating the deck state inside `present()` instead of leaving it a pure read operation
- Not including a `previous_slide` guard, so moving back at index 0 wraps incorrectly
Variations
- Use a plain class with manual `__init__` and property-based navigation instead of dataclasses
- Add a View layer (e.g., a `display()` method) that listens to deck changes via callbacks or the observer pattern
Real-world use cases
- Prototyping a slide deck presenter UI for a desktop or web app before wiring real rendering
- Testing presenter state transitions in a unit test suite without a live view layer
- Mimicking a wizard or onboarding flow where a controller steps users through ordered screens
Sponsored
More from System design patterns
- Build a BFF (Backend for Frontend) Mock Aggregator in Python medium
- Builder pattern for mocking complex objects in Python easy
- Circuit Breaker Pattern in Python: Closed, Open, and Half-Open States medium
- Create a Data Helper Class in Python easy
- Domain Driven Design Aggregate Root Example in Python medium
- Facade Pattern in Python with Mock Simplification medium
Keep learning
Related tutorials and quizzes for this topic.