Все так, о чем и речь, нет смысла делать разделение ради разделения, архитектору нужно взвесить возможное развитие проекта. К примеру, кэш вероятно придется однажды заменить с Redis на Memcached — вероятный сценарий, но вряд ли кто-то и когда-то будет значительно менять поток получения данных пользователя `user($id)` в контроллере, настолько, что придется подменять репозиторий или сервис, скорее всего смысл выносить логику в обычной жизни придется лишь тогда, когда захочется избежать повторения (скажем, если данные пользователя получаются разными действиями контроллера, нет смысла дублировать код, можно реализовать один метод `getUser`). При этом, бизнес-логика (логика домена) как правило уже значительно разделена на слои фреймворком: валидация, проверка прав доступа — это все относится к слоям логики, наиболее частые операции. Ровно так же в некоторых сценариях может понадобиться, скажем, отделить DTO, если вводимые данные отличаются от сохраняемых (из головы пример, если для удобства пользователя адрес вводится с помощью JS-плагина с дополнением адресов, на сервер попадают строка и код реестра, а в базу идет расшифрованный адрес, и тут может понадобиться сервис, что выполнит такое преобразование).