SOLID - 单一责任原则是否适用于班级中的方法?

时间:2015-06-16 07:58:48

标签: php oop solid-principles single-responsibility-principle

我不确定我班级内的这种方法是否违反了单一责任原则,

public function save(Note $note)
{
    if (!_id($note->getid())) {

        $note->setid(idGenerate('note'));

        $q = $this->db->insert($this->table)
                      ->field('id', $note->getid(), 'id');

    } else {
        $q = $this->db->update($this->table)
                      ->where('AND', 'id', '=', $note->getid(), 'id');
    }

    $q->field('title', $note->getTitle())
      ->field('content', $note->getContent());

    $this->db->execute($q);

    return $note;
}

基本上,它在方法中执行两个作业 - 插入或更新。

我应该分成两种方法而不是遵守单一责任原则吗?

但SRP只适用于,不是吗?它是否适用于类中的方法?

SRP -

  

一个班级应该只有一个责任(即只有一个   软件规范的潜在变化应该能够   影响类的规范)

修改

列出笔记(包括许多不同类型的列表),搜索笔记等的另一种方法......

public function getBy(array $params = array())
{
    $q = $this->db->select($this->table . ' n')
                  ->field('title')
                  ->field('content')
                  ->field('creator', 'creator', 'id')
                  ->field('created_on')
                  ->field('updated_on');

    if (isset($params['id'])) {
        if (!is_array($params['id'])) {
            $params['id'] = array($params['id']);
        }

        $q->where('AND', 'id', 'IN', $params['id'], 'id');
    }

    if (isset($params['user_id'])) {
        if (!is_array($params['user_id'])) {
            $params['user_id'] = array($params['user_id']);
        }

        # Handling of type of list: created / received
        if (isset($params['type']) && $params['type'] == 'received') {
            $q
                ->join(
                    'inner',
                    $this->table_share_link . ' s',
                    's.target_id = n.id AND s.target_type = \'note\''
                )
                ->join(
                    'inner',
                    $this->table_share_link_permission . ' p',
                    'p.share_id = s.share_id'
                )
                # Is it useful to know the permission assigned?
                ->field('p.permission')
                # We don't want get back own created note
                ->where('AND', 'n.creator', 'NOT IN', $params['user_id'], 'uuid');
            ;

            $identity_id = $params['user_id'];

            # Handling of group sharing
            if (isset($params['user_group_id']) /*&& count($params['user_group_id'])*/) {
                if (!is_array($params['user_group_id'])) {
                    $params['user_group_id'] = array($params['user_group_uuid']);
                }

                $identity_id = array_merge($identity_id, $params['user_group_id']);
            }

             $q->where('AND', 'p.identity_id', 'IN', $identity_id, 'id');

        } else {
            $q->where('AND', 'n.creator', 'IN', $params['user_id'], 'id');
        }
    }

    # If string search by title
    if (isset($params['find']) && $params['find']) {
        $q->where('AND', 'n.title', 'LIKE', '%' . $params['find'] . '%');
    }

    # Handling of sorting
    if (isset($params['order'])) {
        if ($params['order'] == 'title') {
            $orderStr = 'n.title';

        } else {
            $orderStr = 'n.updated_on';
        }

        if ($params['order'] == 'title') {
            $orderStr = 'n.title';

        } else {
            $orderStr = 'n.updated_on';
        }

        $q->orderBy($orderStr);

    } else {
        // Default sorting
        $q->orderBy('n.updated_on DESC');
    }

    if (isset($params['limit'])) {
        $q->limit($params['limit'], isset($params['offset']) ? $params['offset'] : 0);
    }

    $res = $this->db->execute($q);

    $notes = array();

    while ($row = $res->fetchRow()) {
        $notes[$row->uuid] = $this->fromRow($row);
    }

    return $notes;
}

2 个答案:

答案 0 :(得分:12)

方法将注释持久存储到数据库。如果这是它应该做的事情,那么这是一个单一的责任,并且实施是好的。您需要确定是否插入或更新某处的逻辑,这似乎与任何地方一样好。

只有当你需要在没有隐式决策逻辑的情况下明确地进行插入或更新时,才有必要将这两者分成不同的方法,这些方法可以单独调用。但目前,将它们保持在相同的方法中会简化代码(因为后半部分是共享的),因此这可能是最佳实现。

Exemptigratia:

public function save(Note $note) {
    if (..) {
        $this->insert($note);
    } else {
        $this->update($note);
    }
}

public function insert(Note $note) {
    ..
}

public function update(Note $note) {
    ..
}

如果您因某种原因有时需要明确调用insertupdate,那么上述内容就有意义了。虽然SRP并不是这种分离的真正原因。

答案 1 :(得分:1)

SOLID原则适用于类级术语,它们没有明确说明方法。 SRP本身指出,类应该有一个改变的理由,所以只要你可以替换一个包含在一个类中的责任,你就可以了。

考虑一下:

$userMapper = new Mapper\MySQL();
// or
$userMapper = new Mapper\Mongo();
// or
$userMapper = new Mapper\ArangoDb();

$userService = new UserService($userMapper);

所有这些映射器实现一个接口并承担一项责任 - 它们为用户提供抽象存储访问。因此,mappers有一个改变的理由,因为你可以轻松地交换它们。

您的情况与SRP无关。它更多的是关于最佳实践。好吧,关于方法的最佳实践表明,只要有可能,他们应该只做一件事,尽可能少地接受。这使得更容易阅读和发现错误。

还有一个原则称为Principle of Least Astonishment。它只是声明方法名称应该明确地执行其名称所暗示的内容。

归结为您的代码示例:

save()意味着所有关于数据保存(更新现有记录),而不是创建。通过在那里插入和更新,你打破了PoLA。

就是这样,当你明确地调用insert()时,你知道并期望它会添加一条新记录。关于update()方法的相同方法 - 您知道并期望它会更新方法,但不会创建新方法。

因此我不会在save()中做这两件事。如果我想更新记录,我会打电话给update()。如果我想创建一个记录,我会打电话给insert()