Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Design do participante Shopping\Order #1

Open
netojoaobatista opened this issue Aug 8, 2014 · 9 comments
Open

Design do participante Shopping\Order #1

netojoaobatista opened this issue Aug 8, 2014 · 9 comments

Comments

@netojoaobatista
Copy link
Member

Durante a navegação, o usuário adiciona diversos Shopping\Product ao Shopping\Cart, com suas respectivas quantidades. Ao concluir a escolha e adição dos produtos, existe a opção por finalizar a compra, transformando um Shopping\Cart em um Shopping\Order.

Enquanto um Shopping\Cart é apenas um agregador de Shopping\Product, um Shopping\Order envolve alguns comportamentos adicionais, como total da compra, descontos, taxas, etc. O design de um Shopping\Order deve ser de tal forma que esse participante possa reaproveitar as implementações para iteração dos itens do carrinho, adicionando os comportamentos específicos relacionados com o pedido e sua finalização.

Como deve ser, então, o design de um Shopping\Order?

  • Ele deve derivar Shopping\Cart?
  • Ele deve implementar alguma interface específica?

Como implementar as possíveis opções de pagamento, entrega de mercadoria, descontos, etc, e como esses participantes devem interagir com o Shopping\Order?

@danizord
Copy link
Member

danizord commented Aug 8, 2014

Podemos extrair as implementações de iteração do carrinho para uma ProductCollection? Assim será possível reaproveitar essa implementação sem que o Shopping\Order dependa de uma instância de Shopping\Cart. Afinal, quando uma Shopping\Order é criada, o Shopping\Cart deveria deixar de existir, correto?

@netojoaobatista
Copy link
Member Author

Semanticamente falando, @danizord, um Shopping\Order sempre vai depender de um Shopping\Cart. Afinal, o que é um pedido, senão a finalização de um carrinho?

Veja, não estou dizendo que um ProductCollection não é adequado. Só estou dizendo que a dependência entre Shopping\Order e Shopping\Cart existe por definição.

@danizord
Copy link
Member

danizord commented Aug 8, 2014

@netojoaobatista, ah sim, me expressei mal, minha intenção não é remover a dependência em sí, mas a composição.

O Shopping\Cart é mutável, por isso eu acho que ele deveria ser descartado no momento da criação da Shopping\Order. Depois que a compra foi finalizada, não podemos mais adicionar/remover produtos da compra.

@netojoaobatista
Copy link
Member Author

Okay,

Agora, é mesmo necessário um ProductCollection? Não seria mais simples, seShopping\Order apenas encapsular Shopping\Cart?

@danizord
Copy link
Member

danizord commented Aug 8, 2014

@netojoaobatista A função da ProductCollection seria desacoplar a Shopping\Order do Shopping\Cart, de forma que qualquer alteração no estado do Shopping\Cart não seja refletida no estado do Shopping\Order.

$cart = new Cart();
$cart->addItem(new Product(), 1);
$cart->addItem(new Product(), 1);

$order = new Order($cart);
$price = $order->getPrice();

$cart->addItem(new Product(), 1);

$this->assertEquals($price, $order->getPrice());

@netojoaobatista
Copy link
Member Author

A pergunta permanece, @danizord. É mesmo necessário um ProductCollection?

Uma vez que trabalhamos com referências para as instâncias, modificações em Shopping\Cart afetarão a ProductCollection que, por sua vez, afetará Shopping\Order.

Vejo duas formas de se evitar esse problema:

  1. Prototype - Se criarmos uma instância controlada, copiando o protótipo de Shopping\Cart, conseguimos evitar que mudanças no carrinho, ou em um ProductCollection, afetem o Shopping\Order.
  2. Observer - Se Shopping\Order observar Shopping\Cart por mudanças, podemos disparar um \DomainException, caso exista a tentativa de se modificar o estado do carrinho após criação de Shopping\Order.

@danizord
Copy link
Member

@netojoaobatista Shopping\Cart e Shopping\Order não compartilhariam a mesma instância de ProductCollection, cada um teria a sua própria coleção de produtos encapsulada. Porém, nós precisamos da mesma implementação de iterator nos dois lugares, daí a necessidade de uma ProductCollection.

@gabrielsch
Copy link

class Order
{
    private $products;

    public function __construct(Cart $cart)
    {
        $this->products = clone $cart->getProducts();
    }
}

é isso, @danizord?

@danizord
Copy link
Member

@gabrielsch sim sim, essa é uma das formas que o @netojoaobatista propôs para resolver o problema, que na minha opinião é a melhor forma, com prototype.

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

No branches or pull requests

3 participants