Не ну вы представьте, какой ужас! Работник, отчужденный и от результатов своего труда и от прибыли за эти результаты не хочет по 26 часов в сутки с экстази-энтузиазмом вкалывать на капиталиста! А вы какого результата-то ожидали?
Любезнейший, напраслину на себя возводите. Прогуляйтесь, подышите свежим воздухом.
Как говаривала моя преподавательница органической химии "Дима, Вы такой умный, почему Вы такой ленивый?". На что я молчал и думал про себя "потому что могу себе это позволить" :)
Просто решите что для вас на самом деле важно и гребите в эту сторону. Все фуры на трассе Москва-Владивосток не обогнать :)
Обычно классическая схема богатых франшиз — «я (франчайзи-овнер) добился всего сам, а вы (соинвесторы, покупатели фрнашизы и прочие вложившиеся баблом в бизнес) — просто ленивые и криворукие, поэтому вам не фортануло и я ухожу от вас (с вашими деньгами)». Примеров мильён :)
Да я вот так тоже нашему PM говорил, а он что-то там про сроки, заказчиков и контракты талдычит :)
Лучший код — это понятный любому, который делает то что надо и не делает того, чего не надо. И отгруженный вовремя.
Загрузка модулей в ноде — операция синхронная и блокирующая.
Да, синхронная, нет, не блокирующая. Она начинает проходить по дереву зависимостей и тому, что недорезолвилось — ставит флаг. Именно поэтому в принципе возможны циркулярные зависимости (хоть они и зло). Кроме того новая реализация, которая ES6 modules import — вообще асинхронная.
У вас в примерах уже есть строчка antiniteSys.ensureAllIsReady(), можно старт процесса повесить на этот вызов.
Нет, `.ensureAllIsReady()` это проверка, которая в случае фейла бросает эксепшен. Потому что лучше совсем не взлететь, чем взлететь непонятно на чем, в смысле что не все разрезолвилось.
Или на первый вызов execute если почему-то решили ensureAllIsReady не вызывать.
Некрасиво.
Если вопрос стоит так — сделать что-то сложно выглядящее по-простому или что-то просто выглядящее, но сложное внутри — ИМХО нужно выбирать последнее.
Какая, в сущности разница, как устроен черный ящик, если он работает как надо?
Те сообщения об ошибках, который я предлагаю выкинуть — никогда не будут происходить в принципе.
Да. Но, в теории, они могут появится при внесении изменений. Поэтому моя практика подсказывает проверять то, что может упасть, даже если пока оно падать в общем-то не должно.
Ваша задача прекрасно решается в два этапа: сначала — экспорт всех экшенов, потом связывание и импорт, никаких промежуточных состояний вида «половина сервисов еще не зарезолвились, а остальные нужно использовать» при этом не будет — а значит, и не будет связанных с этим ошибок.
Сложность в том что этих этапов нет, оно начинает разрешаться при импорте домена и как-то там себе разрешается или нет, новый импорт домена — новый цикл разрешений с учетом «ждущих» зависимостей. И если вы 100% уверены что дерево зависимостей корректно и нет асинхронных инициализаций — не нужно даже дожидаться `. onReady()`. Для введения этапов придется жестко задавать момент старта всего процесса, что выглядит не так изящно, и я сейчас не уверен что это сработает всегда. При написании проекта я ориентировался на нативный стиль того, как нода поступает с разрешением зависимостей.
Но мысли интересные, я подумаю.
Спасибо за ваш интерес к коду и приведеные примеры, но я не уверен в корректности его поведения. Если проект Вас заинтересовал — приглашаю присоединится на github. Я всегда очень лоялен к мердж-реквестам, проходящим тесты и соблюдающим стилистику кода, благо standart — очень простой стиль.
Ох, немного неудобно так код обсуждать, в отрыве от него самого.
Но давайте попробую общё — во-первых я не могу себе позволить упрощать код, выкидывая сообщение об ошибках. А так как у нас много ленивых вычислений — верить нельзя никому.
Например — нельзя упросить `proxyUpcomingExecute`, потому что в момент его бинда к `doRequireCall` вполне возможно что `grantedItem.layer` просто отсутствует.
И так много где.
И это мы еще не вспоминаем об асинхронной инициализации сервисов.
Не совсем понимаю вопрос.
Если он в том «почему не все со всеми» — так это и не нужно и неудобно будет, здесь четкое понимание зависимостей прямо в конфигурации видно.
Если «динамическое разрешение доступа» — то по факту-то оно как раз статическое, при сборке всех зависимостей и разрешается.
Надо же, примерно в это время я и писал свой Antinite, а коллеги с хабра говорят «нечего выкладывать такое в интернеты, забирай обратно».
Ведь перспективная тема же?
Ваша статья очень полезна, помогла разобраться в понятиях.
Получилось красиво, не спорю.
Но у Вас сервис-потребитель ограничивает себя сам, а у меня сервис-поставщик и домен, в рамках которого он (поставщик) заявлен, контролирует доступность ресурса. Т.е. никто не берет чужого не потому что все честные, а потому что замок висит. В этом вся разница.
так? Если не брать совсем экстремальные варианты то вроде бы так. А значит при необходимости сделать тест нашего Foo нам надо на минуточку — найти что за объекты пробрасываются в конструктор (а если это довольно далеко от корня — могут быть нюансы), далее — найти методы этих зависимостей, которые используются (по всему коду), далее — сделать на них моки.
Или, используя велосипед — просто посмотреть в перечисление require и дать именно те методы, которые там перечислены. Все! Больше никаких зависимостей у класса нет и быть не может.
Статически объявленная гранулярность зависимостей на уровне методов.
Нет, не нужно? Точно?
Если у вас большой размер кода и нужно грамотно разделять зоны ответственностей модулей, то самое время внедрить Typescript, а не устраивать валидацию в рантайме.
Вероятно я плохо себе представляю возможности Typescript. Каким образом в нем можно разделить видимость методов, кроме как написав кучу оберток интерфейсов?
Про Proxy: во-первых, это уже часть стандарта языка, поддерживается в stable версии Node. Во-вторых, несмотря на использование Proxy, код остаётся типизированным и предсказуемым. В нем всегда можно проследить где метод декларируется и где вызывается. А в вашем подходе найти концы не представляется возможным
И что нам дает типизированность кода в вопросе доступа к методам? И видимо у меня не получилось донести идеи. Первое — концы конечно же можно найти — система в любой момент может отдать граф зависимостей. Приспособить его к тому же Atom — дело техники. Далее — приведенная Вами библиотека — классический вариант DI, разве что с TS интерфейсами, которые существуют только до момента транспилинга. И сам автор указывает на то, что извлечь из контейнера объект следует в самом верху дерева, после чего приходится носиться с этим объектом как с писаной торбой и прокидывать его дальше вглубь. Или прокинуть контейнер и получить -500 к карме. В этом отношении даже древнючий intravenous и то лучше, правда с ним мы так же в итоге не понимаем что откуда берется и что куда девается.
Интерфейсы, контракты — что-то такое слышали, но в JS, уж если у нас как-то получен объект — то ВСЕ его методы доступны. Все варианты сделать методы как бы приватными — черная магия чистой воды.
А как ограничиваеся использование в вашем решении?
Пример маловат, из него не все очевидно, мой просчет.
Все методы, объявленные в `export` конечно же будут доступны компонентам, которые имеют на это права. Но! Обычно объект имеет и приватные методы, которые используются для вынесения кода в аккуратные логичные сущности. И как мы помним, приватны они только на уровне договоренности (см первый абзац ответа). В случае использования Antinite экспортируется ТОЛЬКО то, что описано в экспорте. К приватным методам (не объявленным в экспорте) доступа нет. Вообще нет. Совсем. Никак.
Ровно как у компонентов с правами на методы уровня «чтение» не будет доступа к методам других уровней. Совсем.
И да, библиотека патчит исходные объекты. Потому что она ими владеет по праву использования. Как по мне — грех тянущий максимум на написание хорошего комментария ошибки.
Советую посмотреть на Typescript и библиотеки вроде InversifyJS.
Что именно в Typescript позволяет реализовать хотя бы DI? В Typescript есть что-то для контроля доступа к синглтонам? Аудит их использования?
InversifyJS — забавная вещица, но вот вы мне патчить исходные объекты запрещаете, а там во весь рост Proxy используются, которы мало того что пока в драфте, так еще и, положа руку на сердце, делают тоже самое, по сути.
Ухх! Какая дикая дичь! Это — в походы! Собрать умника, который это написал, в ПВД2Д со всей этой ерундой, для прочищения чакр.
Если кому то действительно внезапно стала интересна тема походов и он хотел бы узнать по снаряге — есть мультибренд, человек-параход и просто отличный малый Денис Доропей. Есть вдумчивый зануда-профессионал Комбриг. Есть просветленный Леопард Фил, экстремал, но пишет отлично. Есть общие советы от всяких инет магазинов, типа Спорт-Марафона. Много всего есть и по снаряге и по подготовке походов в сети, но вот эта рекламная фигня — это треш, угар и содомия!
Одна из немногих приличных вещей тут- палатка, но ультралайт силиконка не для начинающих! А все остальное а большей своей массе — блестящее барахло. Отложите денежку для нормального снаряжения. Или сходите в платный ПВД, за 2-3 штуки вам выдадут и спальное место и еды, идти можно хоть с городским рюкзаком.
Вот простите, не содержался прям! Сбор рюкзака, тоже мне!
Ох. Вы только не обижайтесь, идея здравая, но её качество вам бы подкачать.
var workerCount = require('os').cpus().length;
не делайте так, процы с гипертрейдингом (или как там называется эта маркетинговая шляпа) наивно отдают х2 ядер, что по факто вранье и толком не работает. Вынесите в конфиг.
Статус 999 — детский сад. Есть rfc на статусы ответов, возьмите подходящий код.
Забудьте про синхронные вызовы. ИМХО их использование нельзя оправдать ничем. Ну разве что эмм. невысоким уровнем разработчика. Очень невысоким.
Забудьте про global. Или реквайрте явно, или передавайте параметром. Глобали вообще нет оправданий, даже если это написал Ризинг. Но он так не сделает.
Именование функций местами сбивает с толку. Не пишут ok, пишут isOk, ибо булен-флаг.
И последнее (на что у меня хватило сил) — реквайр ноды устроен хитро и конечно же кеширует последующие require, но идея делать его на каждый запрос вызывает оторопь.
А чего могли хотеть эти "ГУ МВД"? Мне такие как-то звонили, но у меня совещание было, и я
послал их на хренвежливо завершил разговор.Не ну вы представьте, какой ужас! Работник, отчужденный и от результатов своего труда и от прибыли за эти результаты не хочет по 26 часов в сутки с экстази-энтузиазмом вкалывать на капиталиста! А вы какого результата-то ожидали?
Любезнейший, напраслину на себя возводите. Прогуляйтесь, подышите свежим воздухом.
Как говаривала моя преподавательница органической химии "Дима, Вы такой умный, почему Вы такой ленивый?". На что я молчал и думал про себя "потому что могу себе это позволить" :)
Просто решите что для вас на самом деле важно и гребите в эту сторону. Все фуры на трассе Москва-Владивосток не обогнать :)
Кажется тут тот самый случай, когда HR-отделу срочно нужны IT-санитары :)
Лучший код — это понятный любому, который делает то что надо и не делает того, чего не надо. И отгруженный вовремя.
Да, синхронная, нет, не блокирующая. Она начинает проходить по дереву зависимостей и тому, что недорезолвилось — ставит флаг. Именно поэтому в принципе возможны циркулярные зависимости (хоть они и зло). Кроме того новая реализация, которая ES6 modules import — вообще асинхронная.
Нет, `.ensureAllIsReady()` это проверка, которая в случае фейла бросает эксепшен. Потому что лучше совсем не взлететь, чем взлететь непонятно на чем, в смысле что не все разрезолвилось.
Некрасиво.
Если вопрос стоит так — сделать что-то сложно выглядящее по-простому или что-то просто выглядящее, но сложное внутри — ИМХО нужно выбирать последнее.
Какая, в сущности разница, как устроен черный ящик, если он работает как надо?
Да. Но, в теории, они могут появится при внесении изменений. Поэтому моя практика подсказывает проверять то, что может упасть, даже если пока оно падать в общем-то не должно.
Сложность в том что этих этапов нет, оно начинает разрешаться при импорте домена и как-то там себе разрешается или нет, новый импорт домена — новый цикл разрешений с учетом «ждущих» зависимостей. И если вы 100% уверены что дерево зависимостей корректно и нет асинхронных инициализаций — не нужно даже дожидаться `. onReady()`. Для введения этапов придется жестко задавать момент старта всего процесса, что выглядит не так изящно, и я сейчас не уверен что это сработает всегда. При написании проекта я ориентировался на нативный стиль того, как нода поступает с разрешением зависимостей.
Но мысли интересные, я подумаю.
Но давайте попробую общё — во-первых я не могу себе позволить упрощать код, выкидывая сообщение об ошибках. А так как у нас много ленивых вычислений — верить нельзя никому.
Например — нельзя упросить `proxyUpcomingExecute`, потому что в момент его бинда к `doRequireCall` вполне возможно что `grantedItem.layer` просто отсутствует.
И так много где.
И это мы еще не вспоминаем об асинхронной инициализации сервисов.
Если он в том «почему не все со всеми» — так это и не нужно и неудобно будет, здесь четкое понимание зависимостей прямо в конфигурации видно.
Если «динамическое разрешение доступа» — то по факту-то оно как раз статическое, при сборке всех зависимостей и разрешается.
Ведь перспективная тема же?
Ваша статья очень полезна, помогла разобраться в понятиях.
Ну и да, что-то по вашему получается «не читал, но осуждаю». Почитайте, бывает интересно.
Но у Вас сервис-потребитель ограничивает себя сам, а у меня сервис-поставщик и домен, в рамках которого он (поставщик) заявлен, контролирует доступность ресурса. Т.е. никто не берет чужого не потому что все честные, а потому что замок висит. В этом вся разница.
Давайте зайдем все же рассмотрим вариант интеграции с DI.
В любом варианте мы в итоге имеем что-то типа
так? Если не брать совсем экстремальные варианты то вроде бы так. А значит при необходимости сделать тест нашего Foo нам надо на минуточку — найти что за объекты пробрасываются в конструктор (а если это довольно далеко от корня — могут быть нюансы), далее — найти методы этих зависимостей, которые используются (по всему коду), далее — сделать на них моки.
Или, используя велосипед — просто посмотреть в перечисление require и дать именно те методы, которые там перечислены. Все! Больше никаких зависимостей у класса нет и быть не может.
Статически объявленная гранулярность зависимостей на уровне методов.
Нет, не нужно? Точно?
Вероятно я плохо себе представляю возможности Typescript. Каким образом в нем можно разделить видимость методов, кроме как написав кучу оберток интерфейсов?
И что нам дает типизированность кода в вопросе доступа к методам? И видимо у меня не получилось донести идеи. Первое — концы конечно же можно найти — система в любой момент может отдать граф зависимостей. Приспособить его к тому же Atom — дело техники. Далее — приведенная Вами библиотека — классический вариант DI, разве что с TS интерфейсами, которые существуют только до момента транспилинга. И сам автор указывает на то, что извлечь из контейнера объект следует в самом верху дерева, после чего приходится носиться с этим объектом как с писаной торбой и прокидывать его дальше вглубь. Или прокинуть контейнер и получить -500 к карме. В этом отношении даже древнючий intravenous и то лучше, правда с ним мы так же в итоге не понимаем что откуда берется и что куда девается.
Пример маловат, из него не все очевидно, мой просчет.
Все методы, объявленные в `export` конечно же будут доступны компонентам, которые имеют на это права. Но! Обычно объект имеет и приватные методы, которые используются для вынесения кода в аккуратные логичные сущности. И как мы помним, приватны они только на уровне договоренности (см первый абзац ответа). В случае использования Antinite экспортируется ТОЛЬКО то, что описано в экспорте. К приватным методам (не объявленным в экспорте) доступа нет. Вообще нет. Совсем. Никак.
Ровно как у компонентов с правами на методы уровня «чтение» не будет доступа к методам других уровней. Совсем.
И да, библиотека патчит исходные объекты. Потому что она ими владеет по праву использования. Как по мне — грех тянущий максимум на написание хорошего комментария ошибки.
Что именно в Typescript позволяет реализовать хотя бы DI? В Typescript есть что-то для контроля доступа к синглтонам? Аудит их использования?
InversifyJS — забавная вещица, но вот вы мне патчить исходные объекты запрещаете, а там во весь рост Proxy используются, которы мало того что пока в драфте, так еще и, положа руку на сердце, делают тоже самое, по сути.
Если кому то действительно внезапно стала интересна тема походов и он хотел бы узнать по снаряге — есть мультибренд, человек-параход и просто отличный малый Денис Доропей. Есть вдумчивый зануда-профессионал Комбриг. Есть просветленный Леопард Фил, экстремал, но пишет отлично. Есть общие советы от всяких инет магазинов, типа Спорт-Марафона. Много всего есть и по снаряге и по подготовке походов в сети, но вот эта рекламная фигня — это треш, угар и содомия!
Одна из немногих приличных вещей тут- палатка, но ультралайт силиконка не для начинающих! А все остальное а большей своей массе — блестящее барахло. Отложите денежку для нормального снаряжения. Или сходите в платный ПВД, за 2-3 штуки вам выдадут и спальное место и еды, идти можно хоть с городским рюкзаком.
Вот простите, не содержался прям! Сбор рюкзака, тоже мне!
не делайте так, процы с гипертрейдингом (или как там называется эта маркетинговая шляпа) наивно отдают х2 ядер, что по факто вранье и толком не работает. Вынесите в конфиг.
Статус 999 — детский сад. Есть rfc на статусы ответов, возьмите подходящий код.
Забудьте про синхронные вызовы. ИМХО их использование нельзя оправдать ничем. Ну разве что эмм. невысоким уровнем разработчика. Очень невысоким.
Забудьте про global. Или реквайрте явно, или передавайте параметром. Глобали вообще нет оправданий, даже если это написал Ризинг. Но он так не сделает.
Именование функций местами сбивает с толку. Не пишут ok, пишут isOk, ибо булен-флаг.
И последнее (на что у меня хватило сил) — реквайр ноды устроен хитро и конечно же кеширует последующие require, но идея делать его на каждый запрос вызывает оторопь.
В общем у вас есть место для улучшений.