php-brasil / Order

Domain driven order service design
19 stars 0 forks source link

Que problemas vamos resolver? #2

Closed augustohp closed 9 years ago

augustohp commented 9 years ago

Quais os casos de uso que resolveremos e como? Acho que podemos usar o Behat pra isso. Com eles, podemos modelar nossos contextos e domínio, pra atingir uma língua ubíqua.

A lingua ubíqua é o nosso mapa de design. O caminho inverso acho que nem pode ser considerado DDD. O Vaughn Vernon faz um eufemismo e chama isso de DDD-lite mas tanto ele quanto Evans deixam claro que usar os building blocks somente não é DDD.

Nosso vocabulário

Estamos discutindo a nossa linguagem onipresente com a ajuda de um domínio que precisa ser atualizado para refletir esse vocabulário.

@yourwebmaker é nosso especialista de domínio e nosso product owner.

Legenda

:construction_worker: Precisa de mais trabalho/informação. Incompleto. :eyes: Em discussão.

yourwebmaker commented 9 years ago

Exatamente, sendo assim, dando continuidade no exemplo que saiu da minha cabeça, vamos pensar na linguagem aqui e depois escrevemos as features. Ok? Vou tentar deixar o exemplo mais complexo.

Na minha concepção, uma venda seria o total de de uma compra. Esta compra sempre é feita por um cliente.

Nosso pequeno sistema não aprova a venda por si, ele conta outros mecanismos para poder dar continuidade do processo (aprovação ou cancelamento da venda).

Um cenário:

O cliente Daniel entra na loja e efetua uma compra com o total Y. Ao finalizar essa compra precisamos saber quão "honesto" é o nosso cliente. Podemos fazer diversas verificações:

Nosso sistema não é responsável em verificar as condições acima. Quem faz isso é um webservice de terceiros. Envio os dados do Cliente + total da compra para este serviço e ele faz uma chamada na minha aplicação aprovando ou não a compra daquele cliente.

Vejam que estou usando o termo compra. @netojoaobatista usou o termo Order (pedido), e no primeiro exemplo usei venda. Alguém que possua conhecimento nesta área para que possa nos ajudar a refinar nosso vocabulário?

Meu conhecimento em comércio e aprovação de compra é nulo.

netojoaobatista commented 9 years ago

@yourwebmaker, termos que tenho deparado com certa frequência:

Nos casos que tenho visto ultimamente, Order e Sale são quase sinônimos. Transaction é a Order ou Sale já concretizada, com a tentativa de pagamento - independentemente de sucesso no pagamento.

yourwebmaker commented 9 years ago

@fabiocarneiro, vamos discutir aqui. Primeiro vamos focar em discutir uma linguagem ubíqua, pada depois escrever as features, depois implementar.

yourwebmaker commented 9 years ago

Bom, dando continuidade, detalhar os casos:

Order/Sale no domínio do cliente é uma compra, para a empresa isso é uma venda. Correto? (precisamos definir este termo corretamente)

Aprovação de venda: Processo que dará continuidade à compra do cliente. Quando aprovada, o pedido pode assim ser encaminhado para entrega. O produto poderá sair da loja.

Cancelamento de venda: Cancela a venda. Não é feito nenhum processo à partir daqui, a não ser notificar o cliente que a sua compra não foi aprovada.

Deal?

augustohp commented 9 years ago

Eu ainda prefiro enxergar os cenários e limitar AINDA mais o escopo. Pelo que eu entendi existem dois contextos bem separados: a análise de risco e a venda.

Feature: Purchase risk analysis
    In order to increase revenue
    As a company that sell goods directly to customers
    We need to access the risk of a purchase and choose whether or not to deliver the good

Rules:

- We do not sell to black listed customers known in the market.
- A real customer does not buy more than twice a day.

Scenario: First successful purchase of a customer
    Given I am customer "john@doe.net"
    And I search for "Domain Driver Design Eric Evans"
    And I find one result
    And I enter the first result of the search
    And I fill "1" on "quantity"
    When I click "Buy"
    And I fill my payment information
    And I click "Finish"
   Then I should see "We are processing your order."

   Given I am admin "jarbas@company.org"
   And I click "Reports"
   And I click "Open Orders"
   And I see just one result
   When I click on the first result
   And I see "No restrictions known on the market"
   And I see "First purchase of the day"
   And I click "Approve Order"
   Then I should see "Email sent to 'john@doe.net'"    

Com todos os passos num teste black box acho que fica bem claro pra todo mundo o processo. Em cenários onde a compra não é bem sucedida, o processo também estaria tão claro quanto. Com os passos bem delimitados, sabemos o limite da nossa aplicação e quais casos de uso queremos comportar. Se novos aparecerem, discutimos ele.

Com os limites da nossa aplicação mais claros, daí sim acho que podemos discutir os termos. Mas isolar nosso core context sem conhecer nossos casos de uso - com cada um tendo uma idéia diferente da aplicação - não vai levar a nenhum bom resultado.

netojoaobatista commented 9 years ago

@yourwebmaker, vejo o cenário que você abordou como duas coisas distintas. Possivelmente dois domínios complementares.

1 - Sale

Recurso - Venda de produtos ou serviços
    Um cliente
    Após escolher seus produtos ou serviços
    Faz checkout

Cenário - 
    Dado - Um cliente
    E - Um carrinho com um ou mais produtos
    Quando - O cliente faz checkout
    Então - Criamos uma venda com o carrinho do cliente

2 - Fraud management

Recurso - Gerenciamento de fraudes
    Uma venda
    Após ser fechada pelo cliente
    Precisa ser aprovada

