Marc Guinea
Posted on August 10, 2021
You are developing an application that requires an integration with a third party API to provide you some data or any other functionality but... what is the best way to approach it? should I use anything special?
As always, there is no a magic perfect approach, but I will explain what worked for me.
Context example
First of all, we need to define what exactly we want to and what we need.
Our application needs some external service (API) that giving a minimum and maximum integer numbers, it returns a random integer number.
Then, after defining or requirements and use cases, it's time to search the best service that covers it all.
There is a service that fits our requirements! let's create a provider that implements http://www.randomnumberapi.com
Definition
We have made the effort to know what we need and how, so it's time to define a contract (interface).
Why? if we have an interface that defines the methods to use and the parameters, the implementation can be changed at any time without breaking down the application.
We need some name that identifies what is it doing. This is one of the most complex parts of development... NAMING!
- Do not use words that do not add anything like
manager
. - Read the user story that defines what is needed to get some clues.
- Never use the name of the specification you are going to implement.
- Avoid acronyms or abbreviations.
interface RandomNumberProvider
{
public function generate(int $min, int $max): int;
}
Now, it's time to create a class that implements our interface.
Implementation
There are different http clients that will help us to make a connection to an external API. I like those which implements PSR standards as much as possible.
I will use Guzzle but feel free to use the one you like the most.
If you are using composer, just run composer require guzzlehttp/guzzle
to install it in your project as a new dependency.
use GuzzleHttp\Client as HttpClient;
final class RandomNumberAPIProvider implements RandomNumberProvider
{
private HttpClient $client;
public function __construct(HttpClient $client)
{
$this->client = $client;
}
public function generate(int $min, int $max): int
{
$response = $this->client->request('GET', 'http://www.randomnumberapi.com/api/v1.0/random?min='.$min.'&max='.$max.'&count=1');
return json_decode($response->getBody(), true)[0];
}
}
Use the benefits of a Service Container and bind the interface to the implementation to keep Inversion of Control (Dependency Inversion Principle). This brings you the possibility to change the implementation to another API or service without breaking the application.
Testing
Some API have a quota limitation of usage or maybe they will charge you costs even in development environment.
A good approach is to mock it using some tool for this purpose.
I have used Killgrave and the result was really good. The best of all is that you can configure a mock API just using yml configurations files.
Conclusion
It's easy to be overwhelmed when integrating some external API so, if we start thinking on what we need and forgetting the complexity of the specific implementation we will have a better overview and we will not fall in a headache hell.
Interfaces bring us the benefit of separation of concerns and avoid to be hardly coupled to an external implementation. This gives us freedom to change the service if our requirements change.
Posted on August 10, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.