views:

44

answers:

2

Sometimes I come across this problem where you have a set of functions that obviously belong to the same group. Those functions are needed at several places, and often together.

To give a specific example: consider the filemtime, fileatime and filectime functions. They all provide a similar functionality. If you are building something like a filemanager, you'll probably need to call them one after another to get the info you need. This is the moment that you get thinking about a wrapper. PHP already provides stat, but suppose we don't have that function.

I looked at the php sourcecode to find out how they solved this particular problem, but I can't really find out what's going on.

Obviously, if you have a naive implementation of such a grouping function, say filetimes, would like this:

function filetimes($file) {
    return array(
        'filectime' => filectime($file)
        ,'fileatime' => fileatime($file)
        ,'filemtime' => filemtime($file)
    );
}

This would work, but incurs overhead since you would have to open a file pointer for each function call. (I don't know if it's necessary to open a file pointer, but let's assume that for the sake of the example).

Another approach would be to duplicate the code of the fileXtime functions and let them share a file pointer, but this obviously introduces code duplication, which is probably worse than the overhead introduced in the first example.

The third, and probably best, solution I came up with is to add an optional second parameter to the fileXtime functions to supply a filepointer.
The filetimes functions would then look like this:

function filetimes($file) {
    $fp = fopen($file, 'r');
    return array(
        'filectime' => filectime($file, $fp)
        ,'fileatime' => fileatime($file, $fp)
        ,'filemtime' => filemtime($file, $fp)
    );
}

Somehow this still feels 'wrong'. There's this extra parameter that is only used in some very specific conditions.

So basically the question is: what is best practice in situations like these?


Edit:
I'm aware that this is a typical situation where OOP comes into play. But first off: not everything needs to be a class. I always use an object oriented approach, but I also always have some functions in the global space.
Let's say we're talking about a legacy system here (with these 'non-oop' parts) and there are lots of dependencies on the fileXtime functions.

tdammer's answer is good for the specific example I gave, but does it extend to the broader problem set? Can a solution be defined such that it is applicable to most other problems in this domain?

+1  A: 

Use classes, Luke.

Lavir the Whiolet
A: 

I'd rewrite the fileXtime functions to accept either a filename or a file handle as their only parameter. Languages that can overload functions (like C++, C# etc) can use this feature; in PHP, you'd have to check for the type of the argument at run time.

Passing both a filename and a file handle would be redundant, and ambiguous calls could be made:

$fp = fopen('foo', 'r');
$times = file_times('bar', $fp);

Of course, if you want to go OOP, you'd just wrap them all in a FileInfo class, and store a (lazy-loaded?) private file handle there.

tdammers
It is indeed better to let it accept either a filename or a pointer. Thanks.
Dennis Haarbrink
On a sidenote, PHP already has a FileInfo class with `SplFileInfo` and `SplFileObject`, which do provide access to the filetimes as well.
Gordon