Где осуществлять валидацию пользовательского ввода в архитектуре MVC?
=======================================================================

 Всем привет. Пишу настольную программу на Java c гуи на JavaFX. Решил изучить шаблоны ООП и, в частности, подход MVC. Данные сохраняются в файловую реляционную бд. Валидация данных в плане соответствия реляционной модели - понятно, в классе модели. А где нужно, "по уму", закладывать проверки, что в числовое поле введено число? Где фильтруются sql-инъекции, HTML-разметку и прочие грязные хаки?  

В гугле куча примеров ASP.NET MVC или веб-приложения, на пхп, например. Там тоже все мне не очень ясно. В случае, если у нас статическая HTML страница, то все контроллеры и модели - на стороне сервера, а что в случае, если у нас на фронтенде много JS кода с логикой? Как распределена ответственность между частями системы в рамках архитектуры MVC в случае с толстым клиентом? 

> А где нужно, "по уму", закладывать проверки, что в числовое поле введено число? Где фильтруются sql-инъекции, HTML-разметку и прочие грязные хаки?

  

По идее, все вышеперечисленное относится к бизнес-правилам и, соответственно, лежит в моделях. Т.е. контроллер, получив некий ввод от пользователя, отдает эти данные модели (мол, "проверь" или "попытайся сохранить"), а модель либо говорит, что все хорошо, либо возвращает список ошибок, не дающих данные обработать.   
  

> Как распределена ответственность между частями системы в рамках архитектуры MVC в случае с толстым клиентом?

  

Толстый JS-клиент можно сам по себе рассматривать как MV*-приложение. Серверная часть в этом случае становится моделью. При этом часть функций модели (скажем, некая базовая валидация) может быть реализована и на стороне JS; в конце концов, никто не говорит, что модель не может состоять из нескольких слоев. 

 Давайте размышлять что такое валидация и зачем она нам нужна:  
  

Нам нужно проверять, не нарушаются ли пред-условия для действий или инварианты состояний. Например - пользователь всегда должен иметь email - такие правила можно запихивать на уровне конструктора класса пользователя. Тогда у нас не будет физически возможности "создать" пользователя не указав email. Что бы убедиться что переданная строка email - мы можем опять же завернуть "примитив" в свой тип Email, таким образов сделав подтип строк, который гарантирует нам, что любая штука относящаяся к этому типу будет являться email-ом.  
  

Такие правила как "у пользователя должен быть уникальный email" могут быть проверены только там, где достаточно информации. Например - некий репозиторий пользователей, или DAO. При попытке "сохранить" мы уже делаем проверку. Или мы можем делать это просто повесив ограничение на уникальность на уровне базы данных. Это уже не столь важно.  
  

Различие тут в том, что все это будет вызывать ошибки. То есть мы не сможем вогнать систему в "невалидное состояние" но пользователь не сможет получить список ошибок, которые он совершил вводя какие-то данные. Все что он получит - отдельные ошибки.  
  

То есть если смотреть с позиции пользователя, помимо валидации бизнес правил, нам нужно так же производить валидацию входящих данных. Валидацию данных запроса, на уровне контроллера. Тогда у нас есть все входящие данные и каждый отдельный экшен будет знать что надо проверять. И тогда у нас будет возможность проверить все правила и выдать один список всех проблем с входящими данными.  
  

В простых случаях, когда данные из запроса втупую мэпятся на "модель данных", мы можем проверять уже результат. Но в случае с логикой сложнее CRUD это уже не выйдет. Точнее это уже чуть сложнее. К примеру мы передали несуществующий айдишник связанной сущности. Мы запросим данные, получим нул, и валидатор выдаст нам что-то вроде "Извините, но вот эта штука обязательна к заполнению". А пользователь такой "чтааа? Я ж заполнил!" Вот если бы ему приходило сообщение мол "Выбранная вами штука не существует" - тогда ладно, но подавляющее большинство так не запаривается.  
  

Словом... тут нужно исходить не из "где это делается в MVC" а из "а кому это нужно и какие цели вы приследуете".  
  

Если что, MVC это не все приложение, это лишь способ разделить ответственность. Приложение ничего не должно знать о UI и все. То есть валидация входящих данных вполне может лежать на уровне контроллера поскольку это ему нужно сформировать список ошибок и запихнуть их к полям формы. С другой стороны, часть валидации может происходить вообще вне "MVC", где-то внутри, на уровне модели предметной области.  
  

Нельзя из букв "M", "V" и "C" составить слово вечность. Именно по этой причине MVC как подход для организации GUI уже лет 20 как не используется в чистом виде.