Cenário -
    Dado - Uma venda
    Quando - É concretizada pelo cliente
    Então - Verificamos se o nome dele se encontra no Serasa
    E - Verificamos se ele já fez várias compras no mesmo dia
    E - Verificamos se o valor que ele está comprando condiz com a seu limite de crédito
    Então - Aprovamos ou não a venda
augustohp commented 9 years ago

Não sei se penso certo ou errado, mas tenho os seguintes conceitos bem definidos da seguinte forma:

Order/Sale no domínio do cliente é uma compra, para a empresa isso é uma venda. Correto? (precisamos definir este termo corretamente)

Um Pedido (Order) não necessariamente é uma venda. Por vários motivos:

Uma venda (sale) é um processo concluído. Você entrega produtos de uma venda, não de um pedido. Uma venda envolve pagamento e todos os processos internos posteriores a ele. Uma venda envolve faturamento.

Aprovação de venda: Processo que dará continuidade à compra do cliente. Quando aprovada, o pedido pode assim ser encaminhado para entrega. O produto poderá sair da loja.

Acho que você aprova um pedido. Um pedido aprovado PODE virar venda se o pagamento for feito com sucesso.

netojoaobatista commented 9 years ago

Um Pedido (Order) não necessariamente é uma venda. Por vários motivos:

Eu te peço uma guitarra. Você não tem mais guitarras.
Eu te peço para entregar no Amazonas. Vocês não atendem àquela região.

Aí depende um pouco das regras de negócio. Um Order pode ser um contrato. Um compromisso de compra futura. Como trataremos isso? Como apenas um pedido, ou como um compromisso de compra? Se formos tratar como um compromisso, então pode ser um Sale com status PENDING e, eventualmente, ter seu status modificado para CANCELLED - se não for possível entregar em determinado lugar - ou DENIED - se não for aprovado.

augustohp commented 9 years ago

Por isso que precisamos dos cenários de teste. 😉

Concordo que o contexto muda tudo. Se vendemos carros personalizados o pedido é um contrato. Se vendemos camisetas que compramos no varejo, não.

On Fri, Mar 27, 2015 at 8:57 PM, João Batista Neto notifications@github.com wrote:

Um Pedido (Order) não necessariamente é uma venda. Por vários motivos:

Eu te peço uma guitarra. Você não tem mais guitarras.
Eu te peço para entregar no Amazonas. Vocês não atendem àquela região.

Aí depende um pouco das regras de negócio. Um Order pode ser um contrato. Um compromisso de compra futura. Como trataremos isso? Como apenas um pedido, ou como um compromisso de compra? Se formos tratar como um compromisso, então pode ser um Sale com status PENDING.

Reply to this email directly or view it on GitHub: https://github.com/php-brasil/Order/issues/2#issuecomment-87126999

yourwebmaker commented 9 years ago

@augustohp , eu queria simplificar mais ainda eliminando o cenário de aprovação de venda pelo admin. Tudo seria automático, responsabilidade de serviços terceiros. Exemplo: Imagine que somos o Walmart vendendo numa Black Friday. Atribuir a tarefa de aprovar todas as vendas manualmente seria algo ruim, mesmo que fosse só para clicar num relatório que é baseado em dados de serviços terceiros.

Sugiro que todos os processos de aprovação sejam decisões tomadas por outros sistemas (internos ou não) automaticamente - talvez seja fantasia no nosso mundo, mas é legal heheheh.

Vamos aos termos e possíveis cenários, novamente:

John entra na loja e compra o livro sobre DDD do Evans. Ele escolhe o meio de pagamento: Cartão, Boleto, ou Transferência. Se o pagamento for por cartão, precisamos verificar os dados de John e do seu cartão, ok?

Para isso, enviamos estes dados para o serviço de análise de risco para retornar se poderemos dar continuidade ou não. Feito isso, entramos nos cenário de aprovação ou cancelamento.

Estou tentando resumir bastante senão essa discussão nunca ver ter fim e nunca partiremos para o código :fast_forward:

Concordam ou desejam eliminar/acrescentar algo mais?

augustohp commented 9 years ago

Concordo. Agora a gente precisa das regras e condições.

Não me preocuparia muito se o serviço possui suporte ou não. Se implementar empate o quê ou como.

Já sabemos que aceitaremos cartão e boleto. Que chegaremos serasa e veremos compras anteriores do cliente. Mais ainda tem MUITO buraco de casos de uso. Simplificar não significa ignorar vasos de uso 😉

On Fri, Mar 27, 2015 at 9:12 PM, Daniel Lima notifications@github.com wrote:

@augustohp , eu queria simplificar mais ainda eliminando o cenário de aprovação de venda pelo admin. Tudo seria automático, responsabilidade de serviços terceiros. Exemplo: Imagine que somos o Walmart vendendo numa Black Friday. Atribuir a tarefa de aprovar todas as vendas manualmente seria algo ruim, mesmo que fosse só para clicar num relatório que é baseado em dados de serviços terceiros. Sugiro que todos os processos de aprovação sejam decisões tomadas por outros sistemas (internos ou não) automaticamente - talvez seja fantasia no nosso mundo, mas é legal heheheh. Vamos aos termos e possíveis cenários, novamente: John entra na loja e compra o livro sobre DDD do Evans. Ele escolhe o meio de pagamento: Cartão, Boleto, ou Transferência. Se o pagamento for por cartão, precisamos verificar os dados de John e do seu cartão, ok? Para isso, enviamos estes dados para o serviço de análise de risco para retornar se poderemos dar continuidade ou não. Feito isso, entramos nos cenário de aprovação ou cancelamento. Estou tentando resumir bastante senão essa discussão nunca ver ter fim e nunca partiremos para o código :fast_forward:

