Pull to refresh
39
0
Дмитрий Смолин @dimsmol

Software Engineer

Send message
A5 Lux хорош. Легкий, компактный, очень удачный складывающий механизм — удобный и надежный.
Дешевый (~$60 на Амазоне). До него катал на Micro Suspension, который гораздо дороже, при этом тяжелый, менее удобный и убился при моем стиле езды за 3 месяца (на A5 Lux катаю больше полугода уже, полет нормальный).

В дождь самокат противопоказан — грязно и тормоз практически бесполезен (мокрое колесо скользит по металлу почти без трения).

Судя по отзывам на том же Амазоне, A5 Air прилично хуже катит из-за надувных колес и мой опыт с Micro Suspension показывает, что это важно (подвеска тоже амортизирует, отъедая от силы толчка).

На A6 жалуются, что не слишком удачные габариты, тяжеловат, менее удачная конструкция, подножка высоковата (тоже сильно влияет на удобство езды).

В общем, A5 Lux — рекомендую.

Тем не менее, это значительно проще ведения списков инвалидации.
Кроме того, полноценная проверка валидности самодостаточного токена, кажется, в принципе невозможна без обращения в базу (как иначе убедиться, что его не отозвали?).
Это всего лишь более простой способ делать такую проверку.

В том-то и фишка, что при таком подходе сами токены (как и их атрибуты) хранить не надо.


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


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


Здесь я не спорю с позицией автора, я всего лишь говорю о том, что инвалидация может быть устроена проще, чем показано в статье. Не так чтобы совсем тривиально и дешево, но все-таки проще.


Кстати, очевидный недостаток схемы, о которой я говорю – невозможность инвалидировать отдельные токены, только все разом, выданные до определенного момента времени. Так что применить ее можно будет не везде.

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

я сказал: "инвалидировать токены, не храня их (т.е. токены) в базе"
время все еще надо хранить, токены не надо


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

В Кикстартере для стилей используют линзы, выглядит примерно так:


public func cardStyle <V: UIViewProtocol> (cornerRadius radius: CGFloat = Styles.cornerRadius) -> ((V) -> V) {

  return roundedStyle(cornerRadius: radius)
    <> V.lens.layer.borderColor .~ UIColor.ksr_grey_500.cgColor
    <> V.lens.layer.borderWidth .~ 1.0
    <> V.lens.backgroundColor .~ .white
}

пример использования:


    _ = self.cardView
      |> cardStyle()
      |> dropShadowStyle()
      |> UIView.lens.layer.borderColor .~ UIColor.ksr_navy_500.cgColor

(взято отсюда и отсюда)


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


Концепция линз взята из функционального программирования, широко используется в Хаскеле (см. lens package).


На Свифте, из-за синтаксических особенностей, выглядит не так красиво, но достаточно неплохо.
Также, Хаскель позволяет генерировать код для линз автоматически (используя Template Haskell), а тут приходится писать их вручную. Но, поскольку Kickstarter для нас уже постарался, можно использовать готовые.

Есть простой способ инвалидировать токены, не храня их в базе данных. Зашиваем в токен время выдачи, при смене пароля запоминаем время смены пароля, все токены выданные раньше – не валидны. Но один запрос на получение последнего времени смены пароля, конечно, при этом останется.

кстати, хороший пример использования подобного подхода как для Android, так и для iOS – приложения Kickstarter, они открыли исходники не так давно:



примеры особенны интересны тем, что это большое приложение целиком

Прошелся по докам Elm, чтобы ответить конкретнее.
Оказывается, я забыл, насколько он игрушечный. В нем же вообще ничего толком нет.
Самый простой способ это увидеть — сравнить Elm Guide с PureScript by Example.
Из фундаментальных вещей нет Type Classes, newtype и еще много чего.
Из более прикладных STRef, Aff, operators, Generic, derive, etc.

Надо понимать, что многих вещей в Elm нет не потому, что так задумано, а потому что руки не дошли сделать, см., например, type system extensions.
С одной стороны, хорошо, что планы есть, но с другой — отставание от PureScript грандиозное.
Не уверен, что его вообще можно нагнать.

