dongtuwu8548 2015-04-03 11:18
浏览 28
已采纳

域对象管理器?

I’m currently exploring a framework and therein I am coding a Service. the Service itself has a growing number of methods (which is not that bad, because it’s, well, a Service). the uneasiness comes from the mapper that the Service uses to translate DB data into Domain objects, because that class is growing into where I feel uncomfortable (each Service method requires at least 2 Mapper methods and a property (one for fetching data, one for mapping them and the property for SQL).

So my question would be if it is recommended to make a mapper class for each Service method (e.g. by using a Factory)?

so, this is the class in question:

<?php

import('sites::foo::biz', 'Held');
import('sites::foo::biz', 'Attribut');
import('sites::foo::biz', 'Generierung');
import('sites::foo::biz', 'Talent');
import('sites::foo::biz', 'Kampftalent');

class HeldenblattMapper extends APFObject
{
    const SQL_GET_HELD = <<<SQL
    SELECT
        name,
        geschlecht,
        groesse,
        gewicht,
        tsatag,
        haare,
        augen,
        aussehen,
        stand,
        titel,
        SO,
        hintergrund,
        AP_frei   AS freieAP,
        AP_gesamt AS alleAP
    FROM
        helden
    WHERE
        id = ?
    ;
SQL;
    const SQL_GET_ATTR = <<<SQL
    SELECT
        Attribut,
        Wert
    FROM
        held_attribute
    WHERE
        HeldenID = ?
    ;
SQL;

    const SQL_GET_TALENTE = <<<SQL
    SELECT
        Talent,
        Probe,
        Attribute,
        Wert,
        Kategorie
    FROM
        held_talente
    WHERE
        HeldenID = ? AND Kategorie = ?
    ORDER BY
        Kategorie, Talent
    ;
SQL;

    const SQL_GET_RKP = <<<SQL
    SELECT
        RKP,
        Typ
    FROM
        held_rkp
    WHERE
        HeldenID = ? AND pri_sec = ?
    ;
SQL;

    const SQL_GET_KAMPF = <<<SQL
    SELECT
        Talent,
        Spezialisierung,
        AT_PA,
        Wert,
        Kategorie,
        Attacke(HeldenID)   AS AT,
        Parade(HeldenID)    AS PA,
        Fernkampf(HeldenID) AS FK
    FROM
        held_kampftalente
    WHERE
        HeldenID = ? AND Kategorie = ?
    ORDER BY
        Kategorie DESC, Talent ASC
    ;
SQL;

    public function getHeld($id)
    {
        $PDOHeld = $this->getPDOById(self::SQL_GET_HELD, $id);
        return $this->mapPDOHeld2DomainObject($PDOHeld);
    }

    public function getAttributeByHeld($id)
    {
        $PDOAttr = $this->getPDOById(self::SQL_GET_ATTR, $id);
        return $this->mapPDOAttribute2DomainObjects($PDOAttr);
    }

    public function getRKPByHeld($id)
    {
        $sql = 'SELECT RKP FROM held_rkp WHERE HeldenID = ? AND Typ = ? ORDER BY pri_sec ASC;';
        $rkp = $this->getPDOConnection()->prepareStatement($sql);
        $rkp->bindParam(1, $id,  PDO::PARAM_INT);
        $rkp->bindParam(2, $typ, PDO::PARAM_STR);

        $arr   = array();
        $types = array('Rasse', 'Kultur', 'Profession');
        foreach ($types as $typ)
        {
            $rkp->execute();
            $arr[$typ] = $this->mapPDORKP2DomainObject($rkp);
        }
        return $arr;
    }

    public function getTalenteByHeld($id)
    {
        $sql = 'SELECT DISTINCT Kategorie FROM held_talente WHERE HeldenID = ?';
        $PDOKat = $this->getPDOById($sql, $id);
        $PDOKat->setFetchMode(PDO::FETCH_COLUMN, 0);

        $PDOTal = $this->getPDOConnection()->prepareStatement(self::SQL_GET_TALENTE);
        $PDOTal->bindParam(1, $id,  PDO::PARAM_INT);
        $PDOTal->bindParam(2, $kat, PDO::PARAM_STR);

        $arr = array();
        foreach ($PDOKat as $kat)
        {
            $PDOTal->execute();
            $arr[$kat] = $this->mapPDOTalente2DomainObjects($PDOTal);
        }
        return $arr;
    }

    public function getKampftalenteByHeld($id)
    {
        $sql = 'SELECT DISTINCT Kategorie FROM held_kampftalente WHERE HeldenID = ?';
        $PDOKat = $this->getPDOById($sql, $id);
        $PDOKat->setFetchMode(PDO::FETCH_COLUMN, 0);

        $PDOTal = $this->getPDOConnection()->prepareStatement(self::SQL_GET_KAMPF);
        $PDOTal->bindParam(1, $id,  PDO::PARAM_INT);
        $PDOTal->bindParam(2, $kat, PDO::PARAM_STR);

        $arr = array();
        foreach ($PDOKat as $kat)
        {
            $PDOTal->execute();
            $arr[$kat] = $this->mapPDOKampf2DomainObjects($PDOTal);
        }
        return $arr;
    }

    private function mapPDOHeld2DomainObject(PDOStatement $ps)
    {
        $row = $ps->fetch(PDO::FETCH_ASSOC);
        if (!$row)
        {
            throw new DomainException('No Character data found.');
        }
        $held = new Held();
        $held->setName($row['name']);
        $held->setGeschlecht($row['geschlecht']);
        $held->setAlleAP($row['alleAP']);
        $held->setFreieAP($row['freieAP']);

        return $held;
    }

    private function mapPDOAttribute2DomainObjects(PDOStatement $ps)
    {
        $ps->setFetchMode(PDO::FETCH_ASSOC);
        $arr = array();
        foreach ($ps as $row)
        {
            $attribut = new Attribut();
            $attribut->setName($row['Attribut']);
            $attribut->setWert($row['Wert']);
            $arr[] = $attribut;
        }
        return $arr;
    }

    private function mapPDORKP2DomainObject(PDOStatement $ps)
    {
        $rkp = new Generierung();
        $rkp->setRKPName($ps->fetchColumn());
        $mod = $ps->fetchColumn();
        if ($mod)
        {
            $rkp->setModifikation($mod);
        }
        return $rkp;
    }

    private function mapPDOTalente2DomainObjects(PDOStatement $ps)
    {
        $ps->setFetchMode(PDO::FETCH_ASSOC);
        $arr = array();
        foreach ($ps as $row)
        {
            $talent = new Talent();
            $talent->setName($row['Talent']);
            $talent->setWert($row['Wert']);
            $talent->setAttribute($row['Attribute']);
            $talent->setProbe($row['Probe']);
            $talent->setTyp($row['Kategorie']);
            $arr[] = $talent;
        }
        return $arr;
    }

    private function mapPDOKampf2DomainObjects(PDOStatement $ps)
    {
        $ps->setFetchMode(PDO::FETCH_ASSOC);
        $arr = array();
        foreach ($ps as $row)
        {
            $talent = new Kampftalent();
            $talent->setName($row['Talent']);
            $talent->setWert($row['Wert']);
            $talent->setSpezialisierung($row['Spezialisierung']);
            $talent->setAtPaFromDBValue($row['AT_PA'], '_');

            if ('Nahkampf' == $row['Kategorie'])
            {
                $at = (int) $row['AT'] + $talent->getAT();
                $talent->setAT($at);
                $pa = (int) $row['PA'] + $talent->getPA();
                $talent->setPA($pa);

            }
            elseif ('Fernkampf' == $row['Kategorie'])
            {
                $fk = (int) $row['FK'] + $talent->getAT();
                $talent->setAT($fk);
            }
            $arr[] = $talent;
        }
        return $arr;
    }

    private function getPDOConnection()
    {
        $cm = $this->getServiceObject('core::database', 'ConnectionManager');
        return $cm->getConnection('PDO');
    }

    private function getPDOById($sql, $id)
    {
        $ps = $this->getPDOConnection()->prepareStatement($sql);
        $ps->bindValue(1, (int) $id, PDO::PARAM_INT);
        $ps->execute();
        return $ps;
    }

}

releated services

<?php

class HeldenblattService extends APFObject
{
    private $id;

    public function init($param)
    {
        if (!is_int($param))
        {
            throw new InvalidArgumentException('Cannot create a Character Sheet without a valid Character ID.');
        }
        $this->id = $param;
    }

    public function getHeld()
    {
        $mapper = $this->getMapper();
        return $mapper->getHeld($this->id);
    }

    public function heldGetRKP()
    {
        $mapper = $this->getMapper();
        return $mapper->getRKPByHeld($this->id);
    }

    public function heldGetAttribute()
    {
        $mapper = $this->getMapper();
        return $mapper->getAttributeByHeld($this->id);
    }

    public function heldGetTalente()
    {
        $mapper = $this->getMapper();
        return $mapper->getTalenteByHeld($this->id);
    }

    public function heldGetKampf()
    {
        $mapper = $this->getMapper();
        return $mapper->getKampftalenteByHeld($this->id);
    }

    private function getMapper()
    {
        return $this->getDIServiceObject(
            'sites::foo::data', 
            'HeldenblattMapper'
        );
    }
}

it might look like they do the same, but one is a business class and the other a model class (separation of concerns).

  • 写回答

1条回答 默认 最新

  • dpsu84620 2015-04-03 11:59
    关注

    I’d rather prefer a single Service with a number of Mappers, as the implementation of Domain-DB mapping is taking more code that just the load/save calls of the Service.

    if the Service is growing (not much more at this point), I could think about making a service-mapper pair for each section/topic. otherwise the mapper class will easily extend 500 lines.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 使用C#,asp.net读取Excel文件并保存到Oracle数据库
  • ¥15 C# datagridview 单元格显示进度及值
  • ¥15 thinkphp6配合social login单点登录问题
  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配