Concordam ou desejam eliminar/acrescentar algo mais?

Reply to this email directly or view it on GitHub: https://github.com/php-brasil/Order/issues/2#issuecomment-87128379

netojoaobatista commented 9 years ago

John entra na loja e compra o livro sobre DDD do Evans. Ele escolhe o meio de pagamento: Cartão, Boleto, ou Transferência. Se o pagamento for por cartão, precisamos verificar os dados de John e do seu cartão, ok?

Okay

Para isso, enviamos estes dados para o serviço de análise de risco para retornar se poderemos dar continuidade ou não. Feito isso, entramos nos cenário de aprovação ou cancelamento.

Okay

Concordam ou desejam eliminar/acrescentar algo mais?

eu queria simplificar mais ainda eliminando o cenário de aprovação de venda pelo admin

Você pode ter um Fraud Management Service que independe da intervenção do admin. Temos eventos de domínio. A criação de um Sale pode causar um evento Order Created que deverá ser analisado pelo FraudManagementService.

netojoaobatista commented 9 years ago

Já sabemos que aceitaremos cartão e boleto. Que chegaremos serasa e veremos compras anteriores do cliente. Mais ainda tem MUITO buraco de casos de uso. Simplificar não significa ignorar vasos de uso

Concordo, mas é preciso tomar cuidado para que um domínio não viole outro domínio. Os domínios precisam ser desacoplados de tal forma que permita que a análise de fraudes seja adicionada ou removida quando adequado. O sistema de pagamentos precisa ser adicionado ou removido quando adequado - uma loja pode "entregar e receber no local".

São domínios distintos:

Posso ter uma loja com apenas um catálogo. Posso adicionar a feature Venda dos produtos. Posso adicionar um gestor de fraudes. Posso adicionar um sistema de pagamentos digitais. Posso compor a solução com essas features, sem acoplar a aplicação à todas as features ao mesmo tempo.

yourwebmaker commented 9 years ago

Bom... vou ter que dar uma saída agora e volto a discutir. Acho que precisamos de um P.O. para fechar de vez esses requisitos.

Quem assume? Assim a gente evita de cada um ficar dando opinião sobre e seguimos features definidas por um só.

Be right back.

netojoaobatista commented 9 years ago

Acho que você é o mais adequado para P.O., @yourwebmaker. Afinal, foi sua thread que originou a brincadeira.

:P

yourwebmaker commented 9 years ago

Beleza, mas vou precisar de auxílio nestes domínio que não conheço nada. Minha praia é outra. Já volto em instantes com requisitos definidos.

yourwebmaker commented 9 years ago

Vamos lá. Assumindo papel de P.O.

Atendendo ao que o @netojoaobatista falou, vamos delimitar nossos domínios e não deixar que um invada o outro.

Vamos tentar também definir todas as features que envolve um processo de compra numa loja, desde a entrada do cliente até a finalização e recebimento da compra.

Como é MUITA coisa para implementar, vamos fazer de conta que Catálogo e Carrinho já existem (não sei de podemos mockar isso em BDD e depois TDD - Queria apenas confiar nestas interfaces e não dar muito trabalho).

Então:

Acho inicialmente é só isso heheheh

netojoaobatista commented 9 years ago

Como é MUITA coisa para implementar, vamos fazer de conta que Catálogo e Carrinho já existem (não sei de podemos mockar isso em BDD e depois TDD - Queria apenas confiar nestas interfaces e não dar muito trabalho).

Conseguimos mockar, se tivermos uma interface para o carrinho. De acordo com os requisitos que você levantou, o catálogo pode ser dispensável porque estamos um passo após a escolha dos produtos. Mas a interface do carrinho pode ser necessária.

Acho que pode ser bacana criar uma nova issue para cada Feature, @yourwebmaker. Isso ajudará a descrevê-las de forma mais organizada.

lcobucci commented 9 years ago

Quando conversei com o @iannsp sobre a thread no FB, disse pra ele que tínhamos pouquíssimas informações pra analisar o domínio, agora a complexidade vem surgindo. Gostei demais =) Valeu @augustohp

Vou colocar mais água nesse feijão (quem sabe um pouco de paio até).

Acredito que estamos misturando e acoplando bounded contexts diferentes. Sales e Risk Analysis são duas coisas separadas. Assim:

Ao pagar com cartão, precisamos verificar através de um serviço de fraudes se esta compra não nos trará nenhum problema no futuro. Este serviço precisa dos dados do cliente, dados do cartão e total da compra.

O serviço de fraudes não deveria depender necessariamente de um cartão + cliente + total da compra, mas de um contexto de análise (temos uma nova entidade então?).

O serviço de fraude pode nos retornar que podemos prosseguir ou não.

Estamos assim delegando a NOSSA decisão de prosseguir com a venda para o serviço de fraude (not so good, right?). Mas o serviço de fraude pode nos retornar uma análise de crédito (rá, mais uma entidade!) e do lado do Sales tratarmos esta análise.

Uma coisa importante: sempre iremos fazer a análise de crédito? Isso tem um custo (financeiro e de processamento). Uma vez que analisamos que o Fulano está ok, quando precisaremos analisá-lo novamente?

netojoaobatista commented 9 years ago

Nos casos que tenho visto de gerenciamento de fraude, temos um índice que varia conforme o vendor. Vamos supor que o valor seja de 0 à 1.