Кстати, тот факт, что в Elm до сих пор не работает нормально package manager и нет базовых элементов языка, зато втюхана поддержка GLSL, очень многое говорит о приоритетах авторов. Для кого-то, возможно, это хорошие новости, но очевидно не для всех.
«язык слабее Хаскеля» — тут не помешало бы пояснить, что вы имеете ввиду. Как по мне, так упрощение языка снизило порог вхождения и улучшило читаемость исходного кода.

Это очень наивно, полагать, что Haskell переусложнен ради самой сложности и что если от него отгрызть подмножество, то все станет лучше. Все его «сложности» появились постепенно, принося с собой весьма востребованные возможности. Если выкинуть все это и свести к этакому «functional basic», разумеется порог входа понизится, но и возможности пропадут.

Более того, использовать те возможности, что останутся, тоже станет сложнее. Ведь многие фишки языка появились как раз, чтобы упростить некоторые вещи. Никто не мешает взять PureScript или Haskell и просто не использовать то, выходит за пределы возможностей Elm. Но тогда придется либо оставаться в рамках более простых вещей, либо все станет только сложнее.

Да и язык не так уж сложен, сложно научиться его эффективно использовать — все эти монады, теория категорий, etc. Все это не часть самого языка, а то, что с его помощью можно делать. Можно все это отбросить, порог входа станет ниже, но делать что-то полезное станет сложнее.

Мне сложно привести конкретные примеры, где Elm ограничен в возможностях по сравнению с Haskell и PureScript, просто потому что последний раз я писал на нем очень давно и уже не помню, во что конкретно упирался. Навскидку, вот пример про Higher-kinded types. Либо можно посмотреть список расширений Haskell и прикинуть, чего из этого нет в Elm (скорее всего ничего). Вот тут можно почитать о них подробнее. PureScript включает некоторое подмножество этих расширений.
Правда, если вы никогда не писали на полновесном функциональном языке, то все это может выглядеть абстрактно и не очень понятно.
Давайте сначала разберемся, с какой целью вы спрашиваете.
Если у вас намечается конкретный проект и вам непременно нужен типизированный WebGL, а Elm Architecture кажется идеальной для ваших задач, то может вам как раз нужен Elm, а все остальное категорически не подходит. Я вас ни в коем случае отговаривать не буду, ваш проект, вам виднее.

Ну а если вам интересен взгляд с моей колокольни, то пожалуйста.

Я скептически отношусь к идее зафиксировать какой-то конкретный подход или архитектуру на уровне языка. Подходы меняются и это становится проблемой для обратной совместимости. Если появится более удачный подход — придется ждать изменений в языке. Если подход плохо ложится на задачу —
придется менять язык. Особенно весело, если это выяснится в середине проекта. Возможность использовать любой подход и реализовать его в виде библиотеки дает куда большую гибкость.

То же самое касается прочих встроенных вещей, типа WebGL. На Haskell то же самое реализовали бы в виде DSL, в крайнем случае с использованием Template Haskell. Для PureScript аналога Template Haskell еще нет, но вполне можно использовать WebPack для кодегенерации.

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

Есть ли реализация текущей Elm Architecture для PureScript, я не знаю. Знаю что можно сделать, было бы кому-то надо. При этом в PureScript есть свои интересные вещи. Например, Halogen позволяет компонентам иметь локальное состояние и использовать эффекты, если надо. Это очень интересные возможности для наших проектов. Интересна ли нам Elm Architecture — не уверен, надо смотреть.

О каких альтернативных подходах идёт речь и зачем их использовать?

Например, в старом Elm использовались сигналы, теперь их заменили на что-то другое. Это вполне себе альтернативный подход с точки зрения старого. Зачем его используют? Наверное, потому что он лучше.

Есть и другие подходы, разумеется. Есть тот же React, Halogen, новые появятся. Какие-то окажутся лучше. Какие-то будут лучше для каких-то конкретных случаев. Вряд ли в Elm придумали идеал, лучше которого быть уже в принципе не может.
Знаете ли, таки путаете. Я занимался оценкой применимости всех трех подходов (Elm, GHCJS, PureScript) для коммерческого проекта и пишу на PureScript прямо сейчас.

