Learn Python with Talk Python's 270 hours of courses

Robust Python

Episode #332, published Tue, Aug 31, 2021, recorded Mon, Aug 30, 2021

Does it seem like your Python projects are getting bigger and bigger? Are you feeling the pain as your codebase expands and gets tougher to debug and maintain? Patrick Viafore is here to help us write more maintainable, longer-lived, and more enjoyable Python code.

Watch this episode on YouTube
Play on YouTube
Watch the live stream version

Episode Deep Dive

Guest introduction and background

Patrick (Pat) Viafore is a seasoned software developer currently working at Canonical (the company behind Ubuntu) on its public cloud team. He has a background in C++ but fell in love with Python for its simplicity and flexibility. Patrick authored the book Robust Python (published by O’Reilly) inspired by his passion for writing maintainable, sustainable, and expressive Python code. In the episode, he shares insights on how to keep Python codebases healthy over time, integrate typing practices in a balanced way, and communicate effectively with future developers of your software.


What to Know If You're New to Python

If this episode is your first deep dive into Python code quality and maintainability, here are some helpful pointers before you jump in:

  • Dynamic vs. Typed: Understand that Python is primarily a dynamic language but supports optional static typing (e.g., mypy, type hints) for clarity and tooling.
  • Data Structures: Familiarity with dictionaries, sets, lists, and data classes will help you follow the examples about “choosing the right container” and structuring data.
  • Code as Communication: Python places a strong emphasis on readability (a core reason for its popularity), so good naming and minimal “surprises” are highly valued.
  • Incremental Refactoring: You don't have to fix everything at once. Often, improving just the critical sections of your code can yield big benefits.

Key points and takeaways

  1. Sustaining Code for the Long Run A central theme of the episode is writing code that remains maintainable and adaptable over time. Pat emphasizes that software engineering is more than short-term programming—it’s “programming integrated over time.” Sustainable code involves balancing immediate feature delivery with the need to keep things extensible and readable.
  2. Types as a Communication Tool Python’s optional static typing can help avoid many common errors (like NoneType issues) and enhance editor tooling for code completion. But it’s not all-or-nothing—Pat recommends using types where you see recurring bugs or where clarity is most critical. Gradual typing ensures you keep Python’s strengths in speed of development while reducing error-prone sections.
  3. The Principle of Least Surprise One of Pat’s best practices is keeping your function, class, and variable names clear and consistent with what they do. If something is called a “getter,” it shouldn’t change state or do hidden side effects. Violating these expectations forces every future maintainer to spend extra time investigating code they can’t trust at face value.
  4. Moving Beyond Dictionaries for Heterogeneous Data Using a dict to represent many different fields (e.g., 'name', 'age', 'date_of_birth') can create confusion. Converting these to a data class or a Pydantic model makes your intent explicit and easier to type-check. Distinguish between dictionaries for “lookup by key” and data classes for “grouped data with fixed fields.”
  5. Incremental Refactoring and the Boy Scout Rule Rather than striving for “perfect code” in a single pass, a more realistic approach is to leave the codebase “cleaner than you found it.” Each time you modify or review code, fix small inconsistencies, add a couple of type annotations, or simplify logic. Over time, these tiny improvements can significantly enhance maintainability and reduce technical debt.
  6. Data-Backed Conversations with Management Technical debt and code quality can seem abstract to non-developers. Pat discussed using concrete data—like the number of NoneType errors in production or how many times a bug reappears—to demonstrate the value of spending time on better testing, type hints, or refactoring. Show the cost in real terms (e.g., lost customers, extra support hours).
  7. Don’t Gold Plate Early While robust code matters, Pat cautions that you shouldn’t hinder your minimum viable product (MVP) or initial release by over-engineering. Strike a balance: shipping features is still a priority. Many robust practices, like adding tests or type hints, can be phased in once you’ve validated that the feature itself is valuable.
  8. Performance vs. Maintainability Optimizing the wrong part of your code often leads to tangled, hard-to-read solutions. Always measure before you optimize, whether that’s using built-in Python profiling tools or logging-based metrics. If a code path is rarely called or can run asynchronously, it may not be a pressing place to introduce complexity.
  9. Extensibility via Plugins When multiple features have similar mechanics but different “policies,” a plugin system can simplify how new logic gets added over time. Pat mentioned Stevedore (docs.openstack.org) for plugin development in Python. This pattern helps break code into smaller, easier-to-understand components.
  10. APIs, Duck Typing, and Liskov Python’s “duck typing” means an object’s suitability is determined by what methods it supports rather than its class. Concepts like the Liskov Substitution Principle (from the SOLID guidelines) still apply: if a function claims to work with any “file-like object,” your “substitute” class should behave like one. Embracing Python’s dynamic nature is easier when the code states its behavior clearly.

Interesting quotes and stories

  • “Software engineering is programming integrated over time.” – Quoted from Titus Winters, highlighted by Pat to emphasize the importance of maintainability.
  • “I thought I was writing a technical book, but I ended up writing a book about empathy.” – Pat on how maintainable code really focuses on making life easier for other (future) developers.
  • “The more trust you build into your code, the faster you can work.” – On how principle of least surprise and consistent data structures help teams add features quickly.

Key definitions and terms

  • Duck Typing: A style of dynamic typing where the object’s current set of methods and properties determines its valid usage, rather than its class or type name.
  • Mypy: A static type checker for Python. It analyzes your code’s type hints to catch errors before runtime.
  • Data Class: A Python 3.7+ feature that automatically generates special methods (like __init__ and __repr__) based on class attributes, making it easier to store structured data.
  • Technical Debt: The implied cost of additional rework created by choosing a quick or easy solution now, instead of using a better approach that might take longer initially.

Learning resources

If you want to dive deeper into some of the themes from this episode, here are a few curated resources:


Overall takeaway

Maintaining a robust Python codebase goes far beyond just writing code that works today. It’s about empathy for your future self and teammates, choosing data structures that convey intent, and adopting incremental improvements like selective type hints. When you use Python’s power carefully—from dictionaries for fast lookups to data classes for clearer models—you’ll deliver features without sacrificing speed or adaptability. Ultimately, robust Python is about creating a positive experience for everyone who encounters your code, now and in the years to come.

Links from the show

Pat on Twitter: @PatViaforever
Robust Python Book: oreilly.com
Typing in Python: docs.python.org
mypy: mypy-lang.org
SQLModel: sqlmodel.tiangolo.com
CUPID principles @ relevant time: overcast.fm
Stevedore package: docs.openstack.org
Watch this episode on YouTube: youtube.com
Episode transcripts: talkpython.fm

--- Stay in touch with us ---
Subscribe to Talk Python on YouTube: youtube.com
Talk Python on Bluesky: @talkpython.fm at bsky.app
Talk Python on Mastodon: talkpython
Michael on Bluesky: @mkennedy.codes at bsky.app
Michael on Mastodon: mkennedy

Talk Python's Mastodon Michael Kennedy's Mastodon