0 => Sem risco 1 => Fraude confirmada

Valores intermediários são notas de risco que devem ser analisadas pela loja. Algumas lojas automatizam a decisão baseado no total da compra ponderando o risco. Por exemplo, em vendas de até 100 reais, um risco de 0.1 ou 10% é aceitável. Mas numa venda 1000 reais, um risco de 0.1 pode não ser aceitável e uma intervenção manual de aprovação da venda é necessária no admin.

Outro caso é o custo que você mencionou, @lcobucci. Como cada consulta em sistemas de gerenciamento de fraude é paga, então as lojas precisam decidir quando fazê-las. Apenas compras com valor superior a X? Qual o histórico desse cliente na loja?

yourwebmaker commented 9 years ago

@lcobucci, o @netojoaobatista já havia mencionado sobre este lance acoplar contextos diferentes informando também que a análise de fraude pode ser opcional em algumas compras.

O serviço de fraudes não deveria depender necessariamente de um cartão + cliente + total da compra, mas de um contexto de análise (temos uma nova entidade então?).

Imaginei que os serviços de fraudes necessitassem exclusivamente destes dados.

Estamos assim delegando a NOSSA decisão de prosseguir com a venda para o serviço de fraude (not so good, right?). Mas o serviço de fraude pode nos retornar uma análise de crédito (rá, mais uma entidade!) e do lado do Sales tratarmos esta análise.

Se tivermos a análise de crédito podemos evitar consultas ao serviço de fraude.

iannsp commented 9 years ago

uia!!!! bem legal a direção da discussão. da minha parte, concordo com @lcobucci no fato de que tem laranja nessa duzia de maça ai. Domínios que trabalham juntos não necessáriamente precisam ser discutidos juntos ou estar no mesmo dicionario , vejamos:

Sobre linguagem ubiqua, nós ja vimos aqui um caso que exemplifica bem o tipo de problema que achar que a linguagem ubiqua é supra domain que é como a Loja define uma venda e como o cliente define uma venda, então meu primeiro comentario seguindo a regra do mhodm (minha humilde opnião de merda [ sim, eu continuo tentando fazer esse acronimo pegar]) é vamos focar no order e retirar toda a complexidade que esteja fora desse domínio. :)

Ainda sobre isso, queria reafirmar a pergunta do @augustohp Quais os casos de uso que resolveremos e como? e dizer que os casos de uso contem muitos domínios e estao no nível de aplicação e não no nível do domínio, com isso quero dizer que ele é a integração de varios domínios e que isso dificulta a discussão por que traz outros domínios para a baila.

Inicialmente eu tive a impressão que o domínio que @yourwebmaker queria discutir era o Order, então não seria legal utilizar termos como busca(que esta antes do order existir), adicionar(que esta no cart), carrinho(que quando finalizado dá origem ao Order), comprando(já que o order trata do que foi comprado), fraude/antifraude(domínio secundario, componente em Order, que participa do dominio) e alguns outros.

calma que ja tô na metade do meu argumento ;)

Sendo assim...

Company\Sales\Order;
     create(ItemCollection);
     approve();
     reprove();

// permite operações de negócios com coleções de Orders
Company\Sales\OrderCollection;

// encapsula o que foi comprado, independente do que é que foi comprado e da complexidade disso.
Company\Sales\Order\Item;
     setProduct();
     setQuantity();

Company\Sales\Order\ItemCollection;
    add(item);

$cart = new ItemCollection();
$cart->addItem(new Item('Livro do Batman', 14),2);

// missão principal de order
$order = new Order($cart);// um carrinho vira um order ao clicar em fechar/pagar 

// delegacao ao package de pagamento para fazer seu trabalho, meio que uma inversão do modelo sugerido até agora.

if($payment->approve($order, $FinantialData))
  return $order->approve();
return $order->reprove();

$payment->mark($order, 'PAGA')->when("Boleto", "PAGO");

o que eu quis dizer é que discutir o Order ja daria muito pano pra manga, e que o Order é a concretização da venda.... um carrinho abandonado não tem order, mas um carrinho fechado tem, e o estado do Order estaria dentro de (Aprovado, reprovado, Pago, em aberto, atrasado). Então acho que o problema é exclusivamente o order, sua linguagem, sua arquitetura e modelagem para composição).

mhod

lcobucci commented 9 years ago

Explorando um pouco mais oq o @iannsp sugeriu e mesclando com o que o @netojoaobatista disse, podemos modelar algo assim:

Company\Clients\Email; // Just a Value Object
    create(string address);

Company\Clients\Client;
    create(string name, Email email);
    getName():string;
    getEmail():Email;

Company\Stock\Product;
     create(string name, float price);
     getPrice():float; 
     getName():string;

Company\Sales\Item;
    create(Product product, int quantity);
    getPrice():float;

Company\Sales\Order\ItemCollection;
    add(Item item);
    remove(Item item);
    get(Product product):Item;

Company\Sales\ReprovalReason; // Another Value Object
    static RejectedClient():ReprovalReason;
    static InsufficientFunds():ReprovalReason;
    getMessage():string;

Company\Sales\Order;
     create(Client client, ItemCollection items);
     getClient():Client;
     getPrice():float;
     approve();
     reprove(ReprovalReason reason);

Company\Sales\Cart;
    add(Product product, int quantity):Item; // factory method
    remove(Product product, int quantity);
    checkout(Client client):Order;

$cart = new Cart();
$cart->add(new Product('Livro do Batman', 14.5), 2);
$cart->add(new Product('PHP Brasil History', 50000), 4);