Да, PureScript близок к Haskell (за исключением не-ленивости) и по духу, и по синтаксису, и по мощности. До такой степени, что замечательную книгу PureScript by Example можно использовать для изучения некоторых концепций Haskell (они там иногда описаны понятнее, чем в книгах по самому Haskell, рекомендую). Но это не помешало в нужных местах срезать углы, чтобы генерировать более разумный/эффективный JS. Так что PureScript таки заточен на работу в JS-окружении. И очень неплохо заточен.

Поставляется он без стандартной библиотеки, то есть вообще без всего, даже Prelude нет

Вы не правы, либо ваша информация устарела. Вот PureScript Prelude, а вот и прочие пакеты, как правило они весьма высокого качества. То, что Prelude лежит в отдельном пакете, не делает ее менее стандартной, просто дает дополнительную гибкость. Если вы работали с Haskell, то знаете тамошнюю моду заменять стандартную Prelude на кастомную. В PureScript, кажется, просто учли, что люди любят так делать.

Elm же был построен вокруг реактивного программирования, с введением сигналов и адресов

Да, Elm построен вокруг определенного набора концепций и они вшиты в язык насмерть. Реализовать их на самом Elm не представляется возможным, как раз из-за «игрушечности» языка. В PureScript те же самые концепции можно реализовать самому, в виде обычной библиотеки. И много других концепций можно реализовать, которые окажется невозможно представить в Elm.

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

  • Package manager отказывается работать в Docker
  • Отсутствие нормальной поддержки приватных пакетов
  • Практически невозможно опубликовать пакет с использованием FFI (требует approve, а все кто может его делать, давно забили на это, пакеты ждут апрува по полгода и дольше)
  • Модель обработки сигналов требует проброса всех эффектов до самого корня иерархии компонент, это просто ад, когда часто нужны асинхронные вызовы
  • Практическая невозможность использовать альтернативные подходы, если их поддержка не встроена в язык
  • Elm сделан по подобию Haskell, но в нем часто не помогает ни опыт в Haskell, ни поддержка Haskell-сообщества, потому что в Elm многие вещи тупо не работают. Язык гораздо слабее, ему еще предстоит набивать свои шишки и наращивать мускулы там, где они решили отбросить что-то важное, на это уйдет много времени. Даже в Scala JS с этим лучше.

GHCJS был отброшен именно по той причине, что вы назвали — это тупо компилятор Haskell в JS, с поддержкой ленивости и всего-всего. Получаемый код выглядит ужасно, работает медленно, весит много, а про отладку даже думать страшно. Возможно, развитие WebAssembly когда-нибудь изменит это, но точно не в ближайшие годы.

У PureScript нет ни одной проблемы из приведенных выше. Более того, местами он выглядит более идиоматично, чем сам Haskell (поправлены некоторые нестыковки, которые в Haskell так просто не поправить из-за требований обратной совместимости). Работа с FFI и асинхронщиной — вообще сказка. Вызовы из JS — тоже, что важно, если у вас уже большой проект на JS и нужен постепенный переход. Большинство привычных подходов из других FP языков (Haskell, Scala) — просто работают. Очень интересно выглядит Halogen, но тут пока особо сказать нечего, надо еще испытывать на практике. Для более консервативных, есть неплохие биндинги к React, что тоже облегчает плавный переход, если он нужен. Есть прекрасная интеграция с WebPack, включающая оптимизацию сборки (выкидываются неиспользуемые функции и типы, что делает PureScript часть компактной).

Все это делает PureScript гораздо более production ready, при всем моем уважении к Elm и концепциям, которые были в нем изобретены.
Вы путаете PureScript и GHCJS.
PureScript — отдельный язык, причем гораздо более зрелый, чем Elm, но менее разрекламированный.
Elm по сравнению с PureScript выглядит «игрушечным» — хорошо решает отдельные задачи, но не очень-то универсальный.
Действительно, перепроверил – все как вы говорите.
Выглядит разумно, нужно учесть эти фишки при дальнейшем развитии jsonex.

