Giter VIP home page Giter VIP logo

Comments (9)

yvoyer avatar yvoyer commented on August 16, 2024

I created an example of how I would do your requirements. They are not working example, just code fragment from which you can get a basic idea.

Here are what classes or methods I extrapolated from your statements:

Customer talks to Employee. Employee logs in, creates an offer, sends it to Customer

  • I created an Employee->createOffer(): Offer that is handled by a command handle CreateOfferHandler which could be called from some controller.
  • The event listener SendOfferToCustomer::onOfferWasCreated(OfferWasCreated $event) manage the sending of the offer to the customer.

Customer receives Offer, agrees, informs Employee

  • The command handler AgreeToOfferHandler calls the Customer->agreeToOffer(OfferId) which change to state of the offer with Offer->agree().
  • An event CustomerAgreedToOffer event is triggered, and received by the OfferAgreedNotifier listener. From there you can do whatever there is to do to notify the employee.

I did not completed all the requirements, but I hope this gives you a better idea.

Now I started thinking that it should be something like:

Employee->sendOfferToCustomer
Employee->sendOrderToCustomer
Customer->confirmOffer

or at least:

Customer->receiveOffer
Customer->receiveOrder
Customer->confirmOffer

IMO, The Customer should not know about the receiveOrder, receiveOffer, and the Employee should not know about the sendOfferToCustomer or sendOrderToCustomer since Customer and Employee seems to be 2 aggregates roots from 2 differents context. It is ok for them to receive Id, but the aggregate objects should probably not be passed to this context from any other places than the handlers.

But then again, I don't know all the requirements or needs, so it all depends on your domain.

Good luck, and hope it help.

from php-ddd.

webdevilopers avatar webdevilopers commented on August 16, 2024

Great feedback @yvoyer ... again.

So looking at Employee and Customer from a different Context really changes the responsibility of the actor on the Order Domain Model?
Indirectely the Customer is "placing an Order" when calling. But it is the Employee who adds it to the system.

Surprising and exciting at the same time.

BTW: Do you recommend using the Symfony Event Listeners or have you tried the @SimpleBus EventBus?
https://github.com/SimpleBus/EventBus

P.S. on terminilogy:

  • Isn't it Offer Status instead of State?
  • Isn't it better to use submitOffer / placeOrder instead of createOffer / createOrder even on the Employee?

Regarding: https://www.ego4u.com/en/business-english/communication/offer-order

BTW: Really like the $offer = self::PendingOffer($responsible); approach!

from php-ddd.

yvoyer avatar yvoyer commented on August 16, 2024

I have not tried SimpleBus yet, but it seems simple. I heard good review about it though.

I have used lite-cqrs for commands and EventDispatcher from symfony.

The only downside of the symfony dispatcher is having to extend the Event class. Try the lib that you find will help you accomplish your goal sooner.

About the terminology, I would probably go with terms like you said submitOffer and placeOrder as they are probably more meaningfull to the domain users. You should probably ask your domain expert to see which terminology is better for them.

BTW: Really like the $offer = self::PendingOffer($responsible); approach!

My pleasure, This is a good example of factory method. Since PHP do not enable multiple construct definitions, the static methods acts as constructs. I would also recommend to put your __construct private to force the dev (an you) to use the static methods instead of the construct. Makes the code more meaningfull.

For the State vs Status it a mather of choice on your part.

from php-ddd.

webdevilopers avatar webdevilopers commented on August 16, 2024

And again we agree @yvoyer ! I will try to adapt what we talked about to my current project. There will be feedback by the Customer and the Developers at the beginning of next month.
I will post some approved code samples then! Thanks so far!

from php-ddd.

webdevilopers avatar webdevilopers commented on August 16, 2024

One question regarding your getOffer method:
https://gist.github.com/yvoyer/c2c016b7fe5288554e3f6c432acafd65#L124-131

Though it is the Customer that indirectly confirms an Offer it is still the Employee who uploads an Order Confirmation and by this marks it as confirmed.

So I guess I have to move this method to the Employee too.

If I moved the getOffer method there would the Employee have an $offers collection I would use like this?

class Employee
{
    $offers = array(); // some extra lazy Doctrine ArrayCollection possibly

    private function getOffer(OfferId $id)
    {
        return $this->offers[$id];
    }
}

While it would make sense to add the same $offers collection on the Customer the getOffer method should be called on the Employee side, right @yvoyer ?

from php-ddd.

yvoyer avatar yvoyer commented on August 16, 2024

For me it still makes sense for the customer to have a getOrder (OrderId):Order. Since it is private, it do not bloth the domain, but it is still usefull to fetch 1 order. If you need it also in the employee class, it's okay, but I would keep it private as long as possible.

Try not to get the object B of another object A to perform an operation. Just tell object A to perform operation on B, that way A keeps control, and any validation constraint are encapsulated in A.

side note

Employee logs in - an actual "Contract" is created. Work can begin

From this sentence I would probably create a Employee::getApprovedContract (ContractId): Contract. When the Customer would confirm its Order, the system would automatically create the Contract and assign it to the employee and customer using events.

from php-ddd.

webdevilopers avatar webdevilopers commented on August 16, 2024

That brings me back to the beginning of this discussion.

As I mentioned it isn't the Customer in person placing the Order. He calles the Office and the Employee enters it into the system. Later when the Office receives the Order Confirmation it uploads it.

Maybe Office / Employee are just Roles inside the System. Maybe placing and Confirming the Order should ONLY happen in the Customer Domain Model.

There is no urgent need to find out which Employee created which Order. In the end the Employee is just a placedBy or confirmedBy link to the User behind Employee.

Is this still okay from a DDD and Context view?

from php-ddd.

yvoyer avatar yvoyer commented on August 16, 2024

If the customer never touches the system, I would definitely put the task to create the order on the employee. You would still need the customer ID to create the order (but not the whole customer).

Maybe instead of an Employee you need a new domain entity named SalesRepresentative or any other name meaningful for your domain expert. As an employee might be too generic, as it depends upon the bounded context. In the human ressource context, it might make sense to have an Employee. Where in a sale context, you might have the SaleRepresentative which is in charge of taking order from customer.

Then the order would be shipped for confirmation to the shipping context where the order would be prepared by a Shipper to the buyer (customer with address info).

Finally when the order is shipped it might be sent to the quality assurance context to be handled by the AfterSaleRepresentative to take any complaints.

Maybe what is making your domain ambiguous is that you might need to explode it in context and see which finner grained entity is missing. You probably will find with your domain expert that some other terms are missing.

from php-ddd.

webdevilopers avatar webdevilopers commented on August 16, 2024

Actually we do have something like a SalesRepresentative. The Employee belongs to the Office. Though Office simply extends Employee atm.
And the Office will have to confirm the Order after having placed it.

I'm wondering how the Office will receive the Offer to change it.

  • Would a Service get the Customer and then get the Order from the repository and pass it to the Office?
  • Should the Office get the Order directly from the Customer return $orders[$orderId->id()]?

In both cases an $order has to be returned to be updated in the repository.

You see I still have problems with "ignoring the persistence". :/

from php-ddd.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.