$client = new Client('John Doe', new Email('john@doe.com')); // O cliente acabou de se registrar
$order = $cart->checkout($client);

A parte de análise de risco poderia ficar assim:

Company\RiskAnalysis\Context; // interface a ser implementada por Order, por exemplo.
    getClient():Client
    getPrice():float;

Company\RiskAnalysis\Analysis;
    create(Context context, float risk);
    getContext():Context
    getRisk():float;
    getAnalysedAt():DateTime();
    isExpired():boolean;

Company\RiskAnalysis\Analyses; // aka analysis repository
    findLast(Client client):Analysis;

Company\RiskAnalysis\Policy;
    isAllowed(Analysis analysis); // sem criatividade agora =P

Company\RiskAnalysis\Policies\Default; // implements Company\RiskAnalysis\Policy
    create(float acceptableRisk);
    isAllowed(Analysis analysis);

Company\RiskAnalysis\Provider; // interface a ser implementada pelos serviços que oferecem análise de crédito (sem criativade aqui tb)
    analyze(Context context):Analysis

Company\RiskAnalysis\ProviderChain; // inventando moda aqui, normalmente as análises são realizadas em mais de um analisador
    add(Provider provider);
    analyze(Context context):Analysis

Company\RiskAnalysis\Analyzer; // domain service =)
    create(Analyses analyses, ProviderChain providers);
    analyze(Context context):Analysis // busca a última análise do cliente, se não estiver expirada retorna ela, senão solicita análise através dos providers registrados

Assim, quem for realizar análises simplesmente depende da Policy e do Analyzer:

$policy = new Default(0.4);
$analyzer = new Analyzer(new Analyses(), new ProviderChain());

if (!$policy->isAllowed($analyzer->analyze($order)) {
    $order->reprove(ReprovalReason::RejectedClient()); // Reprova a parada na hora
}

Acho que assim temos ideias para a parte de análise e de compra, falta a parte de pagamento =)

lcobucci commented 9 years ago

Agora que desviamos bagarai da pergunta do @augustohp, podemos retornar pra ela =)

@yourwebmaker essa é sua missão.

augustohp commented 9 years ago

Agora que desviamos bagarai da pergunta do @augustohp, podemos retornar pra ela =)

@yourwebmaker essa é sua missão.

Eu me recuso a pensar em código antes de ter a resposta dela. Pela resposta, a última coisa que pertence ao domínio é a análise anti-fraude.

Vocês colocaram quantidade em produto, motivo de recusa da venda, operações em batch de ordens, que a aprovação depende de dados financeiros e nmodm (agradando o @iannsp) :hankey: pros use-cases. Eu possa estar extremamente errado, mas entendi que esse é exatamente o problema que o DDD tenta resolver.

Aos use-cases, tenho minhas perguntas:

Pensando um pouco nas informações que temos, desenhei os seguintes Bounded Contexts. Tenho grandes dúvidas em relação a DDD e gostaria bastante de discutir e melhorar esses contextos.

iannsp commented 9 years ago

então.... eu não quis pensar em código, só quis resumir uma opnião em um modelo de pseudo codigo :) Eu pensei somente a questão do Order. minha pergunta, pra não mais bagunçar... essa coisa toda nasceu de uma discussão de um modelo de Order... esse ainda é o problema original(sim, estou repetindo a pergunta do @augustohp )? se estivermos discutindo order nada de pesquisa, meio de pagamento, risco e fraude tem sentido em estar aqui. :), mas se o que estamos discutindo é todo o conjunto necessário para vender, ai é outra conversa.

lcobucci commented 9 years ago

Vocês colocaram quantidade em produto, motivo de recusa da venda, operações em batch de ordens, que a aprovação depende de dados financeiros e nmodm (agradando o @iannsp) :hankey: pros use-cases.

Ao passo que estamos conversando sobre as necessidades, estamos bolando ideias sobre o que vai aonde. Só colocamos tudo isso numa uma representação textual (é bem mais fácil que desenhar um diagrama de domínio aqui).

  • Não acho que quantidade seja relevante. Eu nunca comprei 3x o mesmo livro. Compro 3 edições diferentes, em línguas diferentes mas não o mesmo.

O @yourwebmaker é o cara pra responder isso, só adaptamos o que está no repo.

  • Um livro, em várias edições é o mesmo "produto" ou outro "produto"? Ninguém aqui ainda sabe responder ao certo que produto vendemos.

Vejo como produtos diferentes.

  • Aceitamos cartão e boleto. Qual a diferença e porque aceitamos os dois? Aceitamos parcelamento? Em quais condições?
  • Pagando bom boleto, após 5 dias cancelamos a compra?

Boas perguntas para o @yourwebmaker.

Sobre os contextos, acredito que não estamos pensando de forma diferente:

O que faltou a gente destrinchar é a parte de pagamento, onde temos mais brechas.

augustohp commented 9 years ago

Acho que o que falta é a gente concordar no nosso Core Domain. Pelo que li até agora é a venda, não tem nada a ver com a análise de risco (que seria um suporting role nesse contexto).

Se for a venda, a pergunta imediata: "O quê, pra quem?" Simplificando ainda mais, vendemos e-books e só. Pra quem?

Antes da implementação eu gostaria de um dicionário de termos e seus significados. Assim podemos ter certeza que todos irão modelar e discutir o mesmo problema. Essa thread é a prova de que o esforço em desenvolver a "língua onipresente" não é um esforço desnecessário.

Em vários casos aqui, o mesmo termo foi usado de formas diferentes e isso reflete invariavelmente no design da aplicação. A exemplo o Company\RiskAnalysis\ProviderChain seria, pra mim, um Company\RiskAnalysis\StrategyInterface mas quem decide isso é o core domain.

