I am designing BC for Promo Codes. They work like this: Admin can create promo code by specifyingDetails (like Code and Description)Benefit (interface for ValueObjects, for example MoneyDiscountBenefit)Usage Restrictions - collection of AbstractUsageRestriction, eachrestricting use of promocode, for example:PromoCode can be used only by sigle userPromocode can be used on max 3 Order Items by each userPromo Code can be used on max 10 Order ItemsPromo Code can be used only to some OrderItems (some specific type, or where price is above some limit etc.)Customer can apply this promo code on his Order (some VO in this BC), then it is applied on all OrderItems fulfilling all restrictions. Then on OrderPaid event, PromoCode is used on each Order Item filfulling restrictions. Used, because this BC from customer perspective just handles that promo code is marked as applied/used and then next restriction checking (by anyone on this promocode) while applying/using can be affected by this use (if desired), for example with UniqueUsageRestriction if some user use promocode, another can't anymore - restriction throws exception.Now, my entity looks like this: <?phpclass PromoCode{    /** @var PromoCodeId */    private $id;    /** @var Details */    private $details;    /** @var Benefit */    private $benefit;    /** @var UsageRestrictions */    private $usageRestrictions;    /** @var PromoCodeUsesCollection */    private $promoCodeUsesCollection;    /** @var PromoCodeAppliesCollection */    private $promoCodeAppliesCollection;    public function __construct(PromoCodeId $id, Details $details, Benefit $benefit, ?UsageRestrictions $usageRestrictions = null)    {        $this->id                         = $id;        $this->details                    = $details;        $this->benefit                    = $benefit;        $this->usageRestrictions          = $usageRestrictions ?: new UsageRestrictions();        $this->promoCodeUsesCollection    = new PromoCodeUsesCollection();        $this->promoCodeAppliesCollection = new PromoCodeAppliesCollection();    }    public function getId(): PromoCodeId    {        return $this->id;    }    public function getBenefit(): Benefit    {        return $this->benefit;    }    public function getOrderItemIdsOnWhichWasAppliedWith(OrderId $orderId){        $this->promoCodeAppliesCollection->getOrderItemIdsWith($orderId);    }    public function applyFor(Order $order): void    {        $this->checkApplicabilityForOrder($order);        foreach ($order->getOrderItems() as $orderItem) {            $this->checkApplicabilityForOrderItem($order, $orderItem);            $promoCodeApply = new PromoCodeApply($order, $orderItem);            $this->promoCodeAppliesCollection->addApply($promoCodeApply);        }    }    public function useFor(Order $order): void    {        $this->checkApplicabilityForOrder($order);        foreach ($order->getOrderItems() as $orderItem) {            $this->checkApplicabilityForOrderItem($order, $orderItem);            $promoCodeUse = new PromoCodeUse($order, $orderItem);            $this->promoCodeUsesCollection->addUse($promoCodeUse);        }    }    public function countAppliesForOrder(OrderId $orderId): int    {        return $this->promoCodeAppliesCollection->countAppliesForOrder($orderId);    }    public function countOrdersWithUseByUser(UserId $userId): int    {        return $this->promoCodeUsesCollection->countOrdersWithUseByUser($userId);    }    public function canBeUniqueForUser(UserId $userId): bool    {        return $this->promoCodeUsesCollection->canBeUniqueFor($userId);    }    public function hasCode($code)    {        return $this->details->getCode()->getValue() === $code;    }    private function checkApplicabilityForOrder(Order $order): void    {        $this->usageRestrictions->checkApplicabilityForOrder($this, $order);    }    private function checkApplicabilityForOrderItem(Order $order, OrderItem $orderItem): void    {        $this->usageRestrictions->checkApplicabilityForOrderItem($this, $order, $orderItem);    }}I have feeling that it knows and does too much, but how to split that?I dont like those use and apply functions somehow, maybe that should do some strategy? So I would refactor it to something like:     public function applyFor(Order $order): void    {        $this->applyPromoCodeStrategy->applyForOrder($this, $order, $this->usageRestrictions, $this->promoCodeAppliesCollection)    }But I dont like that I am passing there a) four parameters, b) That strategy now does something with state of promoCodeAppliesCollection property without PromoCode knowing. It is somehow weird that PromoCode answers questions like countOrdersWithUseByUser or canBeUniqueForUser etc. Just to fillfull questions of some specific restrictions in UsageRestrictions. I would need to make some mutable object inside PromoCode entity (with those collections with applies and usages) that would not have any id, and would handle all those things around using and checking restrictions separately, but I didn't see something like this anywhere.What approaches I can use to improve this design? Or can you name some design smell with possible solutions here? 
How to split responsibilities of my entity
design patterns;object oriented design;domain driven design;solid
Ok, so it's not rocket science as I thought. The solution is to just introduce new entity (PromoCodeUsage) that is hidden in PromoCode, is it's implementation detail and taking care for responsibility of how promo code is used and applied :). So now it looks nice and clean and shiny:<?php declare(strict_types = 1);class PromoCode{    /** @var PromoCodeId */    private $id;    /** @var Details */    private $details;    /** @var Benefit */    private $benefit;    /** @var PromoCodeUsage */    private $promoCodeUsage;    public function __construct(PromoCodeId $id, Details $details, Benefit $benefit, ?UsageRestrictions $usageRestrictions = null)    {        $this->id             = $id;        $this->details        = $details;        $this->benefit        = $benefit;        $this->promoCodeUsage = new PromoCodeUsage($usageRestrictions);    }    public function getId(): PromoCodeId    {        return $this->id;    }    public function getBenefit(): Benefit    {        return $this->benefit;    }    public function getCode(): Code    {        return $this->details->getCode();    }    public function hasCode($code)    {        return $this->details->getCode()->getValue() === $code;    }    public function applyFor(Order $order): void    {        $this->promoCodeUsage->applyFor($order);    }    public function useFor(Order $order): void    {        $this->promoCodeUsage->useFor($order);    }    public function countAppliesForOrder(OrderId $orderId): int    {        return $this->promoCodeUsage->countAppliesForOrder($orderId);    }    public function countOrdersWithUseByUser(UserId $userId): int    {        return $this->promoCodeUsage->countOrdersWithUseByUser($userId);    }}