Tell, Don't Ask

grigori

( ͡° ͜ʖ ͡°)
Команда форума
не, там нормально получается:
PHP:
class ActiveRecord{
public function query(){
$result = $dbobject->query($queryobject);
$this->values = new ValueObject($result);
}
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
У нас это шаблонизатором решается:

{% for user in users %}
зато это никак не решается в контроллере, где надо сделать ветвление логики:
if ($User = Users::findByLogin($POST['login'])){
redirect('/account/'.$User->id);
}else{
redirect('/login/');

обязательно нужен отдельный метод Users::checkIfUserExists()

конечно, данный случай решается выкидываением исключения в findByLogin(), но не всегда это удобно
 
Последнее редактирование:
  • Like
Реакции: WMix

С.

Продвинутый новичок
Как любая абстрактная парадигма "Tell, Don't Ask" задает генеральное направление, но не решает частные вопросы. Если ей следовать до самого конца, то вместо простого объекта с методами типа $obj->doThis(), мы получим кучу уродливых $obj->doThisIfCondition().
 

флоппик

promotor fidei
Команда форума
Партнер клуба
зато это никак не решается в контроллере, где надо сделать ветвление логики:
Ну это же нормально, нет?
TDA не говорит о логике приложения, это правило взаимодействия с объектами — скажем, просто часть ООП-парадигмы.
if в контроллере для принятия решения — это нормально.

PHP:
if ($model->loaded())
{
 $view->set($model);
}
else
{
 throw new HTTP_404();
}
— это ок.

PHP:
if ($Request->type == 'json')
{
 $this->view = new JsonView('views/template.json');
 $this->view->set($model)->render();
}
else
{
 $this->set($model);
}
— не ок.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
да, это нормально, и это делается красиво через null-объекты, которые, к сожалению, пока только в pecl
 

AmdY

Пью пиво
Команда форума
Реквестирую следующий паттерн - SILENT, а то слишком много tell-ов

PHP:
$User = User::find($login);
View::render('template',['user'=>$User]);
и это
$this->view = new JsonView('views/template.json');
$this->view->set($model)->render();
Зачем харкодить модель с юзером, влюху, передавать явно шаблон?
Вот примерно максимально минимальный код.
PHP:
function profile(User $user) {
return $user;
}
DI сам найдёт модель, диспетчер возьмёт из роутера ID и дёрнет метод find, после ретурна проверяется тип запроса (json, xml, html). Если нужны первые, то просто вызывается сериализация модели в нужный формат с учётом прав и скрытых полей. Если html, то кастуем имя шаблона $controller/action и выводим его. Всё это довольно легко программируется практически на любом фреймворке, даже на ZF.

Зачем спрашивать и говорить, если можно молчать?
 
Последнее редактирование:

Ragazzo

TDD interested
helloworld
перевел статью фаулера, на хабре видимо будет бурное обсуждение :)
AmdY
это тебе к rails :)

p.s. странно, что на таком очевидно месте столько вопросов, когда вся суть заключается в том что всю ответственность за свое состояние объект должен возложить на себя согласно SOLID и прочим :)
 

Вурдалак

Продвинутый новичок
Какой нафиг Rails, это и в Symfony есть: FOSRestBundle + ParamConverter:
PHP:
class UserController extends Controller
{
    /**
     * @Rest\View
     */
    public function viewAction(User $user)
    {
        return $user;
    }
}
Код:
/user/42.json
/user/42.xml
...
Няшно, ага.
 
  • Like
Реакции: AmdY

Redjik

Джедай-мастер
Суммирая все вышесказанное (+ Фаулер) пришел к тому же выводу, что дедушка - не всегда Tell, Don't Ask нужен.
Если взять пример из сабжа, то по Tell, Don't Ask логике должно быть как то так:
PHP:
$model = DbQuery::makeModelFromData('ModelName',$criteria);
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
DI сам найдёт модель, диспетчер возьмёт из роутера ID и дёрнет метод find, после ретурна проверяется тип запроса (json, xml, html).

Зачем спрашивать и говорить, если можно молчать?

1. DI найдёт модель по статическому соответствию URL на файл?
у меня веб-сервис на JSON-RPC 2, моделей мало, но есть несколько API с разными параметрами и разной авторизацией: в одном идет SSL-сертификат, в другом - basic auth, третий открыт, и какой же мапинг тут сделать?

2. у меня уже ~50 методов в API, и скоро их будет 100, и еще они собираются в batch-запросы, так какой же мапинг тут сделать?

3. диспетчер возьмёт из роутера ID - а откуда диспетчер его возьмет: из SSL или из RPC-параметра? а, так нам нужен полноценный контроллер! так что этому контроллеру делать: tell или ask? :)

не всем хватает REST ;)
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Суммирая все вышесказанное (+ Фаулер) пришел к тому же выводу, что дедушка - не всегда Tell, Don't Ask нужен.
Если взять пример из сабжа, то по Tell, Don't Ask логике должно быть как то так:
PHP:
$model = DbQuery::makeModelFromData('ModelName',$criteria);
А почему не new ActiveRecord->query($dbobject, $queryobject);
 
Сверху