PS: Eu sei que todo mundo aqui pira no design de código. Eu pelo menos não consegui ignorar eles :stuck_out_tongue_winking_eye: Mas sem as regras e nosso objetivo a coisa fica meio vaga. E por "objetivo" eu imagino uma parada bem detalhada: com estados e fluxos bem definidos.

PPS: Vou tentar manter o primeiro comentário na thread atualizado com o que a gente descobriu até agora. Seria interessante todos nós mantermos ela. :wink:

augustohp commented 9 years ago

Criei um volcabulário lá no primeiro comentário. Considerem ele a versão alpha :see_no_evil: da nossa língua onipresente.

Eu prefiro termos em inglês, mas me preocuparia com eles só depois de definir bem os termos pra evitarmos ruídos na nossa discussão.

iannsp commented 9 years ago

Não sou de usar referência de livros, não diretamente, mas discutir Package\Vendaao invés de um subdomínio de cada vez Order, Fraud etc, se parece muito com págs 408-412 da versão pr-br do domain-driven design, concordam?

yourwebmaker commented 9 years ago

Respondendo às perguntas do @augustohp

Um livro, em várias edições é o mesmo "produto" ou outro "produto"? Ninguém aqui ainda sabe responder ao certo que produto vendemos.

Um livro em várias edições será o mesmo produto. Como havia informado anteriormente, trabalhamos somente com produtos digitais (e.g. downloads, e-books) e queremos sempre oferecer versão mais atualizada dos produtos para nossos clientes. É mais válido pegar a última edição do PoEAA e substitui-la do que vendermos 2 edições separadas. Sendo assim N edições == 1 produto. Sempre 1 produto, nada de grade.

Aceitamos cartão e boleto. Qual a diferença e porque aceitamos os dois? Aceitamos parcelamento? Em quais condições?

Aceitamos os 2 pois nem todos os nosso usuários dispõe de cartão de crédito. Outra vantagem do boleto é que a taxa cobrada pelo banco é menor que a taxa a nossa operadora de cartão de crédito.

Não acrescentaremos taxa aos boletos gerados por nossa empresa.

Parcelaremos em até 3x sem juros.

Pagando com boleto, após 5 dias cancelamos a compra?

Sim, será cancelada. Ao cancelar compra, não precisamos repor nada em estoque, já que se tratam de produtos digitais.

Para aliviar ainda mais a nossa viagem em mares desconhecidos, supomos que estamos desenvolvendo esta loja de E-books: http://www.informit.com/store/browse/ebooks#!?sort=Relevance

A informtit ainda vende livros impressos, mas este não será nosso caso. Trabalhamos só e somente só com livros e produtos digitais.

netojoaobatista commented 9 years ago

O verbo vender, nesse cenário, é transitivo direto e indireto:

Quem vende, vende alguma coisa à alguém.

O alguma coisa é um produto digital. O alguém é o cliente.

O processo de vender alguma coisa significa que um Cliente escolheu o produto e decidiu por comprá-lo. Após a decisão, o cliente se compromete em pagar.

Para poder implementar uma venda, precisamos, antes, que alguma coisa exista e que o cliente possa escolhê-la. Venda, da forma como estamos lidando na brincadeira, é um contexto que, apesar de intimamente ligado com o catálogo e com o carrinho, é diferente.

Não podemos definir Cart nem Product nem ProductItem nessa feature, simplesmente porque esses participantes já existem em um outro lugar da aplicação.

Uma Order, para existir, precisa de OrderItem e de um Customer.

Após comprar, o cliente paga. Após pagar, a loja faz análise de crédito. Ou seja, não temos que falar de nada que não seja a venda, porque as outras coisas acontecem após a venda ser concretizada.

O core domain aqui é tão somente a transformação de uma sessão de compras num contrato chamado Order, onde o cliente se compromete a pagar pelos produtos escolhidos e a loja se compromete a entregá-los.

yourwebmaker commented 9 years ago

Respondendo a mais perguntas do @augustohp :

Nossos clientes precisarão de cadastro ou existirão em outra base (GitHub, Facebook)? Sim, o cliente pode ser autenticado por outros serviços e podemos puxar dados básicos dele destes serviços. Sei que precisamos disso para definir nosso Core Domain, mas não devemos dar muita importância agora.

O que define uma venda? O pagamento com sucesso, o cliente efeutando a compra?

Como falado anteriormente, e creio que seja isso na realidade, uma venda é uma compra finalizada e paga.

Na thread que gerou essa discussão usei o termo venda de forma errada.

Quais os estados possíveis de uma venda?

A venda não tem estado (agora é order/pedido, ok?). A venda é uma concretização e pagamento de uma compra. Quem contem está agora é o order/pedido.

O que diferencia uma venda "segura" (com faturamento pra empresa garantido) de uma que vai provavelmente dar prejuízo?

Uma venda segura é aquela que foi paga por boleto. O dinheiro já consta na conta da empresa.

Uma venda não-segura seria uma venda por cartão. Algum cliente fraudulento poderia comprar com cartão de outra pessoa. Não sei como isso é tratado no mundo real, mas se essa venda fosse concretizada, teríamos que pagar este total à nossa operadora e ainda indenizar a pessoa que foi "roubada", mas...... caso essa não seja a realidade, favor tratar como é feito atualmente na realidade. Creio que é a operadora que é quem se lasca com essas coisas, não a loja.

O pagamento será gerenciado pela gente ou por um terceiro?

