There're several and good reasons why you should avoid flag function arguments whenever possible. Some reasons are:
Ideally, functions should do only one thing. Flag arguments are good hints of functions doing more things besides the one denoted by their names. Functions doing more than one thing are at the edge of breaking the principle of least astonishment. Taking care of POLA improves significantly the best code quality indicator you can have.
Functions doing more than one thing are especially troubling when their name don't tell the reader what other things they do and how the flag argument is conditioning the behavior. That's the case of the function in option #2. See how it's seen from the consumer standpoint. [N1]
//What the hell, "true" does mean?
$id = "myId";
getDocument($id, true);
//... not much better
$download = true;
getDocument($id, download);
- Functions with no arguments (niladic) or one argument (monadic) are easy to reason about (when both, function and argument are properly named). But things start getting complicated with 2 (dyadic) or more arguments tryadic,polyadic, etc). They are not only harder to understand at first glance; they are also harder to test because it takes testing all the permutations possible.
With these 3 points in mind, the proper approach would be option #1. Having two well-differentiated functions, properly named, short and concise.
class DocumentApi{
private const API_DOCUMENT_URI_TEMPLATE = '/api/v1/$id';
private const API_DOWNLOAD_URI_TEMPLATE = self::API_DOCUMENT_URI_TEMPLATE.'/download';
private const DEFAULT_HTTP_REQUEST_HEADER = array(
'Accept' => 'application/json'
);
private function doGet($path, $uriParams, $httpRequestHeaders){
$uri = strtr($path, $uriParams);
//http client goes here
}
function getDocument($documentId){
$queryParameters = array(
'$id' => $documentId
);
doGet(self::API_DOCUMENT_URI_TEMPLATE ,
$queryParameters,
self::DEFAULT_HTTP_REQUEST_HEADER );
}
function downloadDocument($documentId){
$queryParameters = array(
'$id' => $documentId
);
//In PHP arrays are assigned by copy
$httpRequestHeaders = self::DEFAULT_HTTP_REQUEST_HEADER;
$httpRequestHeaders['Accept-Encoding'] = 'gzip, deflate';
$httpRequestHeaders['Accept'] = 'mime-type/*';
doGet(self::API_DOWNLOAD_URI_TEMPLATE, $queryParameters, $httpRequestHeaders);
}
}
[N1]: Some may say that it just takes checking the function's signature to know what's the argument's name and guess what is it for. This is bad for three reasons: 1. Code that makes you dive into the source code is clearly not clean code, it's untrusty code. 2. The laziness of the developer in charge of the code still can surprise you with things like getDocument(id, bool)
. 3. For a reason, you neither have documentation nor the source code of the function and the IDE shows up something like getDocument(arg0, arg1)