Interfacce, astrazione, codifica su un'interfaccia

3

Domande originali qui

Sto imparando OOP e SOLID. Ho una classe 'principale' che esegue alcune azioni dopo aver letto le variabili da un file di configurazione. Questa classe "principale" non è al centro di questa domanda, ma può essere descritta come una concrezione.

Sto provando a suddividere il processo di lettura del file di configurazione e usando le sue impostazioni nella classe 'main'.

Sto pensando di creare una classe Config .

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();
    }
}

Ciò consente a un utente di ottenere tutte le impostazioni come un singolo array dal metodo pubblico.

Tuttavia, come classe, non posso fare a meno di sentire queste impostazioni recuperate come un array dovrebbe essere assegnato come proprietà individuali dell'oggetto con i metodi di accesso pubblici. In quanto tali, queste impostazioni sarebbero uniche per la mia classe 'principale'. In questo caso, sto pensando di estendere una generica classe Config con una classe MainConfig che avrebbe queste proprietà / accessor specifici in relazione alla mia classe 'principale'.

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() {};
}

In primo luogo , questo è un approccio corretto o è meglio mantenere l'array? Inoltre, sono definite le funzioni di interfaccia / classe base necessarie ? O possono essere definiti in seguito?

In secondo luogo , ho bisogno di una classe ConfigHandler / ConfigReader ? Se la mia classe 'principale' ha bisogno che le impostazioni funzionino, potrei semplicemente passare l'oggetto config alla classe 'main' e fare in modo che funzioni? O è una responsabilità separata di un'altra classe?

Sto anche imparando la codifica su un'interfaccia. La mia classe 'principale' funziona solo con impostazioni specifiche (è questa una concrezione?) Quindi se avessi

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 );

Se viene passato un valore diverso da MainConfig , la mia classe 'main' non verrà inizializzata correttamente. Stavo pensando ad un'interfaccia "specializzata", da utilizzare con la mia classe "principale".

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() {};
}

Poi di nuovo nella mia classe 'principale', posso ancora codificare su un'interfaccia?

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

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

Infine , è questo il modo corretto di codificare un'interfaccia in questo senso?

    
posta myol 16.07.2015 - 18:26
fonte

1 risposta

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?

Sì, un'interfaccia ha bisogno di funzioni definite, se non dove è il senso di avere un'interfaccia? Un'interfaccia funziona come un contratto tra un consumatore e il suo cliente. In questo caso la classe Main consuma la classe Config. Questo contratto potrebbe essere: La classe Main ha bisogno che una configurazione sull'inizializzazione porti le impostazioni One e Two.

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

(Forse questo è troppo rigido, perché significa che la tua classe Main avrà solo bisogno di due impostazioni)

E poi puoi avere classi che implementano questa interfaccia in modi diversi

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.

Se ti aspetti qualcosa di specifico, non dovresti usare un'interfaccia perché non accetti il contratto, ma stai escludendo qualcosa che l'interfaccia non può darti. Un'interfaccia specializzata non è la risposta, semplicemente perché puoi scrivere:

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

Il tuo esempio è troppo astratto perché non so come la tua classe principale consuma le impostazioni. Sarà più di una classe principale? È per proprietà a livello di sistema? o fa parte del modello di dominio? Tuttavia volevo rispondere perché le interfacce vuote sono una cattiva pratica e dovrebbero essere evitate. Se puoi dettagliare un po 'di più mi aiuterebbe a darti una risposta migliore.

    
risposta data 16.07.2015 - 19:08
fonte

Leggi altre domande sui tag