Как распознать Active Record?

WMix

герр M:)ller
Партнер клуба
Там правда все через хитрые прокси все сделано, но чисто внешне все выглядит именно так.
в этом и отличие в doctrine ($user instanceof User) == false, а в tdbm true.
по идеи эта строка в DM выглядит так
PHP:
$userMapper->country($user)->getLabel();
$users = $countryMapper->users($country)
ps ($user instanceof User) == false тоже не лучшее решение
 

WMix

герр M:)ller
Партнер клуба
Эм, UserProxy extends User, так что вполне себе true
в этом случае UserProxy становится AR нет?

PHP:
class UserProxy extends User{
  private $mapper; // вот мы все и вшили
  use ProxyTrait;
}
не многим лучше чем
PHP:
class User{
  private $dao;
}
отделить хранилище от сущностей
 

MiksIr

miksir@home:~$
этом случае UserProxy становится AR нет?
Нет, конечно, оно же не ходит само в базу
У АР достаточно четкое определение, зачем домыслы? Открываешь EAA и читаешь. Тоже и про ДМ. Там же в ДМ упомянут и LazyLoad, который тебя смущает.

отделить хранилище от сущностей
ну так сущность ничего не знает о хранилище как и о прокси, все происходит прозрачно
 

WMix

герр M:)ller
Партнер клуба
У АР достаточно четкое определение, зачем домыслы?
DM The Data Mapper is a layer of software that separates the in-memory objects from the database. Its responsibility is to transfer data between the two and also to isolate them from each other.
AR An object carries both data and behavior. Much of this data is persistent and needs to be stored in a database.

на что намекаешь хоть?


Нет, конечно, оно же не ходит само в базу
тут тоже не User ходит а dao
PHP:
class User{
  private $dao;
}
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
LazyLoad - это такой performance hack.
Фактически для тебя UserProxy === User. UserProxy корреткно реализован и не нарушает LSP, а никто, кроме ORM, не знает о существовании UserProxy.
 

WMix

герр M:)ller
Партнер клуба
LazyLoad - это такой performance hack.
Фактически для тебя UserProxy === User.
я вот что понять не могу в этом случае

PHP:
// допустим
interface UserRepository {
  public function getCountry():Country;
}

class UserProxy extends User implements UserRepository{/*...*/}

// какой тип вы ожидаете
public function fx(/* тут*/ $user){
 $user->getCountry()->getLabel();
}
 

fixxxer

К.О.
Партнер клуба
Да нет же, какой implements UserRepository?

PHP:
class User
{
    private $country;
    public getCountry(): Country
    {
        return $this->country;
    }
}
User $user = $userRepository->find(1);
Country $country = $user->getCountry();
$label = $country->getLabel(); // lazy load
А то, что $country это в каком-то случае на самом деле CountryProxy, меня абсолютно не волнует.
 

AnrDaemon

Продвинутый новичок
Опередили. Но в принципе, сама идея реализации в одном классе двух функционалов… попахивает.
Внутренний sanity check должен уже срабатывать на такое.
 

fixxxer

К.О.
Партнер клуба
Это компромисс, как и любой performance hack.

В PHP хоть так можно сделать. Вот, скажем, в JS вообще никак не получится lazy load сделать, там promise никак не спрячешь.
 

WMix

герр M:)ller
Партнер клуба
@fixxxer,

Так это классический AR! Напиши сразу как ты new User запилишь

В DM нормально написать $mapper->create(new User(“foo”))
 

fixxxer

К.О.
Партнер клуба
Где ты у меня AR увидел? Если тебя смутило отсутствие конструктора в User - он там подразумевается, каэш.

В моем примере ровно как во второй Доктрине (с поправкой на псевдокод).

Заметь, CountryProxy будет только в том случае, если я сконфигуировал lazy load маппинг. Если я этого не делал - там будет обычный Country.
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
Это компромисс, как и любой performance hack.

В PHP хоть так можно сделать. Вот, скажем, в JS вообще никак не получится lazy load сделать, там promise никак не спрячешь.
Возможно, я неточно выразился… попробую объяснить.
Если getCountry() - это метод User, то всё окей, и какой там LazyLoad - никого не покачивает.
Если getCountry - это метод UserRepository, который торчит наружу из UserProxy, вот это уже фигня, ибо
1. Те, кто знает о User, ничего не знают о UserRepository.
2. Те, кто всё таки знают, о UserRepository… а с какого, простите, хрена они о нем знают?
 

WMix

герр M:)ller
Партнер клуба
@fixxxer, дело в том что Country содержит метод getUsers() который на момент после setCountry должно содержать страну с коллекцией содержащей хотябы одного пользователя, помимо этого у пользователя кроме страны есть роли, трансакции, ... получается громоздкая система, которую сложновато построить, если только это не AR вездесущий.
@AnrDaemon, я всегда думал, что в сервисе пишут такие строки
PHP:
function rename( $id, $name ){
  $user = $this->repo->get($id);
  $user->rename($name);
  $this->repo->update($user);
}
 

fixxxer

К.О.
Партнер клуба
дело в том что Country содержит метод getUsers()
Это еще зачем?

В моем примере User - это aggregate root.

Возможно, в каком-то другом bounded context-е Country будет aggregate root-ом, но это уже другой Country в другом неймспейсе, да и то чисто теоретически - на практике не вижу никакого смысла в таком агрегате, там, скорее всего, будет достаточно read model, которая заполняется из запроса с джойнами.
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
дело в том что Country содержит метод getUsers() который на момент после setCountry должно содержать страну с коллекцией содержащей хотябы одного пользователя, помимо этого у пользователя кроме страны есть роли, трансакции, ... получается громоздкая система, которую сложновато построить, если только это не AR вездесущий.
Это какой-то северный пушной лис…
 

WMix

герр M:)ller
Партнер клуба
Это еще зачем?.
Но они же это предлагают

и да со страной у пользователя просто, она одна, а если пользователь это aggregate то и без прокси обойтись можно,

в обратную сторону от страны к пользователям интереснее
 
Последнее редактирование:

fixxxer

К.О.
Партнер клуба
1) да я уже не про них, у них не ORM, у них своего рода объектный DBAL с кодогенерацией
2) я ж не говорю, что нельзя, в любом DM можно, мне непонятно, зачем это может понадобиться с нормальными моделями, тем более в обе стороны сразу
 
Сверху