Refactoring Logger interface to open and close logs I asked a question about an implementation of a logger using syslog and error_log as fallback that made me re-evaluate my Logger interface.  Before it simply forced a log($timestamp, $message) to be implemented but after reading over the answer to the question I'm not sure that this is the best API possible to work with all the different logging options available.

Here's my new interface that allows logs to be opened and closed.

&lt;?php

/**
 * @file
 * @brief Holds the interface to be implemented by objects responsible for logging
 * messages and data.
 */

namespace SprayFire\Logger;

interface Logger {

    /**
     * @brief We have left the parameters for this method blank on purpose; the
     * implementations should be responsible for passing the appropriate arguments.
     *
     * @details
     * It should be noted that if your implementation defines the method signature
     * with parameters you may assign a default value to that parameter and your
     * implementation will satisfy this method signature.
     *
     * @return true if log opened, false if didn't
     */
    public function openLog();

    /**
     * @param $timestamp the timestamp for the given message
     * @param $message The string message that should be appended to the end
     *        of the log
     * @return true if the message was logged, false if it didn't
     */
    public function log($timestamp, $message);

    /**
     * @return true if the log was closed, false if it didn't.
     */
    public function closeLog();

}


My problem is keeping the interface generic enough while allowing the various different options needed in opening a log to be satisfied.  For example, NullLogger wouldn't really need any parameters passed to openLog() where as SysLogLogger would probably need some parameters passed.  How would I accomplish this?

What I'm thinking now

That parameters will be passed as variable arguments to the function and the implementation uses func_get_args() to retrieve the necessary information to open the log, if necessary.

Alternatively, the implementation could simply define the parameters needed and ensure there are default values for all parameters.  This would ultimately supply the needs of the interface while still communicating to the user that parameters are needed.

What I could be doing

I could declare the parameter passed to openLog() as an array that holds the appropriate option information.  This means though that I would need to create an array for every Logger, whether it is needed or not.  I'm not one to micro-optimize but at the same time I don't want to be creating unused/needless resources.

I could declare the three parameters passed to openlog in Logger::openLog, and then declare default values for those in the method signature signaling that you could simply not provide these arguments.  But, this really doesn't "feel" right, you'd also be signaling to the user that you could pass arguments to say, NullLogger, that might actually influence the way the implementation works and it really wouldn't.

I'm not sure what would be the best solution here and would appreciate any feedback on the interface's API and the solutions proposed.
NullLogger wouldn't really need any parameters passed to 
  openLog() where as SysLogLogger would probably need some 
  parameters passed. How would I accomplish this?


Pass these parameters to the constructor, store in a private field and use it in the openLog (or any other) function.

If you use func_get_args() you wouldn't be able to replace the logging system without modifying the client code.

SLF4J is a great example for a logging framework. Check it's Logger interface. It contains some methods but none of them depend on any implementation. Logback, Log4j, JCL and other implementations implements this simple interface and their external configuration determines the details.

A note: maybe timestamp shouldn't be passed to the log function, it should be the internal of the logger implementation.