Да уж, есть есть гораздо более важные знания для разработчика. Например, как правильно реализовать equals() и hashCode() для persistence entities — сколько народу на собеседованиях ловятся на том, что думают, раз Блока прочитали, значит все про Java знают.
Размеры структур данных, может быть, имеют значение в случае разработки под эмбеддед системы, но даже там далеко не во всех случаях — уж Андроид с устройствами с 256мб памяти и выше к Эмбеддед относится лишь отчасти.
Сама идея использовать dependentObservable возникла в голове тут же, но то наверное уже опыт работы с библиотекой сказывается.
Вообще жаль, что я к вам на сходку не попал — пришлось пропустить по семейным обстоятельствам, — а так вообще приятно, что в нашем городе еще кто-то Нокаут использует.
Ай-ай-яй, Romanych, нехорошо обманывать! — подумал я, прочитав о том, что-де, Knockout рассчитывает зависимость для dependentObservable только в первый раз. Потом, смотрю, исправились.
Треккинг зависимостей на каждом шаге нужен для случаев, когда в зависимости от значений каких-то свойств список задействованных свойств может быть разным.
Допустим, изначально клиент указал в качестве страны проживания Украину. Тогда location стал бы зависить только от полей city и country.
Т.е. при изменении значения одного из этих observables вызывались бы все listeners, привязанные к свойству location.
Затем пользователь сменил страну на США. Понятное дело, что location у него изменился, но вот обработчики событий, привязанных к location продолжили срабатывать только при изменении страны и города — изменения штата игнорировались полностью.
Понятное дело, при собственно вычислении значения location() штат использовался — но все дело в событиях и обработчиках.
Именно поэтому Knockout вынужден треккить зависимости при каждом вычислении — так список базовых свойств может динамически расширяться.
Мне кажется, что как и с Нокаутом, нужно искать тонкую грань между «определим правила поведения для элементов» и «OMG!!! JavaScript in my HTML!!1»
С другой стороны, Аджилити позиционируется как библиотека для небольших приложений. Так что многие подходы, которые совершенно недопустимы для средних и больших проектов, тут вполне прокатят.
Да, я потому и писал о том, что сложные выражения лучше выводить из выражений байндингов в отдельные dependentObservable — а то оглянуться не успеешь, как окажется в коде каша а ля «Привет, 99!»
Для себя определил, что это будет либо имя свойства в модели, либо простое сравнение свойства. Если условие становится сложным — создаю для него зависимое свойство.
При таком подходе можно мысленно считать, что значения data-bind-атрибутов — не код, а правила.
Ну и конечно, не забываем о том, что атрибуты можно расставить потом из JavaScript-кода, тогда ваш HTML останется чистым. Ссылка на реализацию подхода в статье.
Как я уже сказал, у нас тоже много кода, непосредственно с Нокаутом не связанного, но когда дело касается UI, Нокаут пока обычно работает на нас. Всегда есть два варианта:
Либо DOM под нашим контролем — тогда мы используем байндинги. Это тот случай, на который Knockout и был рассчитан.
Либо DOM создается каким-то третьим компонентом. Тогда задача заключается в привязке его к ViewModel через subscribe. При этом основные сложности возникают всегда с массивами. Если данные одиночные, то дело ограничивается тремя строчками кода, что в общем-то тоже не напряжно.
Не скажите. В JSON.stringify подазумевается, что если у объекта есть метод .toJSON(), то следует для сериализации использовать его. И в нативной реализации, и в json2.js такой метод определяется для прототипа Date [1]:
Кроме того, при десериализации в качестве второго параметра можно передать функцию-трансформер, которая может преобразовывать элементы json-объекта. В комментариях к методу как раз и указан пример правильной обработки дат:
Так что, хотя с точки зрения JSON как формата данных дат не существует, с точки зрения JSON как api браузеров даты есть. Я считаю, что это не проблема JSON, а проблема Knockout.
[1] Да-да, Дуг Крокфорд тоже переопределяет прототипы!
Решение не добавлять поддержку Flash могло быть как экономическим, так и политическим. Компании Adobe выгодно, чтобы флэш-плеер был доступен для как можно большего количества платформ. Тем более, что с недавнего времени новые версии плагина портируются с десктопов на мобильные ОС. Раньше на мобильниках использовался FlashLite — отдельный форк Flash. Теперь же практически везде используется десктопный аналог. Т.е. в Adobe провели огромную работу над тем, чтобы сделать код плеера максимально переносимым. Так что перенести его еще на одну платформу — не такая уж и большая техническая задача. В Nokia вполне могли бы такое себе позволить.
Другое дело, что они могли бы решить не портировать плеер по политическим и маркетинговым причинам. Самая популярная и самая передовая с точки зрения аналитиков рынка платформа — iOS — отказалась от флеша, выставив это решение как шаг вперед, как отказ от старых технологий, отживших свой век, в пользу передового HTML5. Возможно, Нокия последовала их примеру, чтобы показать, что, мол, они тоже смотрят в будущее. При этом вроде бы как получается, что Нокия идет одной дорогой с Эппл к светлому будущему, а остальные Андроиды и Блекберри сидят в хвосте прогресса.
Другое дело, что Adobe смогли отвоевать себе место под солнцем в умах разработчиков и потребителей, и если год назад подобная реторика могла сработать, то теперь никто не считает, что «отказ от Флеша = прогресс». В общем, есть подозрение, что отдел разработки Нокия зажал денег на флеш, а отдел маркетинга опоздал на год со своей рекламной компанией.
Впрочем, «опоздать на год» — это для Нокии типично. Жаль компанию.
Ваш пример с кастом на самом деле надуманный. Каст обходится в 99% случаев с помощью параметризированной типизации. А в тот момент, когда параметризированные типы не «срабатывают», надо просто внимательно посмотреть на то, как мы пытаемся их применять. Generics — относительно новое понятие для мейнстрим-разработчиков. Я сам отлично помню, как путался с ними лет пять назад. Сегодня же единственные случаи когда мне приходится использовать cast — это работа со старыми или плохо адаптированными к generics библиотеками.
Самый возмутительный пример: в JPA метод getResultsList() объекта Query возвращает нетипизированный список. Во многих проектах утилитарная функция его приведения — единственное место, где я реально использую cast.
Размеры структур данных, может быть, имеют значение в случае разработки под эмбеддед системы, но даже там далеко не во всех случаях — уж Андроид с устройствами с 256мб памяти и выше к Эмбеддед относится лишь отчасти.
Вообще жаль, что я к вам на сходку не попал — пришлось пропустить по семейным обстоятельствам, — а так вообще приятно, что в нашем городе еще кто-то Нокаут использует.
Треккинг зависимостей на каждом шаге нужен для случаев, когда в зависимости от значений каких-то свойств список задействованных свойств может быть разным.
Например
viewModel.location = ko.dependentObservable(function () {
if (this.country() === "United States") {
return this.city() + ', ' + this.state();
} else {
return this.city() + ', ' + this.country();
}
}, viewModel);
Допустим, изначально клиент указал в качестве страны проживания Украину. Тогда location стал бы зависить только от полей city и country.
Т.е. при изменении значения одного из этих observables вызывались бы все listeners, привязанные к свойству location.
Затем пользователь сменил страну на США. Понятное дело, что location у него изменился, но вот обработчики событий, привязанных к location продолжили срабатывать только при изменении страны и города — изменения штата игнорировались полностью.
Понятное дело, при собственно вычислении значения location() штат использовался — но все дело в событиях и обработчиках.
Именно поэтому Knockout вынужден треккить зависимости при каждом вычислении — так список базовых свойств может динамически расширяться.
С другой стороны, Аджилити позиционируется как библиотека для небольших приложений. Так что многие подходы, которые совершенно недопустимы для средних и больших проектов, тут вполне прокатят.
Для себя определил, что это будет либо имя свойства в модели, либо простое сравнение свойства. Если условие становится сложным — создаю для него зависимое свойство.
При таком подходе можно мысленно считать, что значения data-bind-атрибутов — не код, а правила.
Ну и конечно, не забываем о том, что атрибуты можно расставить потом из JavaScript-кода, тогда ваш HTML останется чистым. Ссылка на реализацию подхода в статье.
Либо DOM под нашим контролем — тогда мы используем байндинги. Это тот случай, на который Knockout и был рассчитан.
Либо DOM создается каким-то третьим компонентом. Тогда задача заключается в привязке его к ViewModel через subscribe. При этом основные сложности возникают всегда с массивами. Если данные одиночные, то дело ограничивается тремя строчками кода, что в общем-то тоже не напряжно.
github.com/douglascrockford/JSON-js/blob/master/json2.js#L175
Кроме того, при десериализации в качестве второго параметра можно передать функцию-трансформер, которая может преобразовывать элементы json-объекта. В комментариях к методу как раз и указан пример правильной обработки дат:
github.com/douglascrockford/JSON-js/blob/master/json2.js#L103
Так что, хотя с точки зрения JSON как формата данных дат не существует, с точки зрения JSON как api браузеров даты есть. Я считаю, что это не проблема JSON, а проблема Knockout.
[1] Да-да, Дуг Крокфорд тоже переопределяет прототипы!
Другое дело, что они могли бы решить не портировать плеер по политическим и маркетинговым причинам. Самая популярная и самая передовая с точки зрения аналитиков рынка платформа — iOS — отказалась от флеша, выставив это решение как шаг вперед, как отказ от старых технологий, отживших свой век, в пользу передового HTML5. Возможно, Нокия последовала их примеру, чтобы показать, что, мол, они тоже смотрят в будущее. При этом вроде бы как получается, что Нокия идет одной дорогой с Эппл к светлому будущему, а остальные Андроиды и Блекберри сидят в хвосте прогресса.
Другое дело, что Adobe смогли отвоевать себе место под солнцем в умах разработчиков и потребителей, и если год назад подобная реторика могла сработать, то теперь никто не считает, что «отказ от Флеша = прогресс». В общем, есть подозрение, что отдел разработки Нокия зажал денег на флеш, а отдел маркетинга опоздал на год со своей рекламной компанией.
Впрочем, «опоздать на год» — это для Нокии типично. Жаль компанию.
Самый возмутительный пример: в JPA метод getResultsList() объекта Query возвращает нетипизированный список. Во многих проектах утилитарная функция его приведения — единственное место, где я реально использую cast.