parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

Про $result

Maxx 09.10.2012 21:10 / 09.10.2012 21:16

Лирическое отступление. В какой то день пришла сотрудница и сказала что в таблице договоров, которые она вносит в базу у всех договоров, в том числе ранее введенных, одновременно пропали все даты. Это было странно, потому что код не трогался, на сервере проблем не наблюдалось, а сама программка работала давно и успешно. Полез ковыряться...

Проблема обнаружилась вот в таком методе (сильно упрощен), который печатает дату:
@print_date[d]

^if(!($d is date)){
	^try{
		$d[^date::create[$d]]
	}{
		$exception.handled(1)
	}
}
^if($d is date){
	$result[${d.day}.${d.month}.${d.year}]
}
На самый первый взгляд ничего в нем такого криминального вроде не нашлось, но тем не менее именно он почему то даты перестал печатать, все. Пока я искал, девушка внесла еще один договор, и все даты появились назад :)

Немного потестив я понял, что если оператор вызвать первый раз передав ей неверную дату, например '0000-00-00', то все последующие вызовы этого оператора, даже если передать нормальную дату ничего не вернут, иными словами
$d1[0000-00-00]
$d2[2012-10-10]
$d3[2012-10-12]

^print_date[$d1]
^print_date[$d2]
^print_date[$d3]
--> пусто

^print_date[$d3]
^print_date[$d1]
^print_date[$d2]
--> 12.10.2012 10.10.2012
Быстро стало понятно что дело в этом:
Каждый метод должен будет или возвращать результат через $result во всех вариантах своего выполнения или не использовать $result вовсе. Внимание, это несовместимое с предыдущей версией изменение и вам необходимо исправить ваш код.
И стало грустно.

1. это несовместимое изменение совершенно не отражено в документации, там слишком простые примеры
2. нужно хорошо понимать принцип работы парсера, чтобы видеть в вышеприведенном методе наличие второй, неявной ветви
3. это изменение, если не пересмотреть весь код (включая чужой, и которого может быть очень много) является бомбой замедленного действия, т.к. несмотря на то что каждый метод должен (обязан!) возращать результат - никакого эксепшена не случается. Работать такой метод будет "почти всегда"
4. пересмотреть весь код, включая написанный другими людьми, когда это было можно - это очень непростая задача, каким-то универсальным простым решением тут не отделаешься. Например в данном методе можно просто объявить $result[] вначале, но это нельзя сделать в общем случае, т.к. в методе может вовсе не быть $result и это порушит его работу.

Мне кажется с этим надо что-то сделать, в идеале падать с ошибкой, если result не определен для всех ветвей. Ну и в доку добавить, кто читает новости, кроме десятка старожилов?

Версия 3.4.2