Hi, I'm Evan. I'm a software engineer by day, and a gamer and creator at night. I graduated from University of Wisconsin Madison with a BS in Computer Science in 2019. I particularly enjoy applying design patterns while designing new features, which leads to clean implementations that are easy to integrate with, easy to maintain, and easy to understand.
Coming Soon!
The Proxy Pattern is a useful Structural Pattern that allows for a single consistent exposed interface while allowing for differing results. With a Proxy, you create an interface that is common between proxies and the proxied classes, and then call the proxy classes invocation method which will determine which proxied class to execute at runtime. This is best displayed with an example.
Say you have Publisher
interface that has two methods: publish
and validate
.
Here is the Publisher
interface implemented as an abstract base class in Python.
from abc import ABC, abstractmethod class Publisher(ABC): @abstractmethod def publish(self, payload, *args, **kwargs): raise NotImplementedError @abstractmethod def validate(self, payload, *args, **kwargs): raise NotImplementedError
The Publisher
interface will have two children and a proxy in this example, however you can implement as many
children and proxies as you would like.
class SlackPublisher(Publisher): def publish(self, payload, *args, **kwargs): channel = args[0] slack.write(payload, channel=channel) # This is not a real implementation, I made this up for the example. def validate(self, payload, *args, **kwargs): if len(args) == 0: return False return isinstance(payload, str) class SlackConsolePublisher(SlackPublisher): def publish(self, payload, *args, **kwargs): print(f"Payload: {payload} args: {args} kwargs: {kwargs}") class SlackPublisherProxy(Publisher): def __init__(self): self.api_key = os.environ.get('SLACK_API_KEY') if self.api_key: slack.set_write_key(self.api_key) self.publisher = SlackPublisher() else: self.publisher = SlackConsolePublisher() def publish(self, payload, *args, **kwargs): if self.publisher.validate(payload, *args, **kwargs): self.publisher.publish(payload, *args, **kwargs) raise Exception('Invalid slack publisher') # Repeat for validate if you want to expose the validate method
The proxy is the main point of interaction for any piece of code that wants to publish to Slack because it will control whether or not to publish to Slack or STDOUT depending on if a write key is present. This can be incredibly useful for separating between local development, preprod, or production. In local and preprod you can omit the environment variable with the write key and see the output in STDOUT, or you can add the key in temporarily to test the connection. Regardless of what environment the code is running in, the interface or its variables do not change which leads to clean consumption to the caller of the proxy. See below as an example.
from publishers import SlackPublisherProxy SLACK_PUBLISHER = SlackPublisherProxy() ... SLACK_PUBLISHER.publish('this is a test event', 'test-channel')