Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion De thin controllers y detached entities
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Francesc Rosàs  
View profile   Translate to Translated (View Original)
 More options Apr 26 2012, 3:07 pm
From: Francesc Rosàs <francescrosasbos...@gmail.com>
Date: Thu, 26 Apr 2012 21:07:44 +0200
Local: Thurs, Apr 26 2012 3:07 pm
Subject: Re: De thin controllers y detached entities

El 26 d’abril de 2012 20:41, theUniC <theu...@gmail.com> ha escrit:

> Un repository te sirve para consultar datos de tu fuente de datos, no para
> persistirlos. Entiendo que no se refiere a "meter" (por persistir) de forma
> explícita, sino que el propio repository lo hace de manera transparente
> cuándo se ejecuta una consulta contra ese repository para solicitar datos.

> Para no "cargar de responsabilidad" a los repositories, habría que
> desacoplar la persistencia de los propios repositories y añadir una capa
> más que cumpla con esa responsabilidad.

Creo que el Sr. Fowler y yo seguimos discrepando ;)

A no ser que estemos hablando de lo mismo con palabras diferentes. Así lo
veo yo:

Controllers -> Servicios -> Repositorios -> Data mapper (e.g. un ORM) ->
Data store

> Por otro lado, el input hay que validarlo siempre y venga de dónde venga.
> Aquí pasa un poco cómo en la cuestión de los repositories. Y es que el
> patrón ActiveRecord, al menos la mayor parte de implementaciones que he
> visto, suelen acoplar bastante la validación del input con la propia
> persistencia. Y eso es un mal vicio. La responsabilidad de que el
> input sea válido no debería recaer en la capa de persistencia.

> El componente Validate, a través del service "validate", se encarga de
> validar las entidades (que pueden estar vinculadas a un formulario o no)
> según las reglas definidas. El componente Form ya de por si, y
> transparentemente, usa este servicio para validar la entidad que tenga
> asociada.

> *http://symfony.com/doc/current/book/validation.html*

Es por eso que me extraña que la validación no sea una parte intrínseca de
las entidades. Algo como:

$user->setEmail('foo'); // Exception al canto!

En cambio estás "obligado" a validar ese $user cada vez que lo recibes como
argumento de un método. Entiendo que haciéndolo así simplifica bastante la
lógica de setear las propiedades de una entidad desde un formulario pero
complica el resto de capas.

> Un saludo!
> Christian.

> El 26 de abril de 2012 19:47, Francesc Rosàs <
> francescrosasbos...@gmail.com> escribió:

> No estoy seguro de a qué te refieres por "extracción de entidades del
>> domain model". Si te refieres a sólo obtener esas entidades del data
>> store, según el propio artículo que comentas un repositorio sirve tanto
>> para "meter" como para "sacar":

>> Conceptually, a Repository encapsulates the set of objects persisted in a
>>> data store and the operations performed over them, providing a more
>>> object-oriented view of the persistence layer.

>> Y para dejarlo más claro:

>> Objects can be added to and removed from the Repository, as they can from
>>> a simple collection of objects, and the mapping code encapsulated by the
>>> Repository will carry out the appropriate operations behind the scenes.

>> Vamos, como tener un array de entidades persistido y adaptado a tus
>> necesidades :)

>> El 26 d’abril de 2012 19:33, theUniC <theu...@gmail.com> ha escrit:

>>> Hola,

>>> La verdad es que la persistencia tampoco debería ir ligada a la capa de
>>> repositorios, pues los repositorios solo deberían responsabilizarse de la
>>> extracción de entidades del domain model -- *
>>> http://martinfowler.com/eaaCatalog/repository.html*

>>> En todo caso, tal cómo comenta Ronny, deberían tener su propia capa!

>>> Un saludo!
>>> Christian.

>>> El 26 de abril de 2012 19:01, Francesc Rosàs <
>>> francescrosasbos...@gmail.com> escribió:

>>> Ronny, sí de momento estoy liado quitando la lógica del negocio de los
>>>> controladores. El siguiente paso seguramente sería el que comentas, extraer
>>>> la persistencia en forma de repositorios (más que nada para facilitar el
>>>> testeo de estos servicios).

>>>> Y gracias por los ejemplos, la verdad es que cuesta encontrar los que
>>>> pasan del simple "controlador manipula entidades".

>>>> El 24 d’abril de 2012 18:13, Ronny López <ro...@pricebets.com> ha
>>>> escrit:

>>>> Hola,

>>>>> En teoría la interfaz que exponga la capa de servicio debe estar
>>>>> desligada totalmente de la persistencia.

