Top.Mail.Ru
gaperton, posts by tag: javascript - LiveJournal — LiveJournal
? ?
November 2016   01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
Че-та сюда написать забыл.

Есть набор весьма неприятных проблем, которые возникают в JS в случае, если слой данных SPA действительно сложен. Знаете, например, как на раз делается memory leak в JavaScript? Для мемори лика в языке с GC нам нужны две вещи. Синглтон, и подписка на события. И иногда, утечки добиться настолько легко, что это выглядит как фокус. Я объясню на примере BackboneJS.

Пусть у нас есть глобальная коллекция-синглон каких-то объектов - неважно каких, скажем, users. И где-то на одной из страничек нашего SPA мы выбираем юзеров из списка, и выбранные элементы лежат в другой коллекции. Временной. Которая живет столько же, сколько живет страница (пусть у нас SPA состоит из разных "страниц", которые он переключает меняя рауты).

Ну все, у вас уже утечка памяти. Откуда она берется? Коллекция в Бэкбон подписывается на событие change от своих элементов. Подписка на событие на самом деле означает, что объект, который источник события, держит обратную ссылку на получателя. Чтобы его уведомлять.

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

Ну конечно, если при смене страницы, которая ее создала (в случае SPA это не настоящее закрытие страницы, а лишь видимость, с точки зрения браузера страница одна), не удалить из всех этих коллекций все элементы, лежащие в синглоне. То есть, если у вас нет деструктора - у вас утечка памяти. И не важно, что у нас GC. Добро пожаловать в увлекательный мир, в котором живут программисты на С++.

Бэкбон - это был просто пример. Механизм этой проблемы таков, что ему все равно, бэкбон у вас или не бэкбон.

Так вот. Не знаю, как вы, но не хочу обратно в увлекательный мир С++, частью которого я уже был примерно 6 лет. Поэтому, NestedTypes 2.0 RC, который мы в Volicon/Verizon сейчас готовим к выпуску, и который сейчас лежит в основе наших приложений для мониторинга потоковых видео-трансляций, управляет памятью полностью автоматически. При условии, что вы отличаете агрегацию от ассоциации, и напишете об этом в декларации атрибута модели.

А вот о том, что такое агрегация в ОО - вот вам статья. С веселыми картинками и доступными примерами.

Статья с веселыми картинками

Image

cartoon

Введение в NestedTypes

Posted on 2016.08.07 at 01:51
Tags: , ,
React ValueLinks, это конечно, хорошо, но пришло время рассказать о нашей основной технологии, которая лежит в основе продуктов Volicon/Verizon.

https://medium.com/@gaperton/introduction-to-nestedtypes-data-framework-69aff986287e#.nn1a3qsc7

Это универсальная технология управления состоянием приложения. Динамическая сериализуемая система типов для JS.

Мы используем ее в сочетании вот с этим:
https://github.com/Volicon/NestedReact

Которое замещает стандартный React State нашими моделями, и мы получаем сквозную технику управления состоянием. С двухсторонним databinding, естественно - для этого используются наши линки, о которых я писал раньше.

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


cartoon

TypeScript: Static or Dynamic?

Posted on 2016.06.15 at 21:49
Tags: ,
https://medium.com/@gaperton/typescript-static-or-dynamic-64bceb50b93e#.mbkvfp8hh

Про TypeScript, и немного про теорию языков программирования вообще.

В связи с ростом популярности TypeScript, оживились флеймы static vs dynamic languages. Стороны опять точат копья.

А дело в том, что война окончена. В статье я, взрывая мозг примерами, популярно объясняю, что такое soft type system. На примере TypeScript. Ну и заодно делая небольшой экскурс в терминологию и понятия теории языков программирования.

Во-первых, он таки в React есть. Называется value link. Это такой дизайн паттерн. И не смотря на то, что Фейсбук убирает свою кривую реализацию оного из React, он не может вам запретить его использовать.

Понимаем, что это такое, и учимся делать формы на React просто и приятно.

https://medium.com/@gaperton/managing-state-and-forms-with-react-part-1-12eacb647112#.m4awqrpf2

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

Учимся делать валидацию форм красиво, без традиционной для таких случаев боли:

https://medium.com/@gaperton/react-forms-with-value-links-part-2-validation-9d1ba78f8e49#.nbf6s3zee

Ну и в третьих. Самое интересное в этом паттерне вовсе не тот очевидный факт, что он устраняет ненужные коллбэки. А то, что он позволяет полностью отделить (и инкапсулировать) способ, которым выполняется data binding, как от слоя view, так и от слоя данных. Чего вообще ни один из популярных фреймворков не может.

