Crossposted from my personal blog
I was recently reading the sad news about Balanced Payments shutting down. I was a fan of the company, so of course this article struck a chord. But I also found it interesting that a lot of people were downtrodden about the prospect of having to go through their codebase and replace all calls to the Balanced API with a replacement (Stripe in this case).
This might be a bit of an easy piece of advice, but it has saved us from having to do this in the past a bunch of times: keep your 3rd party providers locked inside wrapper classes. What do I mean by this? Basically, in your codebase you should never see a direct call to a 3rd party provider. If you look at your controllers, models, interactions, whatever, and you see yourself doing something like:
Stripe.charge(...)
Braintree.charge(...)
Balanced.refund(...)
Or anything similar to that, be it Airbrake or Bugsnag, or anything, there’s room for improvement! You wanna keep these guys locked in nice little wrapper classes. For example:
PaymentProvider.charge(...)
Where the class PaymentProvider
actually holds all the logic about which 3rd party payment vendor to invoke:
class PaymentProvider
class << self
def charge(...)
Braintree.charge(...)
end
end
end
That way, if you ever need to change payment providers, or error reporting tools, or metrics analytics, or whatever, you just change that one file, that one wrapper class, instead of having to go searching through your entire codebase for invocations.
Another nice thing these interface wrapper classes add is clarity: they make it very apparent which pieces of 3rd party vendor’s offering you’re actually using, which is in turn incredibly helpful when analyzing your business needs should you ever have to look for a replacement, etc.