3

Original question here

I am learning OOP and SOLID. I have a 'main' class that performs some actions after reading variables from a config file. This 'main' class is not the focus of this question but it can be described as a concretion.

I am trying to split up the process of reading the config file and using its settings in the 'main' class.

I am thinking of making a Config class.

interface ConfigInterface {
    public function getFileContents();
}

class Config implements ConfigInterface {
    protected $file_path;
    protected $file_contents;

    public function getFileContents() {
        return $this->file_contents;
    }

    protected function readFileContents() {
        $file_path = $this->file_path;
        if ( is_file( $file_path ) ) {
            $file_contents = include( $file_path );

            return $file_contents;
        } else {
            die( 'Invalid config path specified ' . $file_path );
        }
    }

    public function __construct( $file_path ) {
        $this->file_path     = realpath( $file_path );
        $this->file_contents = $this->readFileContents();
    }
}

This allows a user to get all the settings as a single array from the public method.

However, as a class, I can't help but feel these settings retrieved as an array should be assigned as individual properties of the object with public accessors. As such, these settings would be unique to my 'main' class. In this case, I'm thinking of extending a generic Config class with a MainConfig class which would have these specific properties / accessors in relation to my 'main' class.

interface ConfigInterface {
    // A config has a path, but doesn't need to have a public interface
    // So don't know what goes in here now
}

class Config implements ConfigInterface {
    private $file_contents;

    public function __construct( $config_path ) {}
    protected function readContents() {}
}

class MainConfig extends Config implments ConfigInterface {
    private $main_settings_one;
    private $main_settings_two;
    private $main_settings_three;

    public function getMainSettingOne() {};
    public function getMainSettingTwo() {};
    public function getMainSettingThree() {};
}

Firstly, is this a correct approach or is it better to keep the array? Also, does an interface / base class need functions defined? Or can these be defined later?

Secondly, do I need a ConfigHandler / ConfigReader class? If my 'main' class needs the settings to work, could I just pass the config object to the 'main' class and have a function do this? Or is it a seperate responsibility of another class?

I am also learning coding to an interface. My 'main' class only works with specific settings (is this a concretion?) So if I had

class Main {
    public function __construct( ConfigInterface $config ) { // coding to interface
        $config->getMainSettingOne(); // specific functionality relating to a concretion?
    } 
}

$conf = new MainConfig( $path );
$main = new Main( $conf );

If anything but a MainConfig is passed then my 'main' class will not initialise properly. I was thinking of a 'specialised' interface, for use with my 'main' class.

interface MainConfigInterface {
    public function getMainSettingOne();
    public function getMainSettingTwo();
    public function getMainSettingThree();
}

class Config { ... }

class MainConfig extends Config implments ConfigInterface {
    private $main_settings_one;
    private $main_settings_two;
    private $main_settings_three;

    public function getMainSettingOne() {};
    public function getMainSettingTwo() {};
    public function getMainSettingThree() {};
}

Then back in my 'main' class, I can still code to an interface?

class Main {
    public function __construct( MainConfigInterface $config ) { // coding to interface
        $config->getMainSettingOne();
}

$conf = new MainConfig( $path );
$main = new Main( $conf );

Finally, is this the correct way to code to an interface in this regard?

3

Firstly, is this a correct approach or is it better to keep the array? Also, does an interface / base class need functions defined? Or can these be defined later?

Yes, an interface need functions defined, if not where is the sense of having an interface? An interface works like a contract between a consumer and his client. In this case the Main class consumes the Config class. This contract could be: The Main class needs that a Configuration on initialization brings the settings One and Two.

    interface ConfigInterface {
      public function getConfigOne();
      public function getConfigTwo();
    }

(Maybe this is too rigid, because it means that your Main class only going to need two settings)

And then you can have classes that implement this interface in different ways

class StaticConfig implements ConfigInterface {
    public function getConfigOne(){
      return "configOne";
    }
     public function getConfigTwo(){
       return "configTwo";
     }
}
class DynamicConfiguration implements ConfigInterface {
   private ConfigReader reader;

   public function getConfigOne(){
        reader.readConfigurations(1);
   }
   public function getConfigTwo(){
      reader.readConfigurations(2)
   }

If anything but a MainConfig is passed then my 'main' class will not initialise properly. I was thinking of a 'specialised' interface, for use with my 'main' class.

If you are expecting something specific you should not use an interface because you are not accepting the contract, you are excepting something that the interface can't give you. A specialised interface it's not the answer either, simply because you can write:

class Main {
    public function __construct( MainConfig $config ) { 
        $config->getMainSettingOne();
}

Your example it's too abstract because i don't how your Main class consumes the settings. It will be more than a Main class? It's for system-wide properties? or it's part of the domain model? However i wanted to answer because empty interfaces are a bad practice and should be avoided. If you can detail a little more it would help me to bring you a better answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.