Кстати, если в вызов reviver добавить ссылку на родительский объект и гарантировать, что для массивов тоже передается key (индекс массива), то на базе JSON5 было бы очень просто делать парсинг jsonex в JSON5-представлении. Надо будет обсудить этот вопрос с авторами, может получится договориться и о более тесной интеграции.
Зачем писать Всеобъемлющий Супер Фреймворк, если можно решить каждый вопрос в отдельности, даже если писать все 'вручную' (те же отдельные вызовы апи)?

А зачем писать операционную систему? Ведь все можно сделать вручную!

Конечно можно. Если вам кажется, что ваши задачи лучше решаются в ручной реализации – используйте ручную реализацию. Задачи бывают разные, подход должен соответствовать задаче.

Ваш клиентский код будет генерить сотни-сотни вызовов апи в секунду? зачем заморачиваться об ограничениях браузера?

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

Почему бы не добавить этот самый запрос вытаскивания друзей друзей? Это очень просто и очень явно.

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

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

Я не могу понять, а что плохого в том, что придется во время валидации интерпретировать данные согласно схеме? Давайте назовем этот процесс конвертацией из json в js-объект модели.

Вашему конвертеру нужно будет заранее знать о всех доступных форматах. Либо вам придется писать свой вариант конвертера для каждой новой системы, которая имеет свой взгляд на то, как выглядит сериализованая дата. Либо вы попытаетесь сделать его расширяемым и в какой-то мере повторите дизайн jsonex.

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

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

Что касается сложности фреймворка – движок arc предельно прост. В нем чуть более 300 строчек кода, разбитого на функции, большинство которых укладывается в десяток строк. В реализации от mayorovp кода еще меньше. Что именно вызывает у вас ощущение запредельной сложности?

Я уже не говорю о простоте использования. Если внутренности arc для вас слишком сложны (что на самом деле странно), вы можете просто пользоваться им. Он просто работает. Как работает ваш телефон или компьютер.

Вы извините, конечно. Но я вижу астронавта от архитектуры.

От вас это звучит как комплимент )

Вероятно, вам действительно не нужен jsonex. Честно говоря, всегда будет больше людей, которым он не нужен, чем тех, кому нужен. Но, если вы никогда не сталкивались с необходимостью batch запросов, вам не приходилось выставлять очередной чертов URL, по которому доступно то же самое, что по трем другим, но одним куском, вы никогда не ломали голову, как передать нестандартный тип данных, так чтобы он органично вписался в существующую систему, а не «давайте воткнем это грязным хаком, сейчас нет времени дорабатывать конвертер» – это еще не значит, что вселенная тривиальна и 64K хватит для всех. Это значит только то, что вы пока не сталкивались с более сложными ее проявлениями.

В моем случае, за те годы, что я работаю с веб, jsonex мог сэкономить как мне, так и окружающим огромное количество времени, которое можно было потратить на куда более интересные вещи, чем возня с транспортировкой данных «вручную».
Спасибо! Добавил упоминание библиотеки в статью.

P.S. В arc много всего, потому что на данном этапе он пытается быть «академичным» – позволять играть с отдельными частями, сохраняя общую простоту. Например, он на полпути к использованию Stream-интерфейса, что должно дать возможность парсинга из потока. Он позволяет подключить альтернативный код очереди выполнения, содержит несколько базовых обработчиков, включая событийные get и set, добавлена пара других заделов на будущее. Сейчас это скорее научная лаборатория, чем рабочий завод.
Я ничего не имею против схемы. Это важная и полезная практика, и jsonex вовсе не исключает ее использования, хотя и позволяет без нее обходиться, если по каким-то соображениям от нее отказались. Кроме того, при наличии схемы, он позволяет отделить валидацию от парсинга, что может быть полезно – каждый из процессов по отдельности проще в реализации и может использоваться независимо, ведь валидация бывает нужна не только для свежераспарсеных данных.

Information

Rating
Does not participate
Location
Sunnyvale, California, США
Date of birth
Registered
Activity