Pregunta

Actualizado: 09/02/2009 - revisión de que se trate, siempre mejor de los ejemplos, agregó recompensa.


Hola,
Estoy construyendo una aplicación en PHP utilizando los datos de asignador de patrón entre la base de datos y las entidades (objetos de dominio).Mi pregunta es:

¿Cuál es la mejor manera de encapsular un comúnmente tarea que se realiza?

Por ejemplo, una tarea común es la recuperación de una o más entidades del sitio mapper, y sus asociados (casa) página entidades de la página mapper.En la actualidad, yo lo haría así:

$siteMapper = new Site_Mapper();
$site = $siteMapper->findByid(1);

$pageMapper = new Page_Mapper();
$site->addPage($pageMapper->findHome($site->getId()));

Ahora que es bastante un ejemplo trivial, pero se vuelve más complicado en la realidad, ya que cada sitio también tiene asociada una configuración regional, y realmente la página tiene varias revisiones (aunque para los fines de esta tarea yo sólo estaría interesado en la más reciente).

Voy a necesitar para hacerlo (conseguir en el sitio y se asocia página de inicio, configuración regional, etc.) en varios lugares dentro de mi aplicación, y no puedo pensar en la mejor forma/lugar para encapsular esta tarea, por lo que no tengo que repetir todo el lugar.Idealmente me gustaría terminar con algo como esto:

$someObject = new SomeClass();
$site = $someObject->someMethod(1); // or
$sites = $someObject->someOtherMethod();

Donde la resultante sitio entidades ya tienen sus entidades asociadas creado y listo para su uso.

El mismo problema se produce cuando el ahorro de estos objetos.Decir que tengo un sitio entidad asociada y la página de inicio de la entidad, y que ambos han sido modificados, que tengo que hacer algo como esto:

$siteMapper->save($site);
$pageMapper->save($site->getHomePage());

De nuevo, trivial, pero para este ejemplo se ha simplificado.La duplicación de código se aplica todavía.

En mi mente tiene sentido tener algún tipo de objeto central que podría tener cuidado de:

  • La recuperación de un sitio (o sitios) y todos los nessessary entidades asociadas
  • La creación de nuevo sitio entidades con las nuevas entidades asociadas
  • Teniendo un sitio (o sitios) y de ahorro y todas las entidades asociadas (si ha cambiado)

Así que de vuelta a mi pregunta, ¿qué se debe este objeto?

  • El existente mapeador objeto?
  • Algo basado en el modelo de repositorio?*
  • Algo basado en la unidad de trabajo patten?*
  • Algo más?

* No me totalmente comprender cualquiera de estos, como usted probablemente puede adivinar.

Hay una manera estándar de enfoque de este problema, y alguien podría proporcionar una breve descripción de cómo se había implementar?Yo no estoy buscando a alguien para brindar una implementación de trabajo, sólo la teoría.

Gracias,
Jack

¿Fue útil?

Solución

Utilizando el patrón de repositorio / servicio, sus clases Repository proporcionarían una interfaz CRUD simple para cada uno de sus entidades, a continuación, las clases de servicio sería una capa adicional que realiza la lógica adicional como unir dependencias entidad. El resto de su aplicación entonces sólo utiliza los Servicios. Su ejemplo podría tener este aspecto:

$site = $siteService->getSiteById(1); // or
$sites = $siteService->getAllSites();

A continuación, dentro de la clase SiteService que tendría algo como esto:

function getSiteById($id) {
  $site = $siteRepository->getSiteById($id);
  foreach ($pageRepository->getPagesBySiteId($site->id) as $page)
  {
    $site->pages[] = $page;
  }
  return $site;
}

No sé PHP que también así que disculpen si hay algo incorrecto sintácticamente.

Otros consejos

[Editar: esta entrada intenta abordar el hecho de que muchas veces es más fácil escribir código personalizado para tratar directamente con una situación de lo que es tratar de encajar el problema en un patrón.]

Los patrones son agradables en su concepto, pero no siempre "mapa". Después de años de desarrollo de PHP de gama alta, que se han asentado en una forma muy directa de manejar estos asuntos. Considere lo siguiente:

Archivo: Site.php

class Site
{
   public static function Select($ID)
   {
      //Ensure current user has access to ID
      //Lookup and return data
   }

   public static function Insert($aData)
   {
      //Validate $aData
      //In the event of errors, raise a ValidationError($ErrorList)

      //Do whatever it is you are doing

      //Return new ID
   }

   public static function Update($ID, $aData)
   {
      //Validate $aData
      //In the event of errors, raise a ValidationError($ErrorList)

      //Update necessary fields
   }

A continuación, con el fin de llamar (desde cualquier lugar), basta con ejecutar:

$aData = Site::Select(123);

Site::Update(123, array('FirstName' => 'New First Name'));

$ID = Site::Insert(array(...))

Una cosa a tener en cuenta acerca de la programación OO y PHP ... PHP no mantiene "estado" entre las solicitudes, por lo que la creación de una instancia de objeto sólo para tenerlo inmediatamente destruido a menudo no tiene sentido.

probablemente me inician al extraer la tarea común a un método de ayuda en algún lugar, a continuación, a la espera de ver lo que el diseño requiere. Se siente como que es demasiado pronto para decir.

¿Qué le nombre de este método? El nombre por lo general apunta a que el método pertenece.

class Page {

  public $id, $title, $url;

  public function __construct($id=false) {
    $this->id = $id;
  }

  public function save() {
    // ...
  }

}

class Site {

  public $id = '';
  public $pages = array();

  function __construct($id) {
     $this->id = $id;
     foreach ($this->getPages() as $page_id) {
       $this->pages[] = new Page($page_id);
     }
  }

  private function getPages() {
    // ...
  }

  public function addPage($url) {
    $page = ($this->pages[] = new Page());
    $page->url = $url;
    return $page;
  }

  public function save() {
    foreach ($this->pages as $page) {
      $page->save();
    } 
    // ..
  }

}

$site = new Site($id);
$page = $site->addPage('/');
$page->title = 'Home';
$site->save();

Haga su sitio un objeto agregado Raíz para encapsular la asociación compleja y garantizar la coherencia .

A continuación, cree una siteRepository que tiene la responsabilidad de recuperar el agregado del sitio y llenar sus hijos (incluyendo todas las páginas).

No se necesita un PageRepository separada (suponiendo que usted no hace una página raíz agregada por separado), y su siteRepository debe tener la responsabilidad de recuperar los objetos página también (en su caso mediante el uso de sus cartógrafos existentes).

Así que:

$siteRepository = new SiteRepository($myDbConfig);
$site = $siteRepository->findById(1); // will have Page children attached

Y a continuación, el método findById sería también responsable de la búsqueda de todos los niños página del sitio. Esto tendrá una estructura similar a la respuesta CodeMonkey1 dio, sin embargo, creo que se beneficiarán más utilizando el agregado y patrones de repositorio, en lugar de la creación de un servicio específico para esta tarea. Cualquier otro de recuperación / consulta / actualización del agregado del sitio, incluyendo cualquiera de sus objetos secundarios, se llevaría a cabo a través de la misma siteRepository.

Editar: He aquí una breve guía DDD para ayudarle con la terminología, aunque yo realmente recomiendo la lectura Evans si desea que la imagen completa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top