0

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?

Community
  • 1
  • 1
Dennis Haarbrink
  • 3,738
  • 1
  • 27
  • 54
  • check out this question (and many others tagged object-oriented' or 'oop') for copious background on the well-known problem you have hit here. http://stackoverflow.com/questions/355796/how-do-you-explain-oo-to-new-programmers – Steve Townsend Sep 25 '10 at 15:40
  • I'm well aware of general OOP practices. But this is not about OOP, see the updated question. – Dennis Haarbrink Sep 28 '10 at 07:48

2 Answers2

1

Use classes, Luke.

Lavir the Whiolet
  • 1,006
  • 9
  • 18
0

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
  • 20,353
  • 1
  • 39
  • 56