я так понимаю он предлагает сделать что-то типаЯ, правда, так и не понял, как разделить парсер и либу. что передавать из парсера? Объект? Как это всё соединять потом?
PHP:
// псевдокодик
$conn = new MyDBLib( new MyPlaceholdersParser() );
я так понимаю он предлагает сделать что-то типаЯ, правда, так и не понял, как разделить парсер и либу. что передавать из парсера? Объект? Как это всё соединять потом?
// псевдокодик
$conn = new MyDBLib( new MyPlaceholdersParser() );
например:Я, правда, так и не понял, как разделить парсер и либу. что передавать из парсера? Объект? Как это всё соединять потом?
нет, я предлагаю сделать что-то типая так понимаю он предлагает сделать что-то типа
PHP:// псевдокодик $conn = new MyDBLib( new MyPlaceholdersParser() );
interface iSafeDbParser{
}
class SafeDb{
protected $parser;
setParser(iSafeDbParser $P){$this->parser = $p;}
getParser(){return $this->parser? : new SafeDbParser;}
}
$DB = new SafeDb;
$DB->setParser(new MyParser);
Через конструктор по-любому лучше. А причём тут tell don't ask — grigori его знает.нет, я предлагаю сделать что-то типа
ибо tell don't askPHP:interface iSafeDbParser{ } class SafeDb{ protected $parser; setParser(iSafeDbParser $P){$this->parser = $p;} getParser(){return $this->parser? : new SafeDbParser;} } $DB = new SafeDb; $DB->setParser(new MyParser);
извини, но это хочется в юмор перенести. сейчас удачный ход с одним файлом-классом и нафик не надо его растить в доктрину, которая жрёт места и ресурсов больше чем весь оставшийся проект.например:
1. Class SafeDB вызывает парсер Class SafeDbParser,
2. SafeDbParser парсит строку запроса с плейсхолдерами и возвращает SafeDbParameters, который знает какие в запросе есть имена и типы
плейсхолдеров
3. SafeDB отдает данные пользователя в SafeDbParameters
4. SafeDbParameters обрабатывает проверяет данные и приводит к нужным типам
5. SafeDB вызывает SafeDbQuery
6а. SafeDbQuery подставляет в строку запроса данные из SafeDbParameters
6б. SafeDbQuery приводит строку запроса с именованными плейсхолдерами к нативным плейсхолдерам PDO/MySQLi/Postgres
SafeDbQuery возвращает объект PDO или MySQL с прибайндиными данными
7. SafeDB вызывает вызов PDOStatement->execute() или mysqli_stmt->execute()
8. Результат запроса может оборачиваться в пользовательский класс или объект, который передается параметром в SafeDB
дальше с результатом запроса работает приложение или фреймворк
чем? я считаю, что меньше параметров у конструктора - удобней APIЧерез конструктор по-любому лучше.
tell don't ask - концепция, по которой класс не должен запрашивать параметр у другого объекта, он должен получить его извне,А причём тут tell don't ask — grigori его знает.
ну на то и "псевдокодик" =) главное посыл был пойман правильнонет, я предлагаю сделать что-то типа
ибо tell don't askPHP:interface iSafeDbParser{ } class SafeDb{ protected $parser; setParser(iSafeDbParser $P){$this->parser = $p;} getParser(){return $this->parser? : new SafeDbParser;} } $DB = new SafeDb; $DB->setParser(new MyParser);
Тем, что объект класса SafeDb не имеет смысла без инстанса iSafeDbParser. По определению, такие зависимости лучше передавать через конструктор.чем? я считаю, что меньше параметров у конструктора - удобней API
class SafeDb
{
protected $parser;
public function __construct(iSafeDbParser $parser = null)
{
$this->parser = $parser ?: new SafeDbParser;
}
}
Не понял: каким боком тут «tell, don't ask»? Ты просто перенёс внедрение зависимости в setter, хотя правильнее через конструктор, ибо см. выше.tell don't ask - концепция, по которой класс не должен запрашивать параметр у другого объекта, он должен получить его извне,
аналогично, не надо ждать, что в класс передадут значение в конструкторе, лучше позволять переопределить значение, и этим уменьшить связанность, упростить API
это по какому или чьему определению? пруф plz, ссылку, если это больше, чем личное предпочтениеSafeDb не имеет смысла без инстанса iSafeDbParser. По определению такие зависимости лучше передавать через конструктор.
новый холивар: setter injection VS constructor injection ! оставляю тебя победителем этой специальной олимпиадыхардкодить класс по умолчанию можно аналогично в конструкторе:
да, это демонстация принципа, а не сам код, herr grammar nazziналицо нарушение инкапсуляции для наследников класса.
По определению конструктора. Во всяком случае, в моём понимании, конструктор должен создавать валидный объект: http://martinfowler.com/articles/injection.html#ConstructorVersusSetterInjection. Это подход правильнее, но не всегда удобнее. А уж в приведённом примере, очевидно, никаких неудобств нет.это по какому или чьему определению? пруф plz, ссылку, если это больше, чем личное предпочтение
class Foo {
protected $dep=null;
protected function getDep() {
if (null === $this->dep) {
$this->dep = new DefaultDep;
}
return $this->dep;
}
public function setDep(IDep $dep) {
$this->dep = $dep;
}
}
class Foo {
protected $dep=null;
public function __construct(IDep $dep = null) {
$dep and $this->dep = $dep;
}
protected function getDep() {
if (null === $this->dep) {
$this->dep = new DefaultDep;
}
return $this->dep;
}
}