Pull to refresh
442
0
Mikhail Davydov @azproduction

Frontend/Node.js JavaScript

Send message
Давно применяю такой подход к разработке (очень успешно). Такое архитектурное решение я считаю наиболее эффективным из всех, что я применял. А роль Node-ы, как аггрегатора API, более чем опревдана и уместна. Про этот подход я отчасти рассказывал на html5camp.
При переходе 0.8->0.10 была улучшена производительность модулей, связанных с вводом-выводом. Как известно I/O самая медленная операция и поэтому буст в 1700% решает больше чем, чуть более быстрая молотилка цифр — те апгрейд V8. Так же был улучшен «алгоритм работы» nextTick() — что сильно бустануло все асинхронные операции и промисы.

fs/read-stream buf size=1024: v0.10: 1106.6 v0.8: 60.597 ................... 1726.12%
fs/write-stream buf size=1024: v0.10: 59.926 v0.8: 49.822 .................... 20.28%
tls/throughput.js dur=5 type=asc size=1024: v0.10: 199.7 v0.8: 102.46 ........ 94.91%
Да, подходит. LMD использует CommonJS модули.
Нет, но можно в качестве основы взять github.com/2layer/2layer.github.io проект на Backbone+LMD с хорошим скелетом.
Код абсолютно идентичен и интерфейс объекта работы с БД одинаковый (возвращает promise) как в первом так и во втором примере.
Не вижу проблем с отладкой.
// present
app.get('/users/', function (req, res, next) {
    db.select('users')
    .then(function (users) {
        return users.toJSON();
    })
    .then(res.json, next);
});

// future
app.get('/users/', function *(req, res, next) {
    try {
        var users = yield db.select('users');
        res.json(yield users.toJSON());
    } catch (e) {
        next(e);
    }
});
Любое подключение внешней зависомости это своеобразный «контракт». И лучше, когда этот контракт явный.

use, import, require — это все способы декларации этого контракта. Кроме того, что этот statement/expression это директива интерпретатору/компилятору это еще и сигнал тому, кто читает этот код: этот модуль имеет внешние зависимости, можно использовать такие-то функции из такого-то списка, зависимости могут «намекнуть» на поведение модуля, исключают конфликты имен. Плюс мы имеем всякие плюшки вроде возможности статически анализировать модули для автокомплитов и прочих целей.

export, module.exports — это так же части этого контракта, но уже на поставку ресурсов.

import * from 'lib/dom-promise';
import * from 'lib/super-duper-abstract-module';

export class PromisedModule extends Module {
    fetch () {
        return new Promise(function () {
            // do stuff
        });
    }
}

Если удалить импорты, то появляется куча вопросов: Module и Promise — ты кто такой? Какой у него интерфейс? Где посмотреть код? Класс абстрактный? На какую спеку опирается интерфейс Promise?

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

как нужно проектировать библиотеки используя современный модульный подход в JS
Эта статья должна ответить на ваши вопросы blog.izs.me/post/48281998870/unix-philosophy-and-node-js
Это очень станно, но ваше письмо от 31 мая получено, отмечано как прочитанное, но я почему-то не ответил на него. Хотя регулярно отвечаю на все письма. Отметил его как не прочитанное и обязательно отвечу.
Я работаю с несколькими проектами одновременно каждый over 9000 SLoC.
Почему я бы не стал использовать yamd:

1) [critical] Отвутствие явного импорта
— Если модуль большой, то невозможно найти те модули, которые использует данный модуль
— Любой валидатор по умолчанию будет ругаться на использование незадекларированной в этом файле глобальной переменной в нашем случае math
— При удалении/перемещении модуля сложно найти концы
— Я бы устал искать откуда какая часть пришла

console.info(math.add(7,2));
console.info(math.multiply(7,2)); // откуда пришел math?

2) Завязка на файловую систему
— Проблемы с глубокой вложенностью модулей. Что если у нас /a/b/c/d.js?
— Файловая систему диктует имена экспорта у модулей

3) Модуль можно убить через expose
— expose ожидает синхронную декларацию, но разработчик может задекларировать такой модуль асинхронно
setTimeout(expose, 0, 42);

4) [critical] Все модули выполняются при старте, а не по требованию
5) Проблема с циклической зависимостью — это чаще всего ошибка проектирования
Функции нужно объединить в один модуль. Если никак, то можно обойтись и без tableLookup: использовать другой формат экспорта — в случае с CommonJS:
exports.steps = steps;

6) [critical] Модули не изолированы
// Этот модуль сломет все
files = null;

7) Модуль не может вернуть не объект
8) Лишний код если собираются 2+ библиотеки модулей

Посмотрите еще раз на существующие модульные системы. Я уверен, что они могут решить все ваши проблемы.

