lundi 17 avril 2017

Proxy class for parameter object

I need to make a proxy class to provide an access to some 3rd-party lib (xls generator) within my project. The proxy class itself is quite simple and mostly strait forward. But found that it becomes a bit tricky when I'm trying to control setting of parameters. Let's say I'm working with XLS document and my proxy class to provide a way to set some options for a Sheet or a Cell. The easiest (and most likely wrong) solution is to have something like this:

    abstract class AbsctractXLSProxy {
        protected $xls;
        abstract public function setSheetSomeOption($value);
        abstract public function setSheetOtherOption($value);
        abstract public function setCellOption1($value);
        abstract public function setCellOption2($value);
    }

    class MyXLSProxy extends AbsctractXLSProxy {
        public function __construct($xls) { $this->xls = $xls; }
        public function setSheetSomeOption($value) { $this->xls->setOption($value); }
        public function setSheetOtherOption($value) { $this->xls->setOption($value); }
        public function setCellOption1($value) { $this->xls->setOption($value); }
        public function setCellOption2($value) { $this->xls->setOption($value); }
        /*..... some other stuff */
    }

This is quite good approach in terms of stability, but I have to write a dedicated method in main abstract proxy for each option I ever want to set. Other option I see here is to create universal option setter for each sub-object. Something like this:

    abstract class AbsctractXLSProxy {
        protected $xls;
        abstract public function setSheetOption($optName,$optValue);
        abstract public function setCellOption($optName,$optValue);
    }

    class MyXLSProxy extends AbsctractXLSProxy {
        public function __construct($xls) { $this->xls = $xls; }
        public function setSheetOption($optName,$value) { $this->xls->getSheet->{'set'.$optName}($value); }
        public function setCellOption($optName,$value) { $this->xls->getCell->{'set'.$optName}($value); }
        /*..... some other stuff */
    }

This is more flexible, but won't protect me from running into some forgotten option hidden deep in the code which will not be supported by new proxy implementation.

Parameter objects could help me here to, at least, enumerate all options which my proxy have to support:

    class XLSSheetOptions {
        public $someSheetProperty;
        public $otherSheetProperty;
    }

    class XLSCellOptions {
        public $someCellProperty;
        public $otherCellProperty;
    }

    abstract class AbsctractXLSProxy {
        protected $xls;
        abstract public function setSheetOption(XLSSheetOptions $opt);
        abstract public function setCellOption(XLSCellOptions $opt);
    }

    class MyXLSProxy extends AbsctractXLSProxy {
        public function __construct($xls) { $this->xls = $xls; }
        public function setSheetOption(XLSSheetOptions $opt) { /* set sheet options according to XLSSheetOptions object */}
        public function setCellOption(XLSCellOptions $opt) { /* set cell options according to XLSCellOptions object */}
        /*..... some other stuff */
    }

Much better, but there is still no guaranty that I will have proper setter for each option presented in XLS*Options object.

Question: Is there any pattern or trick to tie together these two - abstract proxy class and parameters object? I want to be sure that whoever will intend to build new proxy implementation he will not leave any of required options uncovered.

Aucun commentaire:

Enregistrer un commentaire