Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Simplificando o participante Shopping\Cart #4

Open
lcobucci opened this issue Aug 12, 2014 · 5 comments
Open

Simplificando o participante Shopping\Cart #4

lcobucci opened this issue Aug 12, 2014 · 5 comments

Comments

@lcobucci
Copy link
Member

O participante Shopping\Cart está gerenciando tanto os produtos quanto as quantidades dos produtos, acredito que isso poderia ser simplificado com a adição de um outro participante, o Shopping\CartItem:

namespace PHPBr\Shopping;

class CartItem
{
    /**
     * @var \PHPBr\Shopping\Product
     */
    private $product;

    /**
     * @var int
     */
    private $quantity;

    /**
     * @param \PHPBr\Shopping\Product $product
     */
    public function __construct(Product $product)
    {
        $this->product = $product;
        $this->quantity = 0;
    }

    /**
     * @return \PHPBr\Shopping\Product
     */
    public function getProduct()
    {
        return $this->product;
    }

    /**
     * @return int
     */
    public function getQuantity()
    {
        return $this->quantity;
    }

    /**
     * @return boolean
     */
    public function isEmpty() // dá pra pensar em um nome melhor pra isso...
    {
        return $this->quantity <= 0;
    }

    /**
     * @param int $quantity
     */
    public function append($quantity)
    {
        $this->quantity += $quantity * 1;
    }

    /**
     * @param int $quantity
     */
    public function remove($quantity)
    {
        $this->quantity -= $quantity * 1;
    }
}

O uso dele seria apenas pelo Shopping\Cart, desta forma (apenas com os métodos referentes à esta proposta):

namespace PHPBr\Shopping;

class Cart implements \Countable, \IteratorAggregate, \Serializable
{
    /**
     * @var \PHPBr\Shopping\CartItem[]
     */
    private $items = [];

    /**
     * @param \PHPBr\Shopping\Product $product
     * @param int $quantity
     */
    public function addItem(Product $product, $quantity)
    {
        $id = $product->getId();

        if (!isset($this->items[$id])) {
            $this->items[$id] = new CartItem($product);
        }

        $this->items[$id]->append($quantity);
    }

    /**
     * @return int
     * @see \Countable::count()
     */
    public function count()
    {
        return count($this->items);
    }

    /**
     * @return \Iterator<\PHPBr\Shopping\Product>
     * @see \IteratorAggregate::getIterator()
     */
    public function getIterator()
    {
        foreach ($this->items as $item) {
            yield $item->getQuantity() => $item->getProduct();
        }
    }

    /**
     * @param \PHPBr\Shopping\Product $product
     * @param int $quantity
     */
    public function removeItem(Product $product, $quantity = 0)
    {
        $id = $product->getId();

        if (!isset($this->items[$id])) {
            throw new \DomainException('Can\'t remove. Product not found.');
            return;
        }

        if ($quantity > 0) {
            $this->items[$id]->remove($quantity);
        }

        if ($this->items[$id]->isEmpty() || $quantity <= 0) {
            unset($this->items[$id]);
        }
    }

    /**
     * @return string
     * @see \Serializable::serialize()
     */
    public function serialize() { /* ... */ }

    /**
     * @see \Serializable::unserialize()
     */
    public function unserialize($serialized) { /* ... */ }
}
@drgomesp
Copy link

👍

2 similar comments
@KennedyTedesco
Copy link
Member

👍

@danizord
Copy link
Member

👍

@netojoaobatista
Copy link
Member

Gosto disso. O participante Shopping\CartItem realmente é bacana e diminui a responsabilidade do Shopping\Cart, transformando-o em um Aggregate de fato.

O único problema que vejo, é o Shopping\Cart referenciar diretamente o Shopping\CartItem. Mesmo que esse novo participante, teoricamente, seja utilizado apenas por Shopping\Cart, não acho bacana a criação da instância de forma "dura" assim. Talvez um FactoryMethod para criação dessa instância seja mais adequado, pois permite a variação da implementação de Shopping\CartItem.

@lcobucci
Copy link
Member Author

Concordo plenamente @netojoaobatista!
E ae, quem se arrisca a implementar?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants