Jeffery Matthias

Future-proofing Your 3rd Party Services

Future-proofing Your 3rd Party Services

by Jeffery Matthias

This talk, delivered by Jeffery Matthias at the Rocky Mountain Ruby 2014 conference, focuses on strategies for future-proofing third-party integrations within software architecture. It addresses the importance of isolating third-party services to enhance flexibility and maintainability in software products, especially as organizations shift towards Service Oriented Architectures (SOA).

Key points include:
- Separation of Concerns: Emphasizing the necessity of keeping third-party logic out of the core application code to avoid dependencies on external implementations.
- Predictable Behavior: Advocating for test-driven development to ensure interactions with third-party services are predictable and manageable.
- Replaceability: The concept that any third-party API should be replaceable, encouraging engineers to consider future changes when integrating these services.

The speaker shares insights on defining a clear architecture for such integrations, using a conceptual example involving a 'Music Box' app and a 'Teapot Adapter'. This adapter acts as a bridge between the application and third-party services, ensuring that the main application code remains agnostic to specific third-party implementations. Key architectural components include:
- Using Ruby gems to bootstrap adapters for third-party services.
- Routing messages to service objects that interact with these third-party services while keeping implementation details concealed from the main application.
- Importance of having a consistent internal vocabulary distinct from the third-party terminology, which helps in communication among stakeholders and minimizes confusion.

Finally, the talk emphasizes that while team members may never intend to swap out third-party services, planning for potential changes is critical. This foresight leads to better-designed systems that remain adaptable to change over time. In conclusion, the presentation advocates for a structured approach to managing third-party services to enhance the development process and safeguard against common pitfalls associated with legacy integrations.

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.”},{