Inicialmente, por nossa empresa mas, poderia exemplificar um caso de paramento gerenciado por terceiros?

iannsp commented 9 years ago

desenhando o problema dessa discussão ;) sales_basic

netojoaobatista commented 9 years ago

Senhores, por favor, vamos colocar uns pingos nos ís:

Se tratar Order como o core domain, tudo o que precisamos são:

  1. Interface já existente do Product e do Cart.
  2. Definir um OrderItem que vai encapsular esse Product e vai definir quantidade, valor unitário, desconto unitário e total do item.
  3. Definir a interface do Customer, que é o cara que está comprando.
  4. Definir um Order que vai agregar os OrderItem, definindo os descontos gerais e total do pedido, e também o Customer, que é o cara que está comprando.
augustohp commented 9 years ago

Não sou de usar referência de livros, não diretamente, mas discutir Package\Vendaao invés de um subdomínio de cada vez Order, Fraud etc, se parece muito com págs 408-412 da versão pr-br do domain-driven design, concordam?

Opa! Discussão de DDD!

Não acho que seja o caso de um Shared Kernel mas sim de um Core Context único e bem definido: a compra.

Todos os demais papéis, pra mim, parecem bem separados e só necessários pra suportar a venda. @yourwebmaker concorda?

Uma Order, para existir, precisa de OrderItem e de um Customer.

Não acho possível definir esses papéis agora, enquanto não concordarmos todos com os termos.

Sale - É o processo como um todo. É a abstração do super domínio. Colocar um produto à venda é sale. O cliente escolher o produto é sale. O cliente pagar pelo produto é sale. A loja aprovar o pagamento é sale. A loja entregar o produto é sale. Sale é um substantivo que define tudo isso.

Sale ou Venda é o processo como todo, concordo. Só "colocar o produto à venda" não seria uma venda, certo? Uma venda ou é o processo todo, ou não é uma venda.

Concorda?

Order - É um contrato. Um compromisso assumido pelo cliente de pagar por um produto ou serviço e da loja de entregar o produto ou serviço.

Prefiro o termo compra ou purchase pra esse motivo. Deixa claro o que o agende é o cliente, enquanto venda deixa claro que o agente é a empresa.

Definir um OrderItem que vai encapsular esse Product e vai definir quantidade, valor unitário, desconto unitário e total do item.

Bem levantado. Temos esses requisitos @yourwebmaker ?

Falando de OOD, eu prefiro a relação de uma Purchase (sou teimoso) diretamente com um Product já que é esse o relacionamento na nossa língua onipresente. Sempre é possível acrescentar responsabilidades usando OO sem alterar essa relação de dependência.

PS: Vou atualizar o vocabulário no primeiro comentário.

augustohp commented 9 years ago

:cop: Só um desabafo. Depois de ler a versão em inglês do DDD tenho achado essa tradução uma bela duma bosta.

Shared Kernel -> Núcleo Segregado

Caralho, a gente não quebra o núcleo em partes diferentes mas compartilha ele entre diferentes domínios. Uma tradução dessa (óbvio que ela não é a única) :hankey: completamente o entendimento de uma técnica de modelagem que tem como principal valor a linguagem. Ironia na sua pior forma.

netojoaobatista commented 9 years ago

Sale ou Venda é o processo como todo, concordo. Só "colocar o produto à venda" não seria uma venda, certo? Uma venda ou é o processo todo, ou não é uma venda.

Concorda?

Sim: Sale é o processo todo, mas como um todo.

augustohp commented 9 years ago

Sale ou Venda é o processo como todo, concordo. Só "colocar o produto à venda" não seria uma venda, certo? Uma venda ou é o processo todo, ou não é uma venda.

Concorda?

Sim: Sale é o processo todo, mas como um todo.

Muy rico.

iannsp commented 9 years ago

@augustohp a compra(concordo com o termo) é muita coisa. É um domínio muito amplo, cheio de subdominios que são utilizados em outros processos (discordo que Client, Fraud, Risk e Order, por exemplo, sejam uteis somente no contexto da compra) para efeito de discussão do domínio COMPRA concordo em olharmos para todos eles ao mesmo tempo, mas não concordo que todos eles sejam um Core a não ser em termos da definição da linguagem. Cada um deles tem seu próprio contexto/problema.

Eu penso Order como um domínio que é subdominio de Compra.

yourwebmaker commented 9 years ago

Eu penso Order como um domínio que é subdominio de Compra. Bingo!

augustohp commented 9 years ago

Caros, dêem uma olhada no nosso vocabulário e vejam se concordam com tudo. Dêem um carinho especial pros :eyes:.

@yourwebmaker o :construction_worker: precisa de um carinho seu. :stuck_out_tongue_winking_eye:

@augustohp a compra(concordo com o termo) é muita coisa.

Concorda com o "muita coisa" do vocabulário?

[o domínio da Compra é] cheio de subdominios que são utilizados em outros processos (discordo que Client, Fraud, Risk e Order, por exemplo, sejam uteis somente no contexto da compra)

Um domínio (até onde entendi) é um conjunto de contextos. Raramente um domínio é composto por elementos (Cliente, Compra, Análise de Risco, etc) isolados mas os contextos podem e devem ser isolados.

Um contexto isolado não significa que ele não dependa de outros contextos. No meu esboço coloquei a compra como contexto principal, Clientes e Produtos como contextos de suporte justamente por esse motivo.

yourwebmaker commented 9 years ago

Compra: Um cliente escolheu um ou mais produtos e decidiu uma forma de pagamento.

