Есть 2 сущности, User и Product. User реализует интерфейс BuyerInterface. PHP: interface BuyerInterface { public function canBuy(Product $product): bool; } Тут понятно. Вопрос в следующем: где правильнее описывать метод buy()? У меня 2 варианта приходят на ум: 1. Описать метод buy() в модели: PHP: class User extends Model implements BuyerInterface { public function canBuy(Product $product): bool { return $product->cost <= $this->money; } public function buy(Product $product) { if ($this->canBuy($product)) { //...do something } else { throw new NotEnoughMoneyException(); } } } // controller try { $user->buy($product); } catch(NotEnoughtMoneyException $ex) { //...do something } И второй вариант - создать сервис, в котором будет метод: PHP: class TradeService { public function buy(BuyerInterface $user, Product $product) { if ($user->canBuy($product)) { //...покупка } else { throw new NotEnoughMoneyException(); } } } // controller try { $tradeService->buy($user, $product); } catch(NotEnoughMoneyException $ex) { //...do something } Как будет лучше с вашей точки зрения? Я склоняюсь к сервису, т.к. позволяет избежать дубляжа кода метода buy() на случай если появится ещё одна сущность, реализующая контракт BuyerInterface. Да и к тому же метод buy() это не прерогатива сущности, от неё нам нужен только контракт на покупку.
По текущей реализации метод бай лишний в абстракции трейд-сервис. Если действительно сущностей реализующих интерфейс байера неопределенное число и объект юзер не только и не обязательно будет в их числе, то да - вынос метода в абстракцию оправдан но я бы реализовал метод в трейте если нет других уточнений