Что, например, позволяет нам легко и непринужденно работать со сложным состоянием в React State, без какой-либо черной магии и кучи сторонних библиотек.

Учимся работать со сложным состоянием:

https://medium.com/@gaperton/state-and-forms-in-react-part-3-handling-the-complex-state-acf369244d37#.9f9rp5mwi

Помимо того, что это просто красиво - эта техника сокращает объем кода в JSX примерно вдвое.

https://medium.com/@gaperton/software-managing-the-complexity-caff5c4964cf#.3zdeyc03t

Такие дела.


Кому-то могло показаться после прочтении предыдущей статьи, что мне "просто нравится бэкбон", или что я считаю его лучшей в мире технологией. Это не так. Мы начали с backbone по двум причинам: (1) многие с него начинают, и (2) это, пожалуй, минимально возможный фреймворк для браузерных приложений.

Так как мы приверженцы "бритвы Оккама" - сравниваться мы будем именно с ним, это как точка ноля. Теперь мы разберемся, с какими именно сложностями сталкиваются люди, использующие Backbone, и умеющие готовить его хорошо. Эти сложности однозначно надо исправлять, и по этим причинам можно выбрать другой фреймворк. А вот то, что в минимально возможном Backbone сложностей не вызывает - для этого нужна очень хорошая аргументация, чтобы это исправлять.

Вообще-то это черновик, написанный в один проход. Но мне сегодня влом вычитывать.

more...Collapse )


Image

4. BackboneJS.

Posted on 2015.07.10 at 16:50
Tags: , ,
Допустим, у нас есть группа разработчиков на PHP, которые знают чуть чуть JS и jQuery. Что самое простое мы можем сделать, чтобы начали писать браузерное приложение, и были продуктивны немедленно?

Мы можем попробовать использовать тот же принцип, и те же архитектурны правила, к которым они привыкли в PHP. У них были шаблоны с встроенным PHP? Отлично, мы будем использовать такие же шаблоны со встроенным JS, которые будут разворачиваться в браузере. Они использовали jQuery? Отлично, мы сохраним jQuery.

Нам остается задать этому какую-то структуру. Элемент UI - это будет объект View с присоединенным DOM-элементом, и методом 'render', который должен разворачивать шаблон в присоединенный элемент. Помимо этого, View должен уметь перехватывать события UI, и вызывать свои методы.

Помимо этого, нелишне добавить к этому простые средства для работы с REST API. Класс для кусочка JSON, который умеет создаваться/читаться/сохраняться/удаляться (CRUD) в каком-нибудь стандартном варианте REST. Назовем его Model. Раз у нас REST, то надо еще уметь получать их список. Значит, нужен еще Collection.

У нас сейчас получилось что? Правильно, самый популярный фреймворк для разработки в браузере - backbonejs (http://backbonejs.org), который, в сочетании с модульной системой позволяет из говна и палок собрать браузерное приложение.

читать дальшеCollapse )


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

К счастью, основной критерий "хорошести" или "плохости" архитектуры очень простой. Коль скоро архитектура - это правила проектирования, то в первую очередь эти правила должны выполнять свою главную функцию - помогать проектировать:


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


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


FYI - есть два основных типа "рекурсивного паттерна".

Первый - "слои". Суть его в том, что система организована в "слои сверху вниз", таким образом, что верхний знает про нижние, а нижние про верхние ничего не знают. Слои отделены друг от друга строгим API, а за этим API вполне может царить Адъ. Ну и что.

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

Второй - "иерархическая декомпозиция". Его суть в том, что сложный модуль состоит из более мелких, они - еще из более мелких, и т. д., таким образом, образуя "дерево". Все модуля отделены API.

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

В реальной системе они всегда встречаются в сочетании. Например, если есть какой-то фрагмент используется в двух "деревьях" сразу - это означает, что он принадлежит "нижнему слою". Явно отделять слои, и наделять их смыслом - критически важно для архитектуры. Задавая осмысленные слои, с внятными критериями принадлежности им, вы задаете правила.


Надо отметить, что у "голой" браузерной платформы с этим исходно большие проблемы. Для описания UI требется целый трех языка: HTML, CSS, и JavaScript. И каждый более мелкий кусочек должен каким-то образом включать в себя все три. Но все, что может дать нам голый браузер - это один файл HTML, включающий в себя много файлов JS и CSS. А из JS файла сказать, что ему нужен другой JS файл нельзя вообще.

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

Хорошая новость в том, что на JS модули есть открытая публичная спецификация CommonJS/Modules. Именно с такими модулями работает серверный JavaScript, например - nodejs.

