HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Restful API Building: Dependency injection + factory patterns

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
factorydependencybuildingpatternsrestfulinjectionapi

Problem

I am learning OOP. I feel I have a grasp of basic dependency injection in that as a rule of thumb, you pass an object to a method rather than the parameters to create an object. As such, never create an object within a method, but use a factory. Right?

The code below is for connecting to a REST API. However, I feel am I overcomplicating it. The $url which is used to access the API has a number of steps in its creation before it can be used. This is what is throwing me.

I think the best approach is to create a factory RequestFactory, call it statically from within getRecord() and pass the $type (GET, POST etc) $url, $username, and $password to return the results of either a ServiceGetRequest or a ServicePostRequest.

In my code, I have stopped just before this part however and just instantiated new objects. I don't know if the single factory is the right direction, or that I should have two factories.

My thinking is with two factories one factory would create an object RequestDetails (containing the $username, $password and $url) to pass to the other RequestFactory rather than a bunch of parameters as with only one factory. I assume this would adhere to basic dependency injection by passing an object to a method? The down side to creating an object just to pass to a method is that the Request Details object then shares properties of the ServiceDetails object - $username, $password...

My final thought is that I could instead change ServiceDetails to include a $url property which is empty on instantiation, then when the $url has been created, rather than create new objects using factories, simply modify the existing ServiceDetails $url property since this is the main object which is being passed around. I thought this could make sense to reduce needless code duplication as two objects would otherwise share the same $username and $password. Or would this violate SoC somehow? Or would this violate dependency injection since th

Solution

Never ever turn off SSL certificate verification:

CURLOPT_SSL_VERIFYPEER => false


means you're throwing away SSL protections, you might as well just not use SSL.

--


As such, never create an object within a method, but use a factory. Right?

Dependency injection and factory method are useful patterns to solve a certain problem, but you should not overuse them when the problem doesn't apply. Use the SOLID principle to guide your design, and apply these patterns to implement dependency inversion principle. In your code, the dependant class SpecificAPI actually knows the implementation of Details concrete classes, thus it had failed to invert the dependency between API to *Details.

I suggest that, rather than having ServiceDetails class, you should split it to class that does BasicAuth($username, $password). The reason we separate in a BasicAuth class is that so that the Auth classes encapsulate the details of the how the API authenticates to the service. You can swap it with other auth class, for example OAuth2, DigestAuth, MyCustomAPIAuth, etc and your SpecificAPI class would not need to change if you decided you want to change the authentication mechanism.

This can be done like so:

$auth = ...;

// convert unauthenticated request to authenticated request
$request = $auth->apply($request);
// alternatively, modify the request in-place
// $auth->apply($request);


--


From what I have gathered, many sources seem to imply that the API itself is either RESTful or not, rather than the code used to access it. Is this true?

Yes, ultimately REST is a characteristic of the API. But the code should also take advantage of the REST API to benefit from REST.

A REST API should be Resource-centric, not Service-centric. I don't see any Resources in your code.

Code Snippets

CURLOPT_SSL_VERIFYPEER => false
$auth = ...;

// convert unauthenticated request to authenticated request
$request = $auth->apply($request);
// alternatively, modify the request in-place
// $auth->apply($request);

Context

StackExchange Code Review Q#96021, answer score: 4

Revisions (0)

No revisions yet.