The Strategy Pattern, like any other design pattern, is supposed to help us write code that's flexible and easy to modify. In the case of the strategy pattern, you have one class, the Context
, which has a member which implements a Strategy
interface. The actual implementation lives in the Strategy
, but the Context
is the object that other code in the program consumes. Ideally, this means that you can change the behavior of your Context
by simply swapping a different Strategy
implementation in.
On the flip side, when it gets out of hand, you might end up like Dotan, consuming an API from a major cloud vendor, written with a terminal case of "Pattern Brain".
$backoff = $config->get(Options::BACKOFF);
if ($backoff === null) {
$backoff = new BackoffPlugin(
// Retry failed requests up to 3 times if it is determined that the request can be retried
new TruncatedBackoffStrategy(3,
// Retry failed requests with 400-level responses due to throttling
new ThrottlingErrorChecker($this->exceptionParser,
// Retry failed requests with 500-level responses
new HttpBackoffStrategy(array(500, 503, 509),
// Retry failed requests due to transient network or cURL problems
new CurlBackoffStrategy(null,
// Retry requests that failed due to expired credentials
new ExpiredCredentialsChecker($this->exceptionParser,
new ExponentialBackoffStrategy()
)
)
)
)
)
);
}
This was from the official vendor documentation, representing a pretty standard request that would run on every single page load.
Now, I'm sure this code works, and I'm sure that this chain of tested strategies and error handlers has a very good purpose. And maybe my hatred of deep nesting is just an aesthetic objection, and this isn't really a WTF.
But this is the worst way I can imagine to do this, even if you're insistent on chaining together all these objects. It's hard to read, and difficult to understand the purpose of all these, even the order of them- does it matter?
This is an API that's so flexible that it forgot to make the common use cases accessible to most developers. And while it'd be easy to wrap this up in some convenience methods, if it's a major vendor, one would hope that the API is a little more finished- even if it is the PHP implementation.