Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
Software is both
archeology and time-
travel
Copyright 2024 Kudzera,
LLC
Your job is to deliver
value in a timely
manner
Copyright 2024 Kudzera,
LLC
How do you enable the
future to be just as
efficient?
Copyright 2024 Kudzera,
LLC
Extensibility
Copyright 2024 Kudzera,
LLC
0) Think about the humans
Copyright 2024 Kudzera,
LLC
Extensibility Themes
Copyright 2024 Kudzera,
LLC
1) Reduce Commit Complexity
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
2) Be Mindful of OCP
Copyright 2024 Kudzera,
LLC
Open-Closed Principle
Copyright 2024 Kudzera,
LLC
Code should be open to
extension and closed
for modification
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
When To Split
● Are easy things hard to do?
● Do you encounter pushback against similar features?
● Do you have consistently high estimates?
● Do commits contain large changesets?
● Are you mixing policy changes with mechanisms changes
Copyright 2024 Kudzera,
LLC
Policies vs. Mechanisms
Copyright 2024 Kudzera,
LLC
3) Separate Policies and
Mechanisms
Copyright 2024 Kudzera,
LLC
From backoff documentation
Copyright 2024 Kudzera,
LLC
From Flask documentation
Copyright 2024 Kudzera,
LLC
4) Data-Driven Designs
Copyright 2024 Kudzera,
LLC
Data options
● Can you put your data in a collection?
● Configuration Files?
● Persistence Layers (i.e. databases, bucket storage, etc.)?
Copyright 2024 Kudzera,
LLC
5) Develop Libraries First
Copyright 2024 Kudzera,
LLC
Good Library Design
● README-driven
● Tested
● Easily Consumable
● Clearly-stated opinions
● Releasable (w/ Documentation)
● Extensible
● Composable
Copyright 2024 Kudzera,
LLC
Composability
Copyright 2024 Kudzera,
LLC
From Flask documentation
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
6) Create Building Blocks
Copyright 2024 Kudzera,
LLC
Architectural Extensibility
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
Dependencies
Copyright 2024 Kudzera,
LLC
Physical Dependencies
Copyright 2024 Kudzera,
LLC
from typing import Callable
@dataclass
class Metadata:
does_match: Callable[[User], bool]
if __name__ == "__main__":
run_self_test()
Copyright 2024 Kudzera,
LLC
pip install requests
Copyright 2024 Kudzera,
LLC
Physical Dependencies
● Hard-coded into source code
● Easy to follow from A to B
● Easily understandable
● Easy to find, hard to change
● Hard to substitute or mock out
● Understandable by static analysis tools
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
pipdeptree
Copyright 2024 Kudzera,
LLC
pydeps
Copyright 2024 Kudzera,
LLC
pyan3
Copyright 2024 Kudzera,
LLC
What Happens If You Need
Something To Change?
Copyright 2024 Kudzera,
LLC
A
B
C
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
A
B
C
Copyright 2024 Kudzera,
LLC
A
B
D
Copyright 2024 Kudzera,
LLC
A
B
Whatever
Copyright 2024 Kudzera,
LLC
Logical Dependencies
Copyright 2024 Kudzera,
LLC
requests.post("table-management/pizza-made", {
"id": order,
"pizza": pizza.to_json()
})
# meal is an abstract type
meal: Meal = meal_factory.create("pizza")
Copyright 2024 Kudzera,
LLC
Logical Dependencies
● Typically determined at run-time
● Readability suffers
● Debuggability suffers
● Hard to find, easy to change
● Easy to substitute or mock out
● Not understandable by static analysis tools
● Crucial for Abstraction
Copyright 2024 Kudzera,
LLC
7) Trade-off Dependencies
Judiciously
Copyright 2024 Kudzera,
LLC
Event-Driven Architectures
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
def complete_order(order: Order):
package_order(order)
notify_customer_that_order_is_done(order)
notify_restaurant_that_order_is_done(order)
Copyright 2024 Kudzera,
LLC
Architectural Extensibility
Copyright 2024 Kudzera,
LLC
Producer
Transport
Consumer
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
Producer
Transport
Consumer
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
pypubsub
Copyright 2024 Kudzera,
LLC
from pubsub import pub
def notify_customer_that_meal_is_done(order: Order):
# ... snip ...
pub.subscribe(notify_customer_that_meal_is_done, "meal-done")
Copyright 2024 Kudzera,
LLC
from pubsub import pub
def complete_order(order: Order):
package_order(order)
pub.publish("meal-done", order)
Copyright 2024 Kudzera,
LLC
8) Use Event-Driven
Architectures to Decouple
Producers and Consumers
Copyright 2024 Kudzera,
LLC
Pluggable Architectures
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
Plug-in examples
● pytest
● poetry
● hypothesis
● pylint
Copyright 2024 Kudzera,
LLC
Plugging Into Algorithms
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
Copyright 2024 Kudzera,
LLC
@dataclass
class PizzaCreationFunctions:
prepare_ingredients: Callable
add_pre_bake_toppings: Callable
add_post_bake_toppings: Callable
Copyright 2024 Kudzera,
LLC
def create_pizza(
pizza_creation_functions: PizzaCreationFunctions
):
pizza_creation_functions.prepare_ingredients()
roll_out_pizza_base()
pizza_creation_functions.add_pre_bake_toppings()
bake_pizza()
pizza_creation_functions.add_post_bake_toppings()
Copyright 2024 Kudzera,
LLC
pizza_creation_functions = PizzaCreationFunctions(
prepare_ingredients=mix_zaatar,
add_pre_bake_toppings=add_meat_and_halloumi,
add_post_bake_toppings=drizzle_olive_oil
)
create_pizza(pizza_creation_functions)
Copyright 2024 Kudzera,
LLC
pizza_creation_functions = PizzaCreationFunctions(
prepare_ingredients=cook_bulgogi,
add_pre_bake_toppings=add_bulgogi_toppings,
add_post_bake_toppings=garnish_with_scallions_and_sesame
)
create_pizza(pizza_creation_functions)
Copyright 2024 Kudzera,
LLC
Plugging Into Packages
Copyright 2024 Kudzera,
LLC
Stevedore
Copyright 2024 Kudzera,
LLC
from abc import abstractmethod
from typing import runtime_checkable, Protocol
@runtime_checkable
class UltimateKitchenAssistantModule(Protocol):
ingredients: list[Ingredient]
@abstractmethod
def get_recipes() -> list[Recipe]:
raise NotImplementedError
@abstractmethod
def prepare_dish(inventory: dict[Ingredient, Amount],
recipe: Recipe) -> Dish:
raise NotImplementedError
Copyright 2024 Kudzera,
LLC
class PastaModule(UltimateKitchenAssistantModule):
def __init__(self):
self.ingredients = ["Linguine",
# ... snip ...]
def get_recipes(self) -> list[Recipe]:
# ... snip returning all possible recipes ...
def prepare_dish(self, inventory: dict[Ingredient, Amount],
recipe: Recipe) -> Dish:
# interact with Ultimate Kitchen Assistant
Copyright 2024 Kudzera,
LLC
from stevedore import extension
def get_all_recipes() -> list[Recipe]:
mgr = extension.ExtensionManager(
namespace='ultimate_kitchen_assistant.recipe_maker',
invoke_on_load=True,
)
def get_recipes(extension):
return extension.obj.get_recipes()
return list(itertools.chain(mgr.map(get_recipes)))
Copyright 2024 Kudzera,
LLC
from setuptools import setup
setup(
name='ultimate_kitchen_assistant',
version='1.0',
#.... snip ....
entry_points={
'ultimate_kitchen_assistant.recipe_maker':
['pasta_maker =
ultimate_kitchen_assistant.pasta_maker:PastaModule'],
},
)
Copyright 2024 Kudzera,
LLC
9) Use Pluggable Python for
Extension Points
Copyright 2024 Kudzera,
LLC
0) Think about the humans
1) Reduce Commit Complexity
2) Be Mindful of OCP
3) Separate Policies and Mechanisms
4) Consider Data-Driven Design
5) Develop Libraries First
6) Create Building Blocks
7) Trade-off Dependencies Judiciously
8) Use Event-Driven Architectures to Decouple Producers/Consumers
9) Use Pluggable Python for Extension Points
Copyright 2024 Kudzera,
LLC
10) Don't Overextend Yourself
Copyright 2024 Kudzera,
LLC
Who Am I?
Principal Software Engineer
Cloud Software Group
Owner of Kudzera, LLC
Author of Robust Python
Organizer of HSV.py
Extensible Python:
Robustness Through
Addition
Patrick Viafore

Extensible Python: Robustness through Addition - PyCon 2024

Editor's Notes

  • #15 https://www.pexels.com/photo/macro-photography-of-a-pavement-crack-2847615/
  • #27 https://www.pexels.com/photo/boys-playing-with-toys-3939173/
  • #30 https://www.pexels.com/photo/barriers-on-asphalt-road-9826960/