Выглядит это так. В каждом файлике .js пишется что-то вот такое:
    var iamimporting = require( 'path/to/js/file' );
    ...
    module.exports = iamexporting;


В node это работает прекрасно, потому, что загрузка модуля с локального диска быстра, и может происходить синхронно. Чтобы это работало в браузере, модуль потребует дополнительной обработки (сборки). Например, мы можем собрать все модули, которые надо загрузить, в один большой файл, и включить его один раз тегом script.

Именно так работают browserify и webpack. При этом, (1) у нас в проекте появляется шаг сборки, и (2) возникает куча нюансов в случае, если приложение очень большое, и мы не хотим грузить все сразу. Мы хотим сразу загрузить необходимый минимум, а далее подгружать то, что нужно, по необходимости.

Это можно сделать, разбив приложение на крупные куски (единицы загрузки), и собрать эти куски
раздельно (по сути очень похоже на DLL). Это особенно удобно делается в webpack.

Или же, можно придумать что-нибудь еще. Это что-нибудь еще называется CommonJS/AMD (Asynchronous Module Definition), позволяет грузить модули без сборки, и в тот момент, когда они действительно нужны. Выглядит это так:

    define( [ 'path/to/js/file', ... ], function( iamimporting, ...){

        return iamexporting;
    });


И есть много загрузчиков, которые позволяют грузить такие модули. Самым популярным из них является requirejs.

Но у этого модуля есть недостаток, который сразу бросается в глаза. Им невозможно пользоваться. Поэтому, помучавшись несколько лет, разработчики придумали формат асинхронного модуля "Simplified CommonJS Wrapper", который допускает асинхронную загрузку, но выглядит по человечески:

     define( function( require, exports, module ){
        var iamimporting = require( 'path/to/js/file' );
        ...
        module.exports = iamexporting;
    });


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

Глядя на это, возникает простая идея. Раз импорт модуля - это не часть языка, и все равно делается неким фреймворком, может ли он быть чуть поумнее, и загрузить прочие нужные нам ресурсы - html-шаблоны, css?

Конечно же может. Например, в requirejs это будет выглядеть так:

    define( function( require, exports, module ){
        require( 'css!./widget');
        var template = require( 'ejs!./widget' );
        ...
        module.exports = mywidget;
    });


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

Что касается директивы import из ES6, я не думаю, что когда она будет поддерживаться браузерами, она быстро вытеснит модули CommonJS. Во-первых, синтаксис CommonJS совсем не плох, и никакого выигрыша сама по себе замена 'require' на 'import' не даст. Во-вторых, возможность тонко контролировать процесс загрузки, и выполнять преобразования над загружаемыми объектами - это очень большое преимущество для браузерных приложений. Вряд-ли от него кто-то просто так откажется.

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

Но уверяю вас, система сборки и загрузки модулей - это совсем не то острие, которое изменит
всю игру.

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

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

SPA (Single-Page Application) весьма сильно изменили архитектуру веб-приложений. Если говорить кратко - архитектура SPA гораздо проще традиционных, и по характеру ограничений практически ничем не отличается от традиционных клиент-серверных приложений. С поправками на веб-технологии, конечно. Остановимся поподробнее на принципиальных возможностях и ограничениях современных веб-платформ - что поменялось с архитектурной точки зрения.
Read more...Collapse )


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




Архитектура* - это набор формальных и неформальных *правил*, руководствуясь которыми люди проектируют систему.


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


  • Мы будем стараться использовать для обозначения нашего понимания термин "Common Design Principles".

  • Постараемся разобраться в определении, и как оно соотносится с фреймворками и структурами. Увидете, как только вы начнете думать об архитектуре как о правилах много встанет на свои места.

Read more...Collapse )


Расскажу, пожалуй, про старую тему - разработку одностраничных JS-приложений. С тех пор, как я послежний раз об этом писал, прошло много времени - наверное, года 3. И с тех пор много чего изменилось. Появилось множество разных JS фреймворков, в моду вошел two-way databinding.

Однако, мэйнстримом (примерно 40% применений) на данный момент является Backbone.js, работающий в связке с jQuery и Underscore.js. Причиной этого, возможно, является его простота. Backbone прост в том смысле, что ему достаточно легко обучить команду, собирающуюся писать одностраничное приложение, и не имеющую в этом опыта. Это безусловный плюс backbone (как и его популярность), однако, его минусом является то, что он слишком прост. То есть, на голом backbone не так просто сделать что-то, кроме совсем простого.

Я расскажу про проблемы backbone, вытекающие из его простоты, и покажу, как их можно решить. Проблемы уйдут. Простота останется.

Read more...Collapse )


Previous 10  
Image