>>>>> En el caso que planteas, a los clientes del TweetService no les
>>>>> concierne como este servicio gestione la persistencia de los objetos que
>>>>> maneja internamente.

>>>>> Piensa por ejemplo, que hoy se pueden estar persistiendo los tweets en
>>>>> MySQL, a través de Doctrine ORM, pero que mañana puedes decidir cambiar a
>>>>> MongoDB a través de Doctrine ODM, o a Redis a través de un cliente de Redis
>>>>> propio.

>>>>> Entonces, si el servicio maneja la persistencia de forma interna,
>>>>> ninguno de sus clientes se verá afectado ante un cambio de este tipo.

>>>>> Unos buenos ejemplos a seguir en este tipo de diseño de "modelo de
>>>>> datos abstracto", son el FOSUserBundle y el FOSCommentBundle.

>>>>> Aquí se interactua con los objetos del modelo a través de un
>>>>> "Manager", el CommentManager por ejemplo. El CommentManager tiene una
>>>>> interfaz bien defina, la cual es totalmente independiente de la
>>>>> persistencia:
>>>>> https://github.com/FriendsOfSymfony/FOSCommentBundle/blob/master/Mode...

>>>>> Entonces, existe una implementación abstracta
>>>>> https://github.com/FriendsOfSymfony/FOSCommentBundle/blob/master/Mode... implementaciones especializadas en diferentes tipos de persistencia, por
>>>>> ejemplo, una basada en Doctrine:
>>>>> https://github.com/FriendsOfSymfony/FOSCommentBundle/blob/master/Enti...

>>>>> Es cierto que este tipo de diseño require más trabajo de diseño y
>>>>> programación, pero la robustez y desacoplamiento que aporta a una
>>>>> aplicación medianamente compleja es importante.

>>>>> Saludos,
>>>>> Ronny.

>>>>> El martes, 24 de abril de 2012 14:51:25 UTC+2, Francesc Rosàs escribió:

>>>>>> Hola symfoneros, estoy trabajando en un proyecto en Symfony2 +
>>>>>> Doctrine2 y los controllers se me están engordando ya demasiado con tareas
>>>>>> que entiendo que pertenecen al modelo.

>>>>>> Había pensado que para aligerarlos podría empezar con extraer todo el
>>>>>> código que pertenece al modelo en forma de servicios. Así si por ejemplo
>>>>>> tengo un action del controller que (pongamos que estamos en Twitter) crea
>>>>>> un tuit a partir de un formulario y notifica a todos los seguidores, la
>>>>>> idea sería crear un servicio (e.g. twitter.tweets) con un método
>>>>>> publish($tweet). El controller seguiría instanciando y trabajando con un
>>>>>> objeto Tweet pero no tendría ningún $em->flush() ni nada por el estilo.

>>>>>> Las ventajas vendrían a ser estas:

>>>>>>    - El controller hace sólo de pasarela entre el usuario y el modelo
>>>>>>    - El modelo se puede reutilizar en otros contextos (en procesos
>>>>>>    batch, por ejemplo)
>>>>>>    - Puedo cambiar la implementación del modelo sin afectar a los
>>>>>>    controllers (e.g. pasar de usar una base de datos a un web service)

>>>>>> Uno de los aspectos que me genera más dudas es la forma de encapsular
>>>>>> correctamente los cambios sobre las entities. Doctrine por defecto recuerda
>>>>>> los cambios que se hacen en las entidades y ahí pierdo la encapsulación que
>>>>>> me da el servicio ya que al hacer un $em->flush() se aplicarían todos los
>>>>>> cambios que se hayan podido hacer en cualquier entidad y sin mucho control
>>>>>> sobre qué quiero aplicar y qué no en la base de datos.

>>>>>> Para evitar esto había pensado en algo así:

>>>>>> class TweetsService
>>>>>> {
>>>>>>     function publish(Tweet $tweet)
>>>>>>     {
>>>>>>         $this->getEntityManager()->**clear();
>>>>>>         $this->getEntityManager()->**merge($tweet);
>>>>>>         $this->getEntityManager()->**flush();

>>>>>>         $this->notifyFollowers($tweet)**;
>>>>>>     }
>>>>>> }

>>>>>>  Básicamente olvida todos los cambios hechos en las entidades (el
>>>>>> clear() hace un detach() de todas ellas) y aplica sólo los que nos
>>>>>> interesan.

>>>>>> Cómo veis esta aproximación? Me estoy liando sólo? Va a afectar mucho
>>>>>> en el rendimiento? Con las pruebas que he hecho hasta ahora la cosa
>>>>>> funciona pero no me gustaría encontrarme con problemas más adelante.

>>>>>> Un saludo.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.