Обновить
16K+
48
Alex Gusev@flancer

Я кодирую, потому что я кодирую…

3,1
Рейтинг
99
Подписчики
Отправить сообщение

С того, что 99% пользователей не занимаются сборкой проектов - они потребляют уже результат сборки (например, JS-код в браузере). Или вы только разработчиков за пользователей считаете? Для них - да, для них время сборки - проблема.

Поглядел на фото Альтмана в посте и почему-то вспомнил эту женщину в контексте вашего комментария.

Ну ладно, хоть про норвежцев с индусами не оспариваете :)

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

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

Рулят те, кто понимает, как работает механизм, который совершенствовался веками и всё ещё продолжает совершенствоваться. Я не говорю, что я понимаю как он работает. Я говорю, что механизм, работавший веками, не сломается в одночасье. А то, что он порочен, лишь наше собственное отражение. Каждый из нас добродетелен без меры, а к власти приходят сплошь порочные. Может какая-то из добродетелей у нас лишняя?

Если не может торговать, оно становится суверенным и тоже нищает.

Общество планеты Земля не может торговать с другими планетами. Оно суверенно, но не нищает.

Если общество не может накапливать богатства, оно не может богатеть.

С этим согласен полностью. Но на интеллектуальный прорыв эта мысль не тянет.

главной движущей силой прогресса является накопление и торговля

А я бы назвал "созидание и обмен". Но я не Дарвин и даже не Ливингстон :)

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

Так что - да, локальный, потоковый Composition Root может иметь место в IoC.

Переспал я с этой мыслью и пришёл к следующему. Я разделяю у себя код на две большие группы: DTO и обработчики. DTO порождаются через фабрики (обработчики). Обработчики зависят от других обработчиков. Некоторые обработчики не имеют своего собственного внутреннего состояния для сохранения результатов работы (обработчики-функции), некоторые имеют (обработчики-объекты). Первые принимают на вход набор параметров, обрабатывают их (в том числе и с использованием обработчиков-зависимостей) и выдают результат. Вторые делают то же самое, но при этом изменяют своё внутреннее состояние (типичный пример - кэширование результатов обработки).

Так вот, когда у нас единый Composition Root у нас все обработчики-функции, зависящие от других обработчиков-функций, будут в приложении иметь жизненный цикл синглтон. Т.е., нам достаточно иметь по одному экземпляру таких обработчиков на всё приложение. Данные (в виде DTO) независимо двигаются по иерархии обработчиков и возвращаются в виде результата, нигде не оставляя следов.

В случае с обработчиками-объектами всё сложнее. Если это объект уровня приложения (например, кэширует в памяти обращения к файловой системе), то он тоже синглтон, а если уровня, например, обработки отдельного HTTP-запроса (потока вычислений), то это уже инстанс (порождается на поток).

Проблема в том, что набор зависимостей в конкретном обработчике (функции или объекте) - это по сути тоже состояние. Если все зависимости - функции, то все могут быть синглтонами. Но как только какая-то из зависимостей является объектом потокового уровня, то вся иерархия обработчиков, строящихся на этой зависимости должна пересоздаваться для каждого потока обработки (HttpContext <= Model <= Operation <= Service <= ...).

