You don't need a one-to-one mapping of interactors and entities. I believe such a design would be harmful.
DDD is all about context boundaries and the ubiquitous language within those boundaries. When you really focus on creating objects to represent the language of the business, you'll find everything begins to shape itself a bit differently.
It seems odd to me that a Sale would create or ship itself. In the real world, I could picture a sales person making a sale. Then, a shipping department may manage the logistics to ship it. Perhaps, a sale would be created via an on-line shopping cart and shipped via email. Using this language as an example, lets explore a possible alternative design.
SalesPerson
+createSale(Customer, Product, Price)
+amendSale(Sale, Amendment)
ShippingDepartment
+shipSale(Sale)
Wait a second!? Don't we usually ship Orders? Maybe it should go like this:
SalesPerson
+createOrder(Customer, Product, Price)
+amendOrder(Order, Amendment)
ShippingDepartment
+shipOrder(Order)
Order
+constructor(Customer, Product, Price)
+applyDiscount(Discount)
+updateShippingAddress(Address)
Both are getting closer, but really our sales team doesn't call them orders and our shipping department only calls them orders. Also, orders are always created from the existence of a Sale, so we should reflect that as well.
SalesPerson
+createSale(Customer, Product, Price)
+amendSale(Sale, Amendment)
Sale
+constructor(Customer, Product, Price)
+applyDiscount(Discount)
+updateShippingAddress(Address)
ShippingDepartment
+shipOrder(Order)
Order
+constructor(Sale)
+placeOnHold()
+shipped(TrackingNumber)
And so, it continues to develop.
The way I deal with the separation of logic is to try and visualize that object in real life. Then, think about the properties and actions it has that are relevant to the business-need/use-case/feature.
Edit: How do you interact with the methods on an Entity in DDD?
Instead of using the Command pattern or other interactors, you simply use them directly:
salesPerson = new SalesPerson()
sale = salesPerson.createSale(...)
...
shippingDept.shipOrder(new Order(sale))
Keep in mind that the two are not mutually exclusive. You can still leverage a Command pattern or Use Case/interactors if there's a need for it. You might have something like this (1 interactor to many entities and methods):
PartyUseCase(ShippingDepartment)
+prepareParty(SalesPerson, Customer)
plates = ProductRepo.findByName('plates')
forks = ProductRepo.findByName('forks')
platesSale = salesPerson.createSale(Customer, plates)
forksSale = salesPerson.createSale(Customer, forks)
ShippingDepartment.shipOrder(new Order(platesSale))
ShippingDepartment.shipOrder(new Order(forksSale))
...
Alternatively, there may be a simple script that's run once daily with nothing more than this (0 interactors):
orderRepo = new OrderRepository()
shippingDept = new ShippingDepartment()
for each order in orderRepo.getOrdersToShip()
shippingDept.shipOrder(order)
Ultimately though, if you are creating a one-to-one mapping of classes to methods, you are creating unnecessary complexity.
SalesService
), but it's just semantics. – king-side-slide Jun 12 '18 at 21:16