The Visibility Debate

4609827016_1bb49bf82c_b
Standard

A lot has been said about when to use public/private/protected. Some say that you should never use private, while others say you should never use protected.

About the only thing that people can seem to agree on is that public should be used with caution. That your versioning should be based around your public API, and you have a responsibility to maintain that API.

The issue is mainly around the maintenance responsibility of protected vs private. Given that other developers can depend upon protected, it can effectively be considered to have the same overhead as your public API.

I personally very rarely use private properties, and I default to protected.

My thinking is thus:

  1. The public API is sacrosanct, following SemVer, breaking the public API shall bring a new major version. I will do my best to support an existing public API for as long as possible and only break backwards compatibility as a last resort.

  2. The protected API is important. It does not impact SemVer, though often accompanies changes at the X.Y level. However I pledge to document any changes in release notes and otherwise, to ensure that if you pay attention you will be able to track changes and avoid issues. I will make changes as necessary to the protected API. (n.b. as I write this, I’m considering making it a rule that X.Y should be incremented for protected changes, always)

  3. The private API is the wild west, and you’re on your own.

I think this is a pretty pragmatic approach, it preaches caution and engagement when extending third party libraries, yet does not needlessly prohibit the ability to extend entirely.

GuzzleHttp VCR

Project

A few days ago I pushed out a very small library to help with testing APIs using Guzzle: dshafik/guzzlehttp-vcr.

This is a simple middleware that records a request’s response the first time it’s made in a test, and then replays it in response to requests in subsequent runs.

It does this by returning a Guzzle \GuzzleHttp\HandlerStack with either the \Dshafik\GuzzleHttp\VCRHandler middleware, or the GuzzleHttp\Handler\MockHandler added. The first will record the responses to JSON files, while the latter will be pre-loaded with those responses and will return them when requests are made.

It’s important to understand that the responses are returned in order regardless of whether it is the same request being made.

The purpose of this library is to just make it easier to create and update your tests for API clients.

Usage is simple, just call Dshafik\GuzzleHttp\VCRHandler::turnOn() passing in the storage location before running the test, and pass in the handler as a guzzle client option:

You can pass in the handler when instantiating the \GuzzleHttp\Client, or when making the individual requests — if you use the same instance for the individual requests it will re-use the same JSON file for storage, otherwise if you pass in unique instances (with unique storage files) it will create individual ones. I recommend passing in the handler to the constructor, but ensuring that you use a new instance (of the middleware, and the client) for each test.

Hopefully folks find this useful, do let me know if you do. If you have issues, please report them and pull requests are welcome!

I’ll be releasing a new Akamai library which uses dshafik/guzzlehttp-vcr next week (probably) so look out for that if you want to see it’s use in a real project.

Return Values

Standard
This post is over 7 years old and is probably out of date.

In #phpc we recently had a discussion about function return values; specifically from database queries.

I’m going to go on a (admittedly, rather sturdy looking) limb and say this applies to pretty much any function that returns from a data resource, not just a database .

My preference, is to return false only for error conditions, or when a function is supposed to only return one result (i.e. when selecting on a primary key) and fails to find any result.

However, it’s very rare that I care about whether I hit an error condition or just got no result when it comes to display — more to the point, my user doesn’t care.

There is a simply solution though, an empty array, also evaluates as false.

[php]
function getData()
{
    if (error()) {
        return false;
    } elseif (noData()) {
        return array();
    } else {
        return myData();
    }
}

if (!$data = getData()) {
    foreach ($data as $row) {
         // Show data
    }
} else {
    echo “No data found.”;
}

// or

$data = getData();

if ($data === false) {
    myLog(“Something Bad Happened!”);
}

if (!$data) {
   echo “No data found.”;
} else {
   // iterate
}
[/php] 

This gives the best of both worlds IMO — the ability to distinguish error conditions or not depending on if you need to in the given context.

– Davey

P.S.

This might be the start of a series of thoughts on common API best practices