Acho que é o feito de comprar algo mesmo =). Forma de pagamento está relacionado ao ato de comprar (pagar)

Venda: A empresa aceitou a compra de um cliente e entregou o produto.

Isso. O produto saiu da empresa. Uma venda é uma receita para a empresa.

Parcelamento: Uma compra pode ser dividida em até 3x sem juros. Independente de valor.

É, precisamos verificar qual é o valor mínimo para parcelamento. R$100, ok? (pode ser definido por config)

Vamos ignorar limites de território e legislações? Vendemos tudo pra todo mundo?

Vendemos SOMENTE para o Brasil. Não aceitamos clientes de outros países. Os motivos:

Mas... nada impede de futuramente vendermos tudo para todos (O P.O. sonhador falando)

Todo cliente está pré-aprovado a comprar ou faremos alguma checagem (por exemplo) de e-mail válido?

O cliente DEVE ter e-mail válido. Caso tenha autenticado-se pelo Facebook ou Github, podemos pegar o e-mail dele e para eliminar essa treta com cadastro de cliente, só aceitamos clientes autenticados por serviços: Google, Facebook, Github, Outlook, etc.

O e-mail do cliente deve ser válido, pois enviaremos o acesso aos nossos produtos para seu e-mail.

Fraude: O cliente não vai pagar pelo produto.

Notificamos ao engraçadinho que sua tentativa de compra não foi aprovada. Não lhe informaremos os reais motivos por ética e segurança. Apenas disponibilizaremos um telefone/email de contato para possamos esclarecer suas dúvidas.

Caso a fraude seja engano, ele terá que refazer a sua compra.

Compra legítima: A probabilidade do cliente não pagar é extremamente baixa. Uma compra legítima se tornará uma venda.

Exatamente. Venda = receita pra empresa.

augustohp commented 9 years ago

@yourwebmaker Pelo que entendi você concorda com o vocabulário. Pra ter certeza, tente desenhar o fluxo de transformação de estado entre Compra e Venda. Quais etapas, com os termos existentes no vocabulário, compõem essa transição.

Se você for usar algum termo diferente, descreva-o como no vocabulário. Repare que no fluxo de trasição, os termos não devem se repetir mas uma transição pode ser composta de um retorno à uma etapa posteior ao fluxo. @netojoaobatista é o mestre pra mim nessas paradas, veja se não deixei passar nada. :wink:

Acho que com isso temos nosso domínio, nossos contextos (principal e de suporte) e nossa língua onipresente. Daí podemos partir pra parte bacana. :smile:

PS: Atualizei o vocabulário com as informações adicionais.

yourwebmaker commented 9 years ago

Antes da parte bacana a gente deveria descrever os *.feature da vida hahahahha

Vou rabiscar algo aqui.

iannsp commented 9 years ago

@yourwebmaker foca em confirmar que a gente conseguiu definir bem o que é necessário para se comunicar bem. claro que a linguagem é evolutiva, mas ideial é que você como P.O. nos dê certeza que isso esta ok e ai, a partir disso não vejo problemas que pense em features, alias, portanto que elas utilizem a linguagem definida aqui, elas poderam ajudar na validação.

augustohp commented 9 years ago

Antes da parte bacana a gente deveria descrever os *.feature da vida hahahahha

Elas constituem a parte bacana. :wink: Mas sem o fluxo de estados e o vocabulário elas são um barulho desnecessário. É contra-produtivo testar a Venda se ninguém concorda com o que ela é.

netojoaobatista commented 9 years ago

Vocabulário:

Coloquei os termos numa ordem meio cronológica de ocorrência e de uma forma mais abstrata, sem muitas especificidades. Antes de trabalhar em especificidades, acho que precisamos concordar com os termos principais, ordem de ocorrência e os cenários criados a partir deles. Uma vez que concordemos com os termos, fazemos a separação e os dissecamos.

Cenário - Compra de um produto

O cliente, por livre e espontânea vontade, escolhe um ou mais produtos e os adiciona ao carrinho. Após escolher todos os itens que deseja, o cliente decide por fazer o pedido e pagar.

Evento relacionado:

Que consiste em decidir transformar o carrinho em um pedido.

Cenário - Pagar uma compra

Dado um pedido de determinado valor total, incluindo taxas e despesas relacionadas com frete, manipulação, etc, o cliente escolhe um método de pagamento aceito pelo vendedor e paga pela compra.

Eventos relacionados:

Que consistem no processo de aprovação ou não do pagamento.

Cenário - Aprovação do pedido

Dado um pagamento por um pedido, o vendedor decide se aprova ou não o pedido. O vendedor pode utilizar, eventualmente, um mecanismo externo para análise de risco, para diminuir a probabilidade de fraudes.

Eventos relacionados:

Que consistem na análise e aprovação do pagamento e/ou da compra.

Cenário - Entrega do pedido

Dado um pagamento aprovado de um determinado pedido, o vendedor entrega os produtos adquiridos pelo cliente.

yourwebmaker commented 9 years ago

Bom.. já que a criança aqui não tem celular e passar algo rabiscado não daria muito bem, segue um descritivo usando algumas palavras do nosso vocabulário:

iannsp commented 9 years ago

Senhores, me parece que temos que dar o próximo passo e aplicar aqui a máxima do "o ótimo é inimigo do bom". Gostaria de partir dessa linguagem que temos para que evitemos paralisia no processo. O que precisa ser descoberto vai ser descoberto, basta que a gente mantenha o modelo refletindo as descobertas ao invés de mofando num canto. Ok!? @augustohp @yourwebmaker @netojoaobatista @lcobucci ?