JavaScript асинхронный и однопоточный (если не считать worker'ов) и в рамках этого одного потока выполнения программы я не вижу особого смысла пересоздавать иерархию обработчиков на каждый поток обработки (HTTP-)запроса. Разумнее передавать обработчикам (функциям и объектам уровня приложения) контекст в качестве параметра (пусть это и не DTO, а FTO).

В worker'ах же Composition Root отдельный и независимый от Composition Root основного приложения. Таким образом, Composition Root всё равно должен быть один на поток выполнения (thread, worker) и никакой иерархии Composition Root'ов я там не вижу.

Т.е., вот здесь:

> (не)связанный с родительским Composition Root

нужно без скобочек: несвязанный. Я в курсе, что есть реализации, позволяющие строить иерархии Composition Roots, но в своей парадигме разработки ПО я считаю это ненужным.

Лично я использую аналог HttpContext"а для передачи объектов между обработчиками (контроллерами) - положил, взял. Но можно для каждого потока обработки инициировать пустой Composition Root (контейнер объектов или что там аналогичное для AC?), (не)связанный с родительским Composition Root и это уже будет IoC с возможностью создания новых объектов при необходимости. Тем не менее, возможность порождения объектов в таком контексте всё-таки должна быть, чтобы считаться IoC. Без такой возможности HttpContext слабо отличается по своим свойствам от какого-нибудь in-memory storage.

Так что - да, локальный, потоковый Composition Root может иметь место в IoC.

Насчёт того, что это контекст - согласен. Насчёт того, что это IoC - нет. Суть IoC - в передаче управления созданием объектов в программе в отдельное место (Composition Root). Различные части программы не создают сами нужные им зависимости, а получают их тем (инъекция) или иным способом (сервис-локатор) из этого места.

В случае с HttpContext и Thread.CurrentPrincipal я полагаю, что подобные объекты создаются не централизовано, а в местах обработки соответствующих запросов, после чего передаются в качестве параметра или свойства объекта.

Да, это похоже на Ambient Context, но не хватает глобальности, чтобы им быть. Два разных объекта HttpContext не пересекаются по своим свойствам и могут существовать в приложении одновременно (в nodejs могли бы).

По сути, коллега @Deosis прав: Ambietn Context - это такой Сервис Локатор, через который части программы имеют доступ к Composition Root (или к хранилищу результатов его работы). А если предположить, что в этот контекст может писать не только Composition Root, а вообще любая часть программы, то он прав и во второй части - "возвращает значение в зависимости от фазы луны".

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

Поэтому вопрос "зачем?" чертовски занимателен.

Так ведь опрос - это и есть практика, разве нет? Важно не то, "что скажет сообщество", важно то, какой процент ответивших использует IoC, какой из методов более популярен и насколько. Я так познаЮ мир. Например, после опроса по поводу используемой версии HTTP я пришёл к выводу, что значимость HTTP/2 мной довольно сильно преувеличена.

Сообщество могло вообще сказать, что ему всё равно, какой из двух методов IoC используется, потому что оно вообще не видит смысла в использовании IoC. Могло разделиться пополам между двумя методами. Могло перевесить в сторону AC. Каждый из этих результатов скорректировал бы моё дальнейшее движение. Нет, я бы не перелопатил свой код - слишком большая инерция у того, что уже есть. Но я бы точно изменил границы применимости своих решений.

К тому же периодическая ревизия основ помогает видеть новые направления для развития. Например, в процессе наших прений с коллегой Карловским мне пришла в голову мысль попробовать добавить в свой контейнер возможность "замораживания" создаваемых объектов by default. Но эту мысль ещё нужно хорошо подумать, есть у неё конфликты с тем, что уже есть.

Ну, например, представим, что вы во всем не правы.

Если мне докажут, что я во всём не прав, я всё буду делать по-другому. Какой смысл делать неправильно, верно?

У-упс... похоже, я её не поставил в саму статью. Исправил.

Я уверен, что принципиальные отличия одного метода от другого не зависят от особенностей их реализации. Первый раз я вашу статью я просматривал довольно давно ("перевёрнутую" машинку помню) и могу ответственно заявить: то, что там описано - это не DI.

Вам удобнее AC, мне - DI. Задачи они решают примерно одинаковые (IoC). Вы заявили, что "В хороших фреймворках IoC реализуют не через инъекцию, а неявно через контекст окружения".

Знаете, я и сам своего рода автор фреймворка
Знаете, я и сам своего рода автор фреймворка

У меня, конечно, есть некоторая профессиональная деформация - я так долго использовал DI в Java & PHP, что пришлось даже написать свой собственный контейнер, чтобы лично мне было удобно кодировать на JS. Но у меня нет и десятой доли вашей профессиональной самоуверенности, время от времени переходящей в наглость.

Заявлять же, что "в хороших фреймворках IoC реализуют неявно" - это наглость, переходящая в непрофессионализм. Ваша реализация IoC в вашем фреймворке размещает всё в globals и делает каждый объект доступным другим объектам. Я уже показал, как убивается ваш сайт с консоли браузера? Это же может сделать любой JS-код на странице.

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

Некоторые наши коллеги вообще считают Ambient Context антипаттерном, но я не стал этого выносить в текст публикации, чтобы не сильно деформировать мнения при опросе.

Я смотрю вы так и не прочитали мою статью, от чего ваши "аргументы" с цитатами великих и "каверзные" вопросы про тестирование и перфоманс выглядят особенно нелепо.

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

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

Я просто использовал вашу же терминологию "неявно через контекст окружения". Я не знаю, как у вас реализован ваш "контекст окружения", но каждый может увидеть результат этой реализации в global scope.

Я не утверждал, что "неявное лучше явного"

Верно, вы лишь утверждали что обосновали это:

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

Вообще-то globalThis является глобальным объектом. Каждый может вбить в браузере:

console.log(globalThis)

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

Также это предоставляет простой и удобный доступ к ко всем рантайм объектам из консоли, без необходимости шаманить с debugger в IIFE.

Согласен, можно было и просто вбить на page.hyoo.ru в консоли браузера

this

и увидеть то же самое:

Это одна из множества фишек для удобства дебага и рефакторинга, о которых вы даже не мечтали, а у нас уже 10 лет как есть.

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

К тому же вот этот простой код, введённый с консоли или любым сторонним кодом, убивает функциональность вашего фреймворка:

this.$mol_delegate = 32;

Проверить очень просто, достаточно войти на page.hyoo.ru, вбить в консоль эту строку и затем попытаться использовать поиск по сайту в правом верхнем углу:

В частности, освойте уже TypeScript. Бойлерплейт на JS без тайпчека в 2025 - это какой-то детский сад уже.

Мне пока что и в детском саду неплохо - свободы больше.

Ну, раз вы не знаете предмет, который мы тут с коллегой @nin-jin обсуждаем, то и разговаривать с вами в этом треде более не о чем. В Святом Писании вы явно лучше разбираетесь.

Эх, а я вам ещё пример кода приводил! Да вы же в нём не видите ничего! Для вас, что внедрение в конструктор, что контекст окружения - всё едино :(

Я нигде и никогда не утверждал, что код со скрина — эталон. Но пример (или несколько примеров) говнокода не могут ничего подтвердить (или опровергнуть).

Вы даже не поняли, что на скрине не код :(

Вот теперь думаю, зачем вы в профиль Steven van Deursen на гитхаб заходили. Что вы там увидеть собирались?

Я заранее согласен со всем тем, что вы скажете или подумаете.

Ладно, тогда вы обоснуйте чем неявное лучше явного вот в этом контексте:

В хороших фреймворках IoC реализуют не через инъекцию, а неявно через контекст окружения.

Я уверен, что вы относите себя к тому типу людей, "которые способны писать код и подтверждают это". Уверен, ваше обоснование с интересом прочтёт сам Карловский.

Только, пожалуйста, не сливайтесь, как он.

Всё, я убежал - у меня Масленица!! Завтра почитаю ваши формулировки.

Вы великолепны!!! Вам предлагают оценить идею и дают ссылку на её изложение, а вы копаете репутацию автора на гитхабе и при этом на серьёзных щах утверждаете "Источник тут вообще ни при чем"?! Так вам авторитетность источника важна или только разумность самой идеи? Давно я так не веселился. Спасибо!

Но пример (или несколько примеров) говнокода не могут ничего подтвердить (или опровергнуть).

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

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

Вы не можете утверждать авторитетность или релевантность источника, пока не ознакомитесь с содержимым. А вы с содержимым не ознакомились и сразу отвергли источник, как неавторитетный. Я дал вам возможность ознакомиться с идеей, ссылаясь на источник, в котором она изложена достаточно полно и достаточно ясно. Лошадь можно привести к водопою, но её нельзя заставить пить, если она не хочет.

Что будет, если вам в конструктор придется передать еще один параметр в связи с эволюцией бизнеса?

Это JS и фактически параметр конструктора там всего один (см. Unpacking properties from objects passed as a function parameter). Внутри него вы можете передавать хоть десяток вложенных параметров, хоть сотню. Сигнатура конструктора не изменится. Я могу добавлять или удалять параметры внутри объекта в конструкторе вызываемого кода и это никаким образом не повлияет на вызывающий код. Вообще никаким.

Бизнес-логика внутри вызываемого кода просто должна оценить наличие или отсутствие новых параметров или игнорировать deprecated. А вызывающий код не изменится вообще никак, ни в своём коде, ни в чужом. Если только, конечно, он не завязан на новые параметры. Но это уже неизбежная неизбежность.

А для меня слово разумное имеет вес чуть больше слова неразумного. Источник тут вообще ни при чем.

Для меня так-то тоже. Но вы же в источник даже не заглянули. Поэтому и разумность слова оценить не можете.

Вы согласны, что "явное лучше неявного", но вы не согласны, что в публичных дискуссиях можно ссылаться на внешние источники, подтверждающие мнение? Ну ОК, я понял вашу позицию.

Вы же видели вот этот скрин, да? Это та самая "комната, где нет ненужного бойлерплейта". И если среди этих объектов есть объекты с транзиентными зависимостями - удачи вам в дебаге при рефакторинге!!!

Я вам просто приведу свой фрагмент кода, где в явном виде прописаны все зависимости в конструкторе:

    /**
     * @param {Fl64_Otp_Back_Defaults} DEF
     * @param {TeqFw_Core_Shared_Api_Logger} logger
     * @param {TeqFw_Db_Back_App_TrxWrapper} trxWrapper
     * @param {Fl64_Otp_Back_Store_RDb_Repo_Token} repoToken
     */
    constructor(
        {
            Fl64_Otp_Back_Defaults$: DEF,
            TeqFw_Core_Shared_Api_Logger$$: logger,
            TeqFw_Db_Back_App_TrxWrapper$: trxWrapper,
            Fl64_Otp_Back_Store_RDb_Repo_Token$: repoToken,
        }
    ) {}

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

к каким-то книжкам, написанным хрен пойми кем 

Ну, так-то там и имена, и фамили указаны. Можете погуглить, кто эти "хрен пойми кто". Тиражи книжки найти можно. Критику изложенных в этих книжках идей. Ответы авторов на критику.

Я, например, сайтов наделал довольно много и в любой момент могу наделать ещё. Могу сделать сайт, на котором могу написать, что "яйцо правильно разбивать с тупого конца", а через дорогу сделать сайт, где напишу, что "яйцо нужно разбивать с острого конца". А потом редиректить вас на тот или иной сайт по настроению со словами - "Вот же! В интернете написано!!".

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

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

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

Я довольно плотно использовал IoC (DI в частности) и в Java, и в PHP. Сейчас использую в JS. Извините, не смог удержаться от комментария, когда увидел такой бред :)

Я не хвалюсь эрудицией, я слегка туповат, чтобы свободно владеть несколькими языками программирования одновременно. Сейчас я программирую на JS и уже почти забыл PHP и довольно сильно забыл Java. А уж всё, что вы сказали про хаскель, эрланг, атомы и всё остальное, для меня вообще "белый шум". Может с вами кто-то и подискутирет на эту тему, но не я :)

Я могу только про DI немножко, я там хоть что-то понимаю. По крайней мере, если бы я увидел обоснование, чем Ambient Context лучше Constructor Dependency Injection - я бы понял, что это оно, то самое обоснование.

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

Информация

В рейтинге
1 285-й
Откуда
Рига, Латвия, Латвия
Дата рождения
Зарегистрирован
Активность

Специализация

Фулстек разработчик
Ведущий
От 3 000 €
JavaScript
HTML
CSS
Node.js
Vue.js
Веб-разработка
Progressive Web Apps
PostgreSQL
MySQL
GitHub