> каждый метод должен быть ответственен за одно действие
Не надо понимать все так буквально. Не стоит к примеру подключаться к базе, выбирать инфу, закачивать обратно результаты и сливать инфу в лог одной большой простыней в одной функции. Но это не значит, что каждую простейшую операцию (такую как присваивание) нужно выносить в отдельный метод.
> а в нашем случае исключение кажется не совсем уместным
Исключение говорит «я не могу выполнить команду», в данном случае не допускаем некорректный ввод. Не надо боятся и экономить на исключениях, это удобный механизм (вплоть до таких задач как остановить map(), но это уже вопрос вкуса). Не важно как глубоко «вложен» вызов до вашей функции/свойства, вы на самом деле этого не знаете и не можете знать.
Да, ваш сеттер должен проверять ввод и присваивать значение, если оно съедобно, иначе генерить исключение.