как вы разрабатываете сложные JS библиотеки
В двух проектах используется огромная общая библиотека модулей. Все модули — CоmmonJS. Проекты собирабтся на LMD. Сторонние модули транслируются в CommonJS при сборке.

PS Путь JavaScript модуля
Но не решает другую еще более злостную.
В Firefox, Safari есть подобная нерешенная проблема: bugzilla.mozilla.org/show_bug.cgi?id=705617

В обработчике beforeunload делаем синхронный XHR на сервер, который держит соединение, но никогда не отечает. Вкладка никогда не закроется сколько бы в нее ни тыкали. В Chrome эта проблема решена — при втором клике на [x] вкладка закроется.

Код примера
На самом делеле с HTML 5 Notifications API не так все просто. Сейчас существует целых 3 реализации этого API со своими багами и интерфейсами:
— Есть старая версия (webkitNotifications) в Safari 5 в которой нет обратного вызова у функции requestPermission (это ахтунг), а вместо свойства permission есть метод checkPermission(), который возвращает число-статус, а не строку.
— Есть версия в Safari 6, в которой вместо свойства permission есть функция permissionLevel(), которая уже возвращает строку.
— Есть какая-то сборка Safari или Chromium в которой Notification есть, а .prototype у него нет и, соответственно, при попытке вызова new Notification вы огребаете :)
— Есть сборка Chromium в которой при попытке вызова new Notification вкладка крашится
И наконце есть свежая сборка в которой метод cancel() переименовали в close(), а iconUrl в icon

И весь этот зоопарк гулят по просторам интернета, хотя и быстро обновляется. Ну и чтобы не огребать советую вам использовать библиотеку $.notification, которая все это чинит. Демка
LMD как и browserify основываются на CJS модулях и являются инструментами по сборке оных. browserify заточен под CJS и Node.js-way — отличная штука если нужно запустить node.js приложение в браузере.

Напомню, что в JS@DOM cвоя атмосфера: ресурсы далеко, ресурсы медленные, зачастую мы не можем грузить все ресурсы, HTTP не стабилен и каждый новый запрос может привести к ошибке. Есть еще сторонние не-CJS-модули (старые плагины к jQuery), что с ними делать? Что если приложение оптимизировано под 3 платформы(3 набора скриптов)?

LMD в отличии от browserify ближе к браузеру(браузерам и средам) и понимает его проблемы: трансформация не-CJS-модулей при сборке, текстовые файлы без пагинов, абстрактная модульная фс, группировка модулей по бандлам… и еще куча апгрейдов вроде кэша в LS и ленивой инициализации.
Согласен, спасибо, что разъяснил твой модульный подход!
base это, как я понял, непрописанный http.vanilla. Вижу неявное перекрытие абстрактного модуля и внедрение ненужной абстракции над модульной системой Node.js и не вижу преимуществ над:
// node_modules/request.js - node
var http = require('http'),
    abstractHttp = require('../lib/abstract-http');

// extends - как вариант наследования
module.exports = abstractHttp.extends({
    doRequest : function(params) {        
        return http.request(...);
    }
});

// js/request.js - browser
var $ = require('$'),
    abstractHttp = require('abstract-http');

module.exports = abstractHttp.extends({
    doRequest : function(params) {        
        return $.ajax(...);
    }
});

// index.js - common
var request = require('request');

request.get('http://ya.ru/').then(function () {

});

На клиенте все пути до модулей разруливаются конфигами, их наследованием и зависимостями модулей, в node все автоматом.
Есть такая штука как поддерживаемость кода и
часто это бывает просто избыточно
и подобные мысли чаще ведут к не поддерживаемому коду и мыслям: «А давай ка я просто проманкипатчу, зачем писать абстракцию?!»
Пример чего именно ты хочешь чтобы я привел?
Пример реализации интерфейса http под ноду и браузер, учитывая поддерживаемость и переносимость кода.
Так гораздо естественней
http монжо так или иначе абстрагировать реально естественными способами вроде заводов или наследования. (Естественными=Привычными способами) Манкипатчинг exports модуля это какаое-то не привычное для разработчика поведение. Эту особенность тянут за собой уровни переопределения BEM?

Покажи, пожалуйста, пример, а то я не пойму в чем удобство.
Технически все ресурсы мы забираем по HTTP и все они текстовые — тут не поспоришь. Логически же мы их все-таки разделяем на скрипты, css, json и пр. по тем или иным признакам. Так же, я думаю, следует и различать модули и данные. И использовать для них разные «загрузчики».
Ага, аналогично и у меня с картами и DOMContentLoaded

Information

Rating
Does not participate
Location
Berlin, Berlin, Германия
Registered
Activity