Программирую давно. Разбираю Kohana и Laravel по косточкам. Хорошо ориентируюсь в движках, но до сих пор не могу сформулировать для себя некие постулаты, скажем так, относительно того, каким данным я могу доверять при создании методов в классах, каким нет, что я должен проверять, что нет.
К примеру. В Кохане есть файл настроек для БД. Файл возвращает массив (ключ => значение) в котором среди прочего указывается собственно имя БД. Предполагается, что программист впишет в этот член строку с названием БД. Но! К примеру, мы вписываем туда массив. Ну вот так, массив и все.
Запускаем скриптик, и когда дело доходит до запросов к БД становится ясно, что в настройках содержится не корректное значение, но проявляется глубоко в движке, непосредственно когда выполняется функция mysql_select_db(). Т.е. разработчик Коханы взял файл настроек, разбил его по составляющим и погнал дальше, не проверив какие значения содержатся в массиве. И когда дело дошло до команды выбора БД наш PHP выбросил ошибку.
Хорошо, если пример такой. А ведь бывают всякие хитрые случаи. Не проверишь сейчас что-то, это может вылезти дальше где-то каким-то боком, как-то не очевидно.
Да, я могу проверять сегодня все и вся, но в том же Ларавел проверок очень мало. Если я буду писать классы с тотальной проверкой, они будут похожи на белых ворон среди классов других программистов, которые не озаботились проверкой, но зато имеют чистый код.
Мой принцип – такие вещи должны проверяться функциональными тестами приложения, т.е. это же не входые данные приложения, зачем городить на них проверки. А подобные ошибки программистов должны всплывать именно на этапе автоматического тестирования программы.
возможно в будущем будет введен тайп-хинтинг для скаляров.
Есть отдельный компонент Symfony/config, который отвечает за валидацию настроек. То есть каждый компонент описывает все варианты настроек которые он хочет получить, какой формат данных допустим, значения по умолчанию и т.д. Валидацией же всего этого и сборкой занимается отдельный компонент. Возможно по этой причине так мало проверок в коде Laravel, ибо все эти проверки были сделаны на более ранних этапах.
По сути в фреймворках использующих Dependency Injection подход с отдельным компонентом для валидации параметров будет самым удобным. Вся логика по проверке и весь бойлерплейт код уходят, а код самого компонента остается чистым. Таким образом необходимость проверять входные данные остается только для публичных методов, и то в некоторых случаях этим можно пренебречь.
Вот прозвучало: ответственность за настройки лежит на программисте. Ок, а еще какие принципы есть? Мне как-то не хватает вот этих соображений, т.е. указаний, что бы я мог понять нужно мне проверять эти данные или нет?
@lihtenshtein, я обновил свой ответ. Ответственность действительно лежит на программисте, но для понижения возможной ошибки можно применять отдельные компоненты, которые будут подготавливать все необходимые настройки необходимые для инициализации компонентов. В этом случае вам нужно описать только что вы хотите получить, а компонент все сам провалидирует. Причем это будет вне компонента и код будет оставаться чистым. Если же пользователь решил использовать ваш класс отдельно, это его задача валидировать параметры. Либо можно сделать отдельный объект конфигураций который будет валидировать параметры и передавать уже его.
Ух, что-то пальцы начали заплетаться. Словом...
валидация параметров для инициализации - задача пользователя вашего класса. Для облегчения этой задачи существуют готовые компоненты, которые исходя из описания сами будут проводить проверку. Если пользователь вашего класса решил не использовать подобный компонет, вся ответственность переходит на него.
Но это касается только инициализации, так как по хорошему пользователь должен использовать Depencency Injection Container. А вот в публичных методах API валидацию данных стоит делать что бы не допускать ошибок в работе компонента. В противном случае кидать InvalidArgumentException.
@Fesor Ок. Я понял, все доступно написано. Но вопрос не только в том какие данные проверять в файлах настройки, но и в целом, по ходу программирования. Например, в одном из методов класса я обращаюсь к статическому свойству другого класса. А если этого свойства нет там, куда-то оно пропало. Мне нужно перед этим проверить его на property_exists()?
@lihtenshtein вы не должны обращаться к статическим свойствам. Вообще при работе с другими объектами вы должны завязываться только на его интерфейс и взаимодействовать только посредствам вызова методов. Это наиболее правильное решение. А проверять что переданный объект имплементит нужный интерфейс можно просто указав оный в тайпхинтинге.