00:00:13.759
Hey!
00:00:20.800
Hey, hey!
00:00:25.920
Hey, alright! Hey, everybody!
00:00:30.960
Do me a favor, raise your hand if you like working with legacy code.
00:00:39.000
Alright, well you guys are missing out! Legacy code is awesome! It tells us everything not to do, and if it wasn't for that, we'd go and repeat some of those mistakes.
00:00:45.640
So, I'm Jeffrey Matthias, I'm an engineer with SRID, and I'm going to talk to you about future-proofing your third-party integrations.
00:00:52.079
This is a collection of practices. I'm not going to claim they’re the best practices, but they've been working really well for us, and that's why I put them together to share.
00:01:05.479
My team's job, as Tim just mentioned a minute ago, is to work from a monolithic Rails app and split that out.
00:01:11.840
We have a similar situation at SRID; we have a pretty fast-growing company with a monolithic PHP app. That is awesome, because it means it gives me a job.
00:01:18.080
One of our core responsibilities is extracting our third-party services from being spaghetti dependencies into a manageable pattern.
00:01:24.200
We can repeat this process and we use Rails to do it, but the stuff I’ll be talking about today applies to any Ruby application.
00:01:30.720
Many of the patterns I’ll show today come from our work with Pivotal Labs about nine months to a year ago, and we’ve built on top of that.
00:01:38.680
When we're looking at a third-party integration, we have a few main goals to manage that interaction.
00:01:44.240
The first one is to keep third-party logic out of our code. I probably don’t need to make a case to you about that.
00:01:49.960
As soon as somebody else’s implementation starts influencing the way you write your code or even think about things, you start becoming dependent on their implementation. It's scary!
00:01:55.439
The next aspect is making our third-party behavior predictable, and we do that by test-driving our code.
00:02:01.479
The last point is making our third-party interactions replaceable.
00:02:07.520
As an engineer at SRID, I'm fully aware that I'm telling you to make my company's product replaceable, and I firmly believe that any third-party API you use should be.
00:02:15.000
Let’s take a look back. I actually have a degree in art—I can prove it! I have an amazing drawing here.
00:02:20.040
My professors would be so proud! This is a general look at what the architecture looks like.
00:02:25.360
The 'Music Box' app obviously doesn’t have anything called 'Music Box' nor do we have a 'My Little Teapot' third-party service.
00:02:30.480
The most important thing to understand is that there's this adapter sitting in the middle, and we have the internet, or something.
00:02:37.120
This doesn't just apply when I say third-party integrations; I'm not just talking about outside your company.
00:02:43.080
Anytime you're engaging—since we’re all moving to Service Oriented Architecture, breaking things up—you need to assess the dependencies on your logic.
00:02:49.080
How intertwined are your actual dependencies with your own internal applications?
00:02:54.840
For example, we currently have a database abstraction at SRID that people like or don’t like, but the point is we're applying this pattern for our internal service too.
00:03:01.040
Someday, someone might agree or disagree with us and not like that service enough to replace it, so we want to ensure flexibility.
00:03:08.400
This 'Teapot Adapter' is designed for our third-party service. The key aspect is that it's just a Ruby gem.
00:03:14.400
By using 'bundle gem teapot_adapter,' you create and bootstrap a gem for us.
00:03:21.210
When you do that, you don’t need to push it anywhere; keep it in your repository and specify the path for your gem file.
00:03:28.880
I hope most of you have already been using this to organize your code.
00:03:36.000
This provides a very clear separation line for our concerns, allowing the SRID logic to remain in the application while third-party logic resides in the adapter.
00:03:43.040
All you need to focus on is the messages exchanged in between.
00:03:50.960
That said, don't ignore third-party SDKs that provide libraries for you to utilize their services. They have put in hard work, and you should leverage that.
00:03:56.880
I'm not suggesting you reinvent the wheel by rolling your own gem, but the messages passing into this adapter should be in your own language.
00:04:04.640
The implementation should utilize any existing code. Your adapter gem can still use the SDK or gem from the third party or anyone else.
00:04:11.680
Let’s go back and look at this architecture again. It’s really just a basic architecture composed of service objects.
00:04:17.000
Your messages are routed to these service objects, which then call out to the third party, returning appropriate objects.
00:04:23.760
One of the most crucial aspects of setting up this architecture is ensuring that your main application doesn’t know what adapter it’s using.
00:04:30.720
It knows how to communicate with the adapter, but doesn’t know which one to use.
00:04:37.040
The only place you should see the name of that adapter is in some initializer.
00:04:44.000
This reflects our current version of a Rails initializer, and the bottom lines show where we hand over the service name.
00:04:50.720
That should be the only instance within your entire application where references to that adapter are made.
00:04:56.640
Once that’s established, we use a configuration class to refer to our services by the configuration instance.
00:05:01.120
For those unfamiliar, this denotes the use of a Singleton pattern, which is one of the few places I would recommend it.
00:05:07.600
Again, I want to emphasize that this is the only place in the application where the 'Teapot' should appear in your 'Music Box' app code.
00:05:13.440
How do you begin moving toward this standard?
00:05:19.440
First, clearly define your internal vocabulary. This could not have followed a better talk than Mike’s discussion on understanding your domain and concerns.
00:05:26.000
We need to know how we regard our business structure and avoid focusing on that third-party service.
00:05:32.280
This means getting everyone to agree on terminology. It often seems obvious, but when talking with business owners, product owners, or stakeholders, it's crucial to ensure they are on the same page.
00:05:39.320
You'll find variances often; getting consensus sets the vocabulary for messaging between your application and the adapter.
00:05:48.760
Even if you never intend to replace a third-party service—first off, you should always plan to replace third-party services—you should maintain your own language.
00:05:55.360
Ensure how you articulate things is relevant to your company and distinct from the third party.
00:06:01.600
For instance, from our perspective, when we mention a package, our third-party provider relates to it as a product rate plan.
00:06:07.600
When referring to add-ons, they talk about a product rate plan as well.
00:06:13.800
A coupon is referred to as a product rate plan charge by the third party.
00:06:20.000
This differentiation simplifies conversations with our teams.
00:06:27.440
We can reference packages, add-ons, and coupons very clearly, while those who must deal with the